All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Grouped Configuration Options: Consolidated
monthDayandrelativeTimeoptions into nested objects. - Internal layout detection: Added
isMonthDaydetection for improved regional layout resolution. - CI Benchmarks: Added performance benchmarking suite to CI.
- Event Overrides: Fixed
$setEventslogic to correctly handle custom event overrides. - TimeZone Fallbacks: Improved and cleaned up the IANA TimeZone fallback list.
- Intl.Locale Debugging: Enhanced diagnostic logging for locale resolution.
- Standardized UTC Offsets: Added
normalizeUtcOffsetutility for transforming informal UTC-offset strings. - Custom Layout Order: Added
layoutOrderoption to customize parsing element precedence.
- Season Scope Simplification (Breaking): Removed Chinese-specific object from
term.seasonscope. - Refined TimeZone Normalization: Improved UTC offset handling during initialization.
- Layout Pattern Resolution: Fixed ordering to respect intended sequence.
- Sandbox Factory Mode: Introduced
Tempo.create(), a static factory method for creating isolatedTemposubclasses with independent configurations and registries. - Layout Order Resolver Module: Extracted layout-ordering decision logic into a dedicated
engine.layoutmodule. - Layout Controller Framework: Implemented minimal controller-map infrastructure for future input-class pre-filtering.
- Debug Layout Order Visibility: Added optional debug output in
Tempo.#swapLayoutto emit the resolved layout order for diagnostics.
- Internal Layout Resolution: Refactored
Tempo.#swapLayoutto delegate ordering to the external resolver. - Alias Precedence: User-defined
eventandperiodaliases now take precedence over built-in aliases. - Module Path Flattening: Relocated core modules to
src/module/for a flatter, more intuitive internal architecture.
- Determinism Coverage: Added comprehensive unit tests for layout resolution and multi-pair swap handling.
Version 2.4.0 was not released; the project merged new functionality from 2.4.0 into 2.5.0.
- Standalone Parse Engine: Extracted the natural language engine into a standalone
parse()function for instance-free datetime resolution. - Noise Filtering: Added an
ignoreoption to strip irrelevant words during string parsing. - Backtracking Security: Implemented
Match.backtracksafety guards in the snippet registry. - Ecosystem Installation Guide: Released comprehensive installation instructions for Node.js, Deno, and standard browser environments.
- Automatic Context Sync: Hemisphere settings now automatically synchronize with timezone updates.
- State Optimization: Refactored the internal parser state machine for reduced memory usage.
- Interactive Playground: Enhanced the browser-based demo with live timezone selectors and real-time clock updates.
- Resolution Resilience: Hardened the resolution loop with safety valves to prevent infinite loops in extreme date ranges.
- Type Safety: Hardened TypeScript definitions for all
parseandtermresolution functions.
- Premium Browser Test Dashboard: Overhauled the browser-based test suite with a modern, glassmorphism-inspired UI featuring interactive feedback, live result streaming, and robust error visualization.
- Isomorphic Export Support: Enhanced the
dist/tempo.bundle.esm.jsto provide both a default export and a named{ Tempo }export, ensuring the exact same import syntax works seamlessly across Node.js and browser environments.
- Unified Import Syntax: Standardized all documentation and testing examples to use named imports (
import { Tempo } from '@magmacomputing/tempo'), eliminating environment-specific inconsistencies.
- JSBI Resolution: Explicitly added
jsbito all documentation import maps to resolve bare-specifier errors in@js-temporal/polyfillwhen running in strict browser environments. - Documentation Formatting: Corrected orphaned script blocks and added missing headers to the
Tempo.mdguide for better readability.
- Cross-Bundle Singleton Stability: Implemented a symbol-based brand check for
TempoRuntimeto ensure reliable singleton resolution even when multiple versions of the library are loaded.
- Consolidated Internal Storage: Merged redundant internal term/plugin arrays into a unified, validated
pluginsDbwithinTempoRuntime, reducing memory overhead and improving consistency. - Refined Year Semantics: Normalized the
yearcomponent in term templates to intelligently distinguish between relative offsets (e.g., year0) and absolute historical years (e.g., year2000). - Improved Type Safety: Introduced
MatchResultas a type alias forInternal.Matchto resolve naming conflicts with theMatchruntime class, while maintaining the publicMatchexport for backward compatibility.
- Term Resolution Accuracy: Fixed a sorting bug in the yearly-cycle resolution engine that caused incorrect anchor identification for non-calendar-ordered term groups (e.g., seasons).
- Documentation Integrity: Updated architecture and README guides to point to the correct
#tempo/supportmodule and provided functional, complete importmap examples for browser environments. - HTML Standards Compliance: Wrapped library demonstration and test pages in proper HTML5 skeletons to ensure consistent rendering and prevent quirks-mode issues.
- Package Optimization: Refined
sideEffectsinpackage.jsonto exclude non-published source files, improving tree-shaking for consumer builds.
- Ticker Redefinition: Added safety guards to
TickerModule.installto preventTypeError: Cannot redefine property: tickerwhen extending an already-initialized or@Immutableclass. - Granular ESM Resolution: Bundled
tslibinto granular ESM distribution files to resolve browser-side "Failed to resolve module specifier" errors. - Documentation Build: Resolved dead links in
Tempo.mdto ensure successful VitePress production builds. - Verification Dashboard: Synchronized the browser verification dashboard with current build artifacts and updated to
v2.2.4.
- Dual-Bundle Strategy: Modernized the Rollup configuration to produce both a "batteries-included" ESM bundle (
tempo.bundle.esm.js) and a classic IIFE bundle (tempo.bundle.js). - Global Export Map: Added
./bundle(ESM) and./global(IIFE) export mappings topackage.jsonfor better consumer clarity.
- Parsing Priority: Reordered
ParseEngine.resultvalidation to ensureisTempoinstances are converted toTemporal.ZonedDateTimebefore primitive-type validation occurs. - Registry Error Hints: Improved module-resolution error messages to suggest cleaner import specifiers (e.g.,
#tempo/parseinstead of#tempo/parsemodule).
- Version Synchronization: Unified versions across the monorepo root,
tempo, andlibrarypackages. - Test Infrastructure: Updated
vitest.workspace.tsand library configurations to use the renamedtemporal-polyfill.tssetup file.
- Live Documentation Links: Updated the package README to link directly to the live VitePress site.
- CI/CD Hardening: Resolved dependency resolution and build target issues in the GitHub Actions deployment pipeline.
- Modular Mutation Engine: Refactored
add()andset()into a standaloneMutateModule. While the public entry point remains "batteries-included," this refactor allows advanced users to import a slimmed-downTempocore and only opt-in to mutation logic as needed. - VitePress Documentation Site: Launched a comprehensive, searchable documentation platform with deep TypeDoc integration and interactive guides.
- Browser Distribution Dashboard: Introduced a unified verification suite at
/demo/index.htmlto validate ESM, IIFE, and modular distributions in real-time. - Enhanced Payload Validation: Implemented strict validation for Ticker payloads to prevent ambiguous mixing of directional and relative mutations.
- Semantic Event Update: Refactored
tomorrowandyesterdayto be instance-relative rather than system-anchored, providing more predictable behavior during complex temporal shifts. - Internal State Protection: Hardened the
[sym.$Internal]()accessor, making the underlyingzdtread-only to guarantee instance immutability.
- Arithmetic Precision: Resolved out-of-bounds access and floating-point indexing errors in term range resolution through floored cycle calculations.
- State Propagation: Fixed inconsistent
mutateDepthpropagation in error fallback paths, ensuring robust recursive protection. - Primitive Integrity: Corrected the
distinctutility to properly respect and bindthisArgduring mapping operations. - Redundant State Removal: Eliminated the unused global
STATEconstant from utilities to prevent potential cross-instance state leakage.
- VitePress Documentation: Launched a modern, searchable documentation site powered by VitePress and TypeDoc.
-
Proxy-Delegator Pattern: Refined the lazy-evaluation engine for
$O(1)$ property access. - Scan-and-Consume Guard: Implemented high-performance token matching for v2.1.2 stabilization.
-
Ticker Stability Guard: Implemented a 10,000-iteration safety break in
resolveTermShiftto prevent infinite loops when resolving malformed or non-advancing custom terms. -
Unified Diagnostics (
Logify): Integrated theLogifyutility into core internal classes. This provides a standardized mechanism fordebug,catch, andsilentmodes across the library.
- High-Precision Ticker: Migrated
TickerPluginfromDate.now()toinstant().epochMilliseconds, ensuring consistent use of high-precision timing without legacyDateobject dependencies. - Test Performance: Standardized the test suite on
vitest --pool=forksto ensure deterministic execution of asynchronous ticker and generator tests. - Vitest Upgrade Deferral: Intentionally deferred the upgrade to Vitest 4.x and maintained version
^2.1.8. The current Vitest 4 transformer (Oxc) does not yet support the Stage 3 (ECMAScript) decorators used extensively by this library's@ImmutableandLogifyutilities.
- Term Plugin Resolution: Corrected package export mappings for term-based plugins in
package.json, resolving module resolution errors in development and test environments. - Numeric Word Parsing: Fixed regressions in numeric word resolution (e.g., "eleven days hence") by ensuring registry synchronization during late-import scenarios.
-
Zero-Cost Constructor: Optimized the instantiation path to
$O(1)$ by deferring all parsing and property registration until the first property access. -
Generic Lazy Delegator: Introduced
getLazyDelegatorto standardize on-demand property discovery forfmtandtermobjects. -
Anchor-Aware Parsing: Added native support for anchoring relative date strings (e.g., "next Friday") to a specific reference date via the
anchoroption. -
Timezone Safety: Implemented graceful fallback to
UTC(with a warning) for invalid IANA TimeZone IDs whencatch: trueis enabled.
- Parsing Robustness: Resolved 299/299 regressions in the core and plugin test suites.
- Immutability Performance: Fixed
TypeErrorduring lazy discovery on secured instances by implementing defensive prototype-shadowing.
- Reactive Registration Hook (
$Register): Introduced a global reactive hook that allow plugins to automatically triggerTempo.init()if they are imported after the main library. This resolves several "late import" edge cases in complex bundle environments. - Strictly Typed Enums: Refactored
tempo.enum.tswith privateconstkey arrays, restoring 100% strict type inference (no moreany) while maintaining a clean, code-minimal declaration pattern. - Dynamic Registry Mapping: Implemented a centralized
REGISTRIESmap intempo.enum.ts, providing a single point of change for all discoverable registries (NUMBER,FORMAT,TIMEZONE, etc.).
-
Plugin Architecture Consolidation: Centralized all core registration logic, symbols ($Tempo, $Plugins, $Register), and factory methods (
definePlugin,defineTerm) into a single module atpackages/tempo/src/plugins/tempo.plugin.ts. -
API Consistency: Updated
Tempo.init()to returnthis(the static class instance) to better support fluent chaining patterns (e.g.,Tempo.init({...}).extend(...)). - Circular Dependency Resolution: Relocated term plugins and adopted a strict "import type" policy in the plugin layer to break core-plugin cycles and improve build stability.
- Type-Safe Discovery Symbols: Updated
BaseOptionsto natively supportsymbolas a discovery key, resolving "not assignable" errors across the test suite and production environments. - Ticker Plugin Typing: Resolved implicit
anyand reduction-type errors in the ticker plugin for better safety in strict mode. - Weekday/Month Alignment: Restored 1-based alignment (ISO 8601) for
WEEKDAYandMONTHenums by ensuringAll/Everydayplaceholders remain at index 0.
- Monorepo Migration: Successfully transitioned to a unified monorepo structure, naming
packages/tempoandpackages/libraryas npm workspaces. - Publishing Optimizations: Integrated
prepublishOnlybuild hooks andfileswhitelisting inpackage.jsonfor leaner and more reliable NPM distribution. - Enhanced Type Resolution: Fixed
nodetype definition errors in nested test environments by explicitly configuringtypeRoots.
- Dependency Rationalization: Consolidated
tsliband@js-temporal/polyfillat the project root while preservingtslibas a runtime dependency for published packages. - Plugin Loading Refactor: Refactored
static loadinto a unified, single-pass dispatch logic for handling Plugins, TermPlugins, and Discovery configurations robustly.
- Plugin System (
Tempo.load): Introduced a formal architecture for extending theTempoclass and prototype, allowing for modular feature injection (e.g.,TickerPlugin). - Auto-Plugin Discovery: Plugins can now be automatically loaded via the
pluginsconfiguration inTempo.init()or through the Global Discovery manifest (Symbol.for($Tempo)). - Selective Immobility: Enhanced the
@Immutabledecorator with a "Selective Immute" pattern. Core methods (including Symbols likeSymbol.dispose) are now write-protected, while the class remains extensible for new plugins. - Reactive Clock (Modularized): The
Tempo.tickerlogic has been extracted into an optional plugin available at@magmacomputing/tempo/plugins/ticker. This reduces core bundle size while offering high-performance Async Generators and countdown support. - Symbol Protection: Core identifiers are now safe from runtime hijacking, providing a robust security model for library consumers.
- Polyfill Decoupling: Moved the
TemporalAPI availability check to the coreTempoclass, allowing standalone utilities to run in environments withoutTemporal. - Type-Strict Reflection: Updated internal reflection tools to use
ownEntries()for cleaner property descriptor management. - Documentation Overhaul: Updated all technical guides to reflect the modular, plugin-based architecture.
- Numeric Pattern Inference: Corrected
FormatsandFormattypes to ensure numeric patterns (likeyearMonthDay) are correctly inferred asnumberwhile preserving enum-like functionality for the format registry. - Layout Patterns Guide: Created a new technical guide
doc/tempo.layout.mdfor describing Tempo services through custom layout/snippet building. - Enum Type Flexibility: Loosened TypeScript constraints on
enumifyobjects. Thecount()method now returns a standardnumber, and iteration callbacks (forEach,filter,map) now accept a genericEnum.wrap<any>, resolving assignability issues in complex configurations likeTempo.Config. - Custom Global Formats: Introduced support for defining custom format layouts via Global Discovery (
Symbol.for($Tempo)), making them available across all instances. - Type Safety Refinement: Significantly enhanced the
Tempoclass by removing redundantas anycasts, particularly in#parseand timezone handling, achieved through better destructuring and explicit string resolution. - Modern Syntax Adoption: Updated the codebase to use
Object.getOwn()instead of legacyObject.prototype.hasOwnProperty.call()for cleaner and more modern property checks.
-
Core Simplification ($Base Removal): Removed the
$Basesymbol and its termination logic fromreflection.library.ts. This simplifies prototype chain traversal across the library, as boundary protection is no longer required following theconfiggetter refactor and existing enumerable property filtering for Enums. -
Constant Modernization: Renamed and deprecated
Tempo.TIMEandTempo.TIMESin favor of more semanticTempo.DURATIONandTempo.DURATIONS, improving readability and consistency with internal logic. -
Enum Extension Optimization: Refactored
Enum.extendto support deep prototype chains (up to 50 levels) and fixed a critical boundary bug where root Enum data was being excluded from child extensions. -
Proxy Trap Performance: Optimized
toJSONand$Inspecttraps inproxifyto prevent unnecessary prototype chain traversal. The traps now prioritize checking for own properties, significantly improving performance and preventing recursion during serialization. -
Term Traversal Logic: Unified prototype traversal by introducing a shared
$Basesymbol to terminate chain climbing, improving both performance and collision resistance. -
Node.js Custom Inspection: Standardized the Node.js custom inspection symbol as
$Inspectin the reflection library and updatedTempoandEnumifyfor consistent console formatting. -
Stealth Proxy for terms: Implemented a "Stealth Proxy" for the
termaccessor to provide a flat, iterable object view of resolved terms across Node.js and Browser environments while preserving lazy resolution. -
Term Getters Performance: Refactored
#setTermlogic to use prototype shadowing (Object.create), improving performance and reducing overhead. -
Strict Global Discovery: Standardized the global configuration mechanism by removing legacy
TempoOptionssupport and strictly enforcing theTempo.Discoverycontract. -
Enumify Extend: Refactored the internal
extendutility withinenumifyfor improved maintainability. -
Parsing Reorganization: Adjusted the
#parsemethod to resolvetzandcalidentifiers after configuration updates, ensuring internal state always reflects the most current settings.
- Decorator Compatibility: Resolved nominal typing issues in
registerTermsby loosening internal constraints, enabling seamless synchronization with projects using Stage 3 decorators (likewhiteLibrary). - Enum Boundary Bug: Corrected the logic in
ownEntriesto ensure that root Enum entries (marked with$Base) are correctly collected during full-chain resolution. - Getter Handling in Extensions: Fixed a regression in
reflection.library.tswhere properties with getters were being incorrectly unwrapped; they are now accessed directly to ensure proper execution. - Timezone Round-trip Restoration: Fully resolved critical serialization regressions by updating
#setConfigto recursively handle theconfigproperty during revival. - Instance Timezone Integrity: Restored the safe update to
#local.config.timeZonein#parseZone, ensuring internal getters stay in sync with date-time strings without clobbering initial state. - String Handling Cleanup: Removed redundant
String()wraps in regex group parsing and mutation logic where types were already guaranteed.
toPlain...Methods: AddedtoPlainDate(),toPlainTime(), andtoPlainDateTime()helper methods to theTempoclass for easier extraction of specificTemporalcomponents.- Argument Flexibility: Enhanced
.set()and.add()to accept either a date-time payload or an options object as the first argument, improving developer ergonomics. - API Reference: Created
doc/tempo.api.md, a comprehensive technical guide covering all static and instance API entrypoints, signatures, and properties. - TypeScript Types: Created
doc/tempo.types.mdas a detailed reference for all core namespace types. - Regression Tests: Added
test/issue-fixes.test.tsto permanently cover relative events, timezone brackets, and storage precedence.
- Performance Optimization: Switched Vitest to
--pool=forksand refactored internal iteration in.set()and.add()to resolve test runner hangs during complex parsing. - Relative Events: Refactored
now,today,tomorrow, andyesterdayto be relative to the specificTempoinstance. Date-based events now usetoPlainDate()for improved parsing robustness. - Config Precedence: Established and documented a reliable precedence order: Metadata < Defaults < Storage < Discovery < Global Init < Instance.
- Config Privacy: Explicitly excluded the internal
anchorproperty from public configuration to prevent developer confusion. - Cleanup: Removed obsolete
rdt(recent date) snippet logic as it is fully superseded by smart event aliases (functions). - Storage Logic: Consolidated persistence merging into
#setConfig, ensuring storage values correctly act as defaults. toInstant/toDateTimeGetters: Enhanced getters to prioritize the instance's underlying value while providing robust fallbacks to system "now" (including safe handling of uninitialized timezones).
- Timezone Round-trip: Resolved a critical bug where timezone information was lost when reviving Tempo instances from JSON (serialization/deserialization).
- Timezone Bracket Parsing: Resolved an issue where bracketed timezones were ignored or incorrectly overridden by offsets.
- Mutation Safety: Fixed
TypeError: Cannot add propertyin#resultwhen performing operations on instances decorated with@Immutableby ensuring internal state is handled safely. - Relative Event Drifting: Fixed a bug where events like 'yesterday' were incorrectly calculated based on the run-date instead of the
Tempoinstance state. - Storage Merge Bug: Corrected an issue where explicit options were being clobbered by storage values.
- API Reference: Created
doc/tempo.api.md, a comprehensive technical guide covering all static and instance API entrypoints, signatures, and properties. - Node.js Support: Added explicit server-side usage instructions and code examples to
README.mdanddoc/Tempo.md. {wy}Token & Getter: Introduced the{wy}formatting token and a corresponding publicwygetter for the 4-digit ISO week-numbering year.
- Config Documentation: Refactored
doc/tempo.config.mdto follow technical precedence (Persistence > Discovery > Global > Instance). - Doc Cross-Linking: Standardized documentation navigation by converting all textual cross-references into clickable markdown links.
- Precision Glossaries: Refined documentation in
vision.mdandcomparison.mdto specify "meteorological seasons" and "zodiac signs". - Token Renaming: Renamed
{isoy}to{wy}across the library, tests, and documentation for improved semantic clarity.
- ISO Week Logic: Refined
wyandyywwformatting logic to correctly handle boundary cases between years. - Global Discovery Trace: Improved trace logging visibility when
debug: trueis enabled.
- GitHub Sponsors: Integrated
FUNDING.ymland added sponsorship links toREADME.md. - Commercial Support: Added
doc/commercial.mdoutlining consulting and priority support options. - Term Registration: Implemented a new functional registration system for
Tempo.termsto resolve circular dependencies.
- Config Architecture: Relocated
pivotproperty fromTempo.ConfigtoTempo.Parseto better align with its parsing-specific purpose. - Type Accessibility: Moved
TermPlugintype definition to the publicTemponamespace for easier external plugin development. - Initialization Logic: Updated
Tempo.init()to handle term registration and pivot defaults internally.
- Resolved circular dependency between
tempo.class.tsandterm.import.ts. - Standardized internal property access for
pivotusing thethis.#local.parse["pivot"]syntax.
- Initial public release refinements.
- Established documentation for vision and core features.