diff --git a/package-lock.json b/package-lock.json index fc620d2..385ff7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tempo-monorepo", - "version": "3.4.0", + "version": "3.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tempo-monorepo", - "version": "3.4.0", + "version": "3.5.1", "workspaces": [ "packages/*" ], @@ -10149,7 +10149,7 @@ }, "packages/library": { "name": "@magmacomputing/library", - "version": "3.4.0", + "version": "3.5.1", "license": "MIT", "dependencies": { "tslib": "^2.8.1" @@ -10160,7 +10160,7 @@ }, "packages/tempo": { "name": "@magmacomputing/tempo", - "version": "3.4.0", + "version": "3.5.2", "license": "MIT", "dependencies": { "tslib": "^2.8.1" diff --git a/package.json b/package.json index 483a4aa..e532b8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tempo-monorepo", - "version": "3.5.0", + "version": "3.5.1", "private": true, "engines": { "node": ">=20.0.0" diff --git a/packages/library/package.json b/packages/library/package.json index a7e24fe..e18e5c4 100644 --- a/packages/library/package.json +++ b/packages/library/package.json @@ -1,6 +1,6 @@ { "name": "@magmacomputing/library", - "version": "3.5.0", + "version": "3.5.1", "description": "Shared utility library for Tempo", "author": "Magma Computing Solutions", "license": "MIT", diff --git a/packages/tempo/CHANGELOG.md b/packages/tempo/CHANGELOG.md index 205a545..be609ae 100644 --- a/packages/tempo/CHANGELOG.md +++ b/packages/tempo/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.5.1] - 2026-06-28 + +### Fixed +- **Term Registration Resilience**: Hardened `Tempo.extend` with structural deduplication to safely ignore redundant registrations of identical core terms. This prevents edge-case term collisions (e.g., `qtr`) in mixed module-loader environments like Vitest where Node ESM and Vite may evaluate plugins multiple times. + ## [3.5.0] - 2026-06-28 ### Added diff --git a/packages/tempo/package.json b/packages/tempo/package.json index a01dffe..70b7e1c 100644 --- a/packages/tempo/package.json +++ b/packages/tempo/package.json @@ -1,6 +1,6 @@ { "name": "@magmacomputing/tempo", - "version": "3.5.0", + "version": "3.5.1", "engines": { "node": ">=20.0.0" }, diff --git a/packages/tempo/src/tempo.class.ts b/packages/tempo/src/tempo.class.ts index dda8535..16349a6 100644 --- a/packages/tempo/src/tempo.class.ts +++ b/packages/tempo/src/tempo.class.ts @@ -572,13 +572,25 @@ export class Tempo { if (Tempo._termMap.get(config.key) === config) return; if (Tempo._termMap.has(config.key)) { + const existing = Tempo._termMap.get(config.key); + const rangesMatch = JSON.stringify(existing?.ranges) === JSON.stringify(config.ranges); + if (existing?.scope === config.scope && existing?.description === config.description && rangesMatch) { + logDebug(`[Tempo#extend] Duplicate term registration ignored for key: "${config.key}"`, state.config); + return; + } logError(`[Tempo#extend] Term collision on key: "${config.key}". Registration aborted.`, state.config); return; } if (config.scope && Tempo._termMap.get(config.scope) === config) { /* continue */ } else if (config.scope && Tempo._termMap.has(config.scope)) { - logError(`[Tempo#extend] Term collision on scope: "${config.scope}". Registration aborted.`, state.config); - return; + const existingScope = Tempo._termMap.get(config.scope); + const rangesMatch = JSON.stringify(existingScope?.ranges) === JSON.stringify(config.ranges); + if (existingScope?.key === config.key && existingScope?.description === config.description && rangesMatch) { + /* continue */ + } else { + logError(`[Tempo#extend] Term collision on scope: "${config.scope}". Registration aborted.`, state.config); + return; + } } Tempo._termMap.set(config.key, config); @@ -596,13 +608,11 @@ export class Tempo { if (r.key) { let val: string | undefined; if (isDefined(r.hour)) { - if (Number.isInteger(r.hour) && r.hour >= 0 && r.hour <= 23) { + if (Number.isInteger(r.hour) && r.hour >= 0 && r.hour <= 23) val = `${r.hour}:${pad(r.minute ?? 0)}`; - } } else if (r.month) { - if (Number.isInteger(r.month) && r.month >= 1 && r.month <= 12) { + if (Number.isInteger(r.month) && r.month >= 1 && r.month <= 12) val = `${pad(r.day ?? 1)} ${monthKeys[r.month - 1]}`; - } } if (val) aliases.push([r.key, val]); diff --git a/packages/tempo/src/tempo.version.ts b/packages/tempo/src/tempo.version.ts index f3af59d..674c584 100644 --- a/packages/tempo/src/tempo.version.ts +++ b/packages/tempo/src/tempo.version.ts @@ -5,4 +5,4 @@ * ⚠️ This file is auto-updated by `npm run build:version` (see `bin/update-version.mjs`). * Do NOT edit manually — your changes will be overwritten on the next build. */ -export const TEMPO_VERSION = '3.5.0'; +export const TEMPO_VERSION = '3.5.1';