Skip to content

📜 Version 4.x History

[v4.1.0] - 2026-09-04

🚀 Key Highlights & Architectural Enhancements

Tempo v4.1.0 expands enterprise configuration governance and developer ergonomics with Remote & Cascading Configuration Resolution ("extends"), a dedicated pluginOptions Configuration Slot, and Overloaded Tempo.create() with Deterministic Resource Disposal (TC39 using).


🌟 New Features & Improvements

1. Remote & Cascading Configuration Resolution (resolveConfig)

  • Remote URL Config Fetching: Enhanced resolveConfig() and Tempo.bootstrap() to fetch tempo.config.jsonc and tempo.config.json over http:// and https:// URLs (including http://localhost:... or http://127.0.0.1:... for dev servers, container environments, and central governance APIs).
  • file:// URL Support: Added native support for file:// URLs in Node.js environments via fileURLToPath.
  • Cascading Inheritance ("extends"): Introduced recursive "extends" resolution in configuration files (string URL/path or array of URLs/paths). Parent configurations are resolved and merged under child local overrides.
  • Security Boundaries & Loop Protection: HTTP requests are bounded by a 3-second timeout and 128KB payload size cap to prevent hangs and DoS attacks. Remote configs are restricted to static data-only JSON/JSONC payloads. Circular inheritance is detected and prevented.

2. Dedicated pluginOptions Configuration Slot

  • Introduced pluginOptions?: Record<string, any> across BaseOptions, Discovery, and Config.
  • Enforces clean architectural separation:
    • plugins: Strictly reserved for executable code registration (plugins, terms, modules).
    • pluginOptions: Dedicated dictionary holding serializable runtime options and defaults for plugins.
  • Deep, recursive namespace merging across extends inheritance layers.
  • Supplying plain configuration dictionaries directly under plugins is marked @deprecated in favor of pluginOptions.

3. Overloaded Tempo.create() & Deterministic Resource Disposal

  • Explicit Resource Management (TC39 using): Tempo.create() returns SandboxTempo subclasses that implement the TC39 Disposable protocol (Symbol.dispose) and expose an isDisposed getter. Disposing a sandbox clears its discovery slot from globalThis and cleans up internal registry state (ClassStates).
  • Scoped Callback Mode (Tempo.create(fn) / Tempo.create(options, fn)): Overloaded Tempo.create() to accept an execution callback, automatically disposing the ephemeral sandbox upon completion (supporting both synchronous results and async Promises via try...finally).
  • Native using Block Scoping: Full support for TypeScript 5.2+ block-scoped disposable sandboxes: { using sb = Tempo.create({ ... }); ... }.

4. Architectural Separation of extends and plugins

  • extends: Strictly reserved for configuration inheritance via URLs or file paths (string | string[]), mirroring tsconfig.json and ESLint conventions.
  • plugins: Dedicated for registering executable plugins and terms ((Plugin | Term)[]).
  • Tempo.use() & Deprecation of Tempo.extend(): Standardized Tempo.use(...) as the runtime registration method. Marked Tempo.extend() as @deprecated Use Tempo.use(...) instead. while preserving backwards compatibility.

🐛 Bug Fixes

  • Sandbox Symbol.dispose Global State Leakage: Fixed a critical bug where invoking [Symbol.dispose]() on a sandbox class (e.g., via the TC39 using keyword or scoped callback mode) inherited Tempo[Symbol.dispose]() via the prototype chain and inadvertently executed Tempo.init(), wiping the global library configuration and registered plugins. Sandboxed classes now implement an isolated [Symbol.dispose]() that strictly cleans up local sandbox state and discovery slots without mutating global defaults.

[v4.0.0] - 2026-08-27

🚀 Key Highlights & Paradigm Shifts

Tempo v4.0.0 is a major architectural milestone introducing Dynamic Functional Context (DFC), a 100% Open-Source Community Core, zero-await Synchronous JSONC Config Discovery, standardized Plugin SDK Facade, and unified {Term: Value} Mutation Payloads.


🚨 Major Breaking Changes

  • 100% Open-Source Community Core: Completely removed commercial licensing enforcement, JWT verification, JWS claims validation, domain-locking, and premium plugin gating (license.manager.ts, license.validator.ts, Tempo.license, #formatLicense, #isBlocked, validateLicenseState, LICENSE enum, $updateScopeStatus, and #tempo/license export subpath).
  • Commercial Package Decoupling: Relocated all enterprise licensing hooks and commercial plugin management to the @magmacomputing/tempo-pro wrapper package.
  • Config Auto-Discovery Modernization: Dropped .cjs configuration discovery support in favor of modern ES-preferred module extensions (.mts, .ts, .mjs, .js, .jsonc, .json).
  • Tempo.ready() Return Signature: Simplified Tempo.ready() return value to a static 'none' status for community core compatibility.
  • Configuration Namespace Enforcement: Fully excised legacy root-level property access that was deprecated during v3.x.
    • formats configuration key has been entirely removed from top-level Options and Discovery. Use registry: { formats: ... } instead.
    • numbers configuration key has been entirely removed from top-level Options. Use registry: { numbers: ... } instead.

🌟 New Features & Architectural Modernizations

1. Dynamic Functional Context (DFC) & Options Evaluation

  • Upgraded BaseOptions and Tempo options (timeZone, locale, calendar, sphere) to support Evaluable<T> suppliers (T | (() => T)).
  • Context options are dynamically evaluated on a per-request basis without requiring instantiation or re-building configuration state, perfect for multi-tenant applications (e.g., dynamic request headers or per-tenant session resolvers).

2. Synchronous JSON & JSONC Config Discovery (resolveConfigSync)

  • Introduced zero-await static startup configuration discovery (resolveConfigSync()) utilizing parseJSONC for .jsonc and .json files.
  • ESM and TypeScript config modules (.mts, .ts, .mjs, .js) continue to utilize the asynchronous resolveConfig() path.
  • Automatically executed inside Tempo's static { ... } initialization block at module load time.

3. Standardized Plugin SDK Facade (@magmacomputing/tempo/plugin/sdk)

  • Standardized plugin development on @magmacomputing/tempo/plugin/sdk, replacing legacy plugin-api imports.
  • Exposes definePlugin, defineTerm, defineModule, defineNamespace, defineRange, and internal evaluation utilities via a single, CDN-friendly facade.

4. Expanded Utility Stack Exports (@magmacomputing/tempo/library)

  • Re-exported core evaluation and runtime primitives (Evaluable, AsyncEvaluable, evaluate, evaluateAsync, evaluateConfig, evaluateConfigAsync, dynamicProxy, Pledge, cipher, webToken, enumify) from the #library surface for downstream plugins and custom extensions.

5. API Standardization for Boundary & Mutation Payloads ({Term: Value})

  • Standardized mutation object signatures across .set(), .add(), and plugin payloads to follow the unified {Term: Value} pattern (e.g., .set({ year: 'start' }), .set({ month: 'end' }), .set({ '#qtr': 1 })).
  • Legacy positional syntax (e.g., .set({ start: 'year' })) remains supported transparently for backwards compatibility.

🗑️ API Removals & Cleanups

  • Removed Static Accessors: Removed Tempo.formats accessor; use Tempo.registry.formats instead.
  • Removed Deprecated Subpaths: Removed #tempo/license export mapping.

Released under the MIT License.