Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions bin/version-sync.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,25 @@ if (!version) {
console.log(`\n🔄 Syncing version ${version} to workspaces...`);

try {
execSync(
`npm version ${version} -w @magmacomputing/tempo -w @magmacomputing/library --no-git-tag-version`,
{ stdio: 'inherit' }
);
console.log(`✅ Version successfully synced to ${version} across workspaces!\n`);
const workspaces = ['@magmacomputing/tempo', '@magmacomputing/library'];
let syncedCount = 0;
for (const ws of workspaces) {
try {
execSync(`npm version ${version} -w ${ws} --no-git-tag-version`, { stdio: 'inherit' });
console.log(`✅ Synced ${ws} to ${version}`);
syncedCount++;
} catch (error) {
console.warn(`⚠️ Bypassed ${ws} (likely already at ${version} or not found). Error details:`, error);
}
}

if (syncedCount === 0) {
console.error(`\n✖ Sync failed: All workspaces were bypassed (already at ${version} or not found).`);
process.exit(1);
}

console.log(`\n🎉 Version sync complete!\n`);
Comment thread
magmacomputing marked this conversation as resolved.
} catch (error) {
console.error('Failed to sync versions.', error);
console.error('Fatal error during sync.', error);
process.exit(1);
}
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tempo-monorepo",
"version": "3.6.1",
"version": "3.7.0",
"private": true,
"engines": {
"node": ">=20.0.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/library/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@magmacomputing/library",
"version": "3.6.1",
"version": "3.7.0",
"description": "Shared utility library for Tempo",
"author": "Magma Computing Solutions",
"license": "MIT",
Expand Down
9 changes: 9 additions & 0 deletions packages/tempo/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ 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.7.0] - 2026-07-08

### Added
- **Runtime Versioning Registry**: Introduced a secure, static `Tempo.versions` registry. This provides zero-burden runtime observability of all loaded core modules and community plugins.
- **Automated Plugin Versioning**: Community plugins now automatically inject their version via a custom ESBuild virtual module pipeline, eliminating the need for magic strings. Internal bundled terms (like `QuarterTerm`) seamlessly inherit the core `TEMPO_VERSION`.

### Changed
- **Internal Privacy Modernization**: Refactored internal runtime registries (including `_termMap` and other internal configuration variables) to utilize strict ECMAScript private fields (`#`), ensuring complete architectural security against prototype tampering.

## [3.6.1] - 2026-07-06

### Fixed
Expand Down
10 changes: 10 additions & 0 deletions packages/tempo/doc/releases/v3.x.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# 📜 Version 3.x History

## [v3.7.0] - 2026-07-08

### ✨ What's New — Runtime Version Registry
Tempo now features a fully automated runtime version registry accessible via `Tempo.versions`. This allows developers to instantly query exactly which core modules, terms, and community plugins are loaded into their current Tempo environment and what versions they are running. This system is completely zero-burden for plugin authors, utilizing a virtual build pipeline to auto-inject version strings without requiring manual updates or magic strings.

### 🏗️ Internal Refactoring
- **Architectural Security**: The internal state management (including term registries and configuration variables) has been modernized to use true ECMAScript private fields (`#`), ensuring that Tempo's runtime state is strictly impenetrable from the outside.

---

## [v3.6.0] - 2026-07-05

### ✨ What's New — Shorthand Mutation Keys
Expand Down
2 changes: 1 addition & 1 deletion packages/tempo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@magmacomputing/tempo",
"version": "3.6.1",
"version": "3.7.0",
"engines": {
"node": ">=20.0.0"
},
Expand Down
5 changes: 3 additions & 2 deletions packages/tempo/src/module/module.format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { isString, isObject, isZonedDateTime, isInstant, isPlainDate, isPlainDat
import { formatDayPeriod, getDTF, getPR, getISOWeekOfYear } from '#library/international.library.js';
import { delegator } from '#library/proxy.library.js';

import { isTempo, enums, Match, getRuntime, NumericPattern, BigIntPattern, hasOwn } from '#tempo/support';
import { isTempo, enums, Match, getRuntime, NumericPattern, BigIntPattern, hasOwn, $Internal } from '#tempo/support';
import { defineInterpreterModule } from '../plugin/plugin.util.js';
import { findTermPlugin } from '../plugin/term/term.util.js';
import type { Tempo } from '../tempo.class.js';


Expand Down Expand Up @@ -277,7 +278,7 @@ export function format(obj?: any, fmt?: any, options?: any): any {
if (token.startsWith('#') && isTempo(obj)) {
const termKey = token.slice(1);
const termName = termKey.split('.')[0];
const plugin = (obj.constructor as any)._termMap?.get(termName);
const plugin = findTermPlugin(termName, (obj.constructor as any)[$Internal]());

if (plugin) {
const termVal = (obj as unknown as Tempo).term[termKey];
Expand Down
1 change: 1 addition & 0 deletions packages/tempo/src/plugin/plugin.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
export interface Plugin<T = any> {
name: string;
version?: string;
install: (this: T, t: T) => void;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/tempo/src/plugin/plugin.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ import { TempoError } from '../support/support.error.js';
import { getRuntime } from '../support/support.runtime.js';
import { hasOwn, logError } from '#tempo/support/support.util.js';
import type { Tempo } from '../tempo.class.js';
import type { Plugin, Module, Extension } from './plugin.type.js';
import type { Plugin, Module } from './plugin.type.js';
import { TEMPO_VERSION } from '../tempo.version.js';

export type TempoType = typeof Tempo;
export type TempoPlugin = Plugin<TempoType>;
export type TempoModule = Module<TempoType>;
/** @deprecated Use `TempoPlugin` instead. */
export type TempoExtension = Extension<TempoType>;

export function getHost(t: any): any {
const TempoClass = getRuntime().modules['Tempo'];
Expand Down Expand Up @@ -138,6 +137,7 @@ export function attachStatics(TempoClass: any, props: Record<string, any>) {
export function defineInterpreterModule(name: string, logic: any, statics?: Record<string, any>) {
return defineModule({
name,
version: TEMPO_VERSION,
install(this: TempoType, TempoClass: TempoType) {
const rt = getRuntime();
const modules = rt.modules;
Expand Down
1 change: 1 addition & 0 deletions packages/tempo/src/plugin/term/term.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type TempoTermType = typeof Tempo & {
*/
export interface TermPlugin {
key: string;
version?: string;
scope?: string;
description?: string;
locale?: Record<string, string | Function>;
Expand Down
2 changes: 2 additions & 0 deletions packages/tempo/src/plugin/term/term.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import { getRuntime } from '../../support/support.runtime.js';
import { SCHEMA, getLargestUnit } from '../../support/support.util.js';
import type { Tempo } from '../../tempo.class.js';
import type { TermPlugin, Range, ResolvedRange } from './term.type.js';
import { TEMPO_VERSION } from '../../tempo.version.js';

/**
* ## defineTerm
* Helper to register a Term plugin.
*/
export const defineTerm = <T extends TermPlugin>(term: T): T => {
if (!term.version) term.version = TEMPO_VERSION;
registerTerm(term);
return deepFreeze(term) as T;
}
Expand Down
Loading
Loading