Build runtime infrastructure layer: aapp + 5 new artifacts
Adds the application composition root and six new runtime artifacts. lang
and logr alone could not cover an app surface — locale propagation, format
helpers, frontend preferences, validation, persistence and DOM service all
needed independent artifacts that aapp wires together under a single
locale source of truth and a shared logger.
New artifacts:
- aapp: composition root. createActiveApp + createTestApp +
App.createSiumEngine + frontend.persist + Storage wiring.
- stor: pluggable adapters (local/session/memory/cookie + SSR via
cookieAdapter.fromCookies), envelope versioning + migrate +
TTL, validate via Standard Schema, intra-tab + cross-tab sync,
Storage.clear(), per-entry adapter/namespace overrides.
- adom: reactive DOM service. shareViewport opt-in + per-window
tracker, dispose(). breakpoints, viewport, attribute writes.
- fend: frontend preferences (theme, mode, dir, density,
reducedMotion, reducedSound) with auto/clear/isAuto pattern.
- fmts: localized formatting (numbers, currency, units, dates) with
shared LocaleSource and per-domain auto/clear pattern.
- sium: validation engine. Standard Schema interop, Lang/Logger
injection, codec/refine/transform, domain types
(color/date/time), introspection.
Existing artifacts extended:
- lang: BCP 47 SupportedLocale (LangBase | base-region), mono lang
for monolingual apps, extend() leaf-overwrite warning,
EngineLang/ActiveLang naming alignment with the rest of the
project (no Instance suffix).
- logr: EngineLogger.dispose(), failureThrottleMs anti-cascade for
transports, README sync to the per-level filter API
(minLevel removed).
Cross-cutting:
- $locale: shared LocaleSource type consumed by fmts and fend.
- arts/README.md: artifact map, dependency graph, naming conventions.
- Test pages for every artifact under /test/<artifact>.
733 tests passing; svelte-check clean except 2 pre-existing errors on
sium/svelte provider (port pending).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
import { describe, expect, it } from 'vitest';
|
Rename permissions→perm, formats→format; consolidate sium error infra
Two more module renames flipping the direction of the previous pass:
- arts/permissions, libs/permissions, svrs/permissions, libs/svrs/permissions.ts
→ arts/perm, libs/perm, svrs/perm, libs/svrs/perm.ts.
Alias: $permissions → $perm. Constants: PERMISSION_* → PERM_*.
Wire: 'permissions::*' → 'perm::*'. Module value: 'perm'.
Class names: Permission*Error → Perm*Error. Helper functions:
permissionDecisionKey → permDecisionKey (and similar).
- arts/formats → arts/format (with the four sub-modules currency,
numbers, units, dates carried along). Alias: $formats → $format.
Constants: FORMATS_* → FORMAT_*. Wire: 'formats::*' → 'format::*'.
Class names: Formats*Error → Format*Error.
Both follow the auth/http/dom precedent: short word as the canonical
name. The earlier full-word forms (permissions, formats) created
asymmetric prefixes (PERMISSION_* singular, PERMISSIONS_REFRESH
plural) that were already showing as drift in this commit's call
sites.
Plus a fix to sium error structure that was carried over from the
previous audit round but never fully consolidated:
- arts/sium/errors.ts now owns the full error infra: SIUM_ERR seed,
all SIUM_ERR_* codes, SIUM_ERROR_MESSAGES catalog, error classes
(SiumValidationError, SiumAsyncSchemaError, SiumDiscriminatedUnionError),
guards and the SIUM_ERROR_MESSAGES type. The legacy SIUM_ERRORS
string catalog stays for the few non-thrown sites until those are
migrated.
- arts/sium/consts.ts no longer carries error codes — only module
identifier and diagnostic events.
- arts/sium/core/types.ts no longer carries error classes — only
schema types.
- All call sites in arts/sium/core/* and arts/sium/types/* now import
the error classes from `../errors` instead of `../core/types` /
`../consts`.
This is the canonical pattern documented in conventions.md rule 6:
all of a module's error infrastructure lives in a single errors.ts
file; consts.ts is for module configuration that has nothing to do
with errors. Sium is now compliant; the rest of the modules will
follow in subsequent commits.
All 1334 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
import { createActiveFormat, createEngineFormat } from '..';
|
Build runtime infrastructure layer: aapp + 5 new artifacts
Adds the application composition root and six new runtime artifacts. lang
and logr alone could not cover an app surface — locale propagation, format
helpers, frontend preferences, validation, persistence and DOM service all
needed independent artifacts that aapp wires together under a single
locale source of truth and a shared logger.
New artifacts:
- aapp: composition root. createActiveApp + createTestApp +
App.createSiumEngine + frontend.persist + Storage wiring.
- stor: pluggable adapters (local/session/memory/cookie + SSR via
cookieAdapter.fromCookies), envelope versioning + migrate +
TTL, validate via Standard Schema, intra-tab + cross-tab sync,
Storage.clear(), per-entry adapter/namespace overrides.
- adom: reactive DOM service. shareViewport opt-in + per-window
tracker, dispose(). breakpoints, viewport, attribute writes.
- fend: frontend preferences (theme, mode, dir, density,
reducedMotion, reducedSound) with auto/clear/isAuto pattern.
- fmts: localized formatting (numbers, currency, units, dates) with
shared LocaleSource and per-domain auto/clear pattern.
- sium: validation engine. Standard Schema interop, Lang/Logger
injection, codec/refine/transform, domain types
(color/date/time), introspection.
Existing artifacts extended:
- lang: BCP 47 SupportedLocale (LangBase | base-region), mono lang
for monolingual apps, extend() leaf-overwrite warning,
EngineLang/ActiveLang naming alignment with the rest of the
project (no Instance suffix).
- logr: EngineLogger.dispose(), failureThrottleMs anti-cascade for
transports, README sync to the per-level filter API
(minLevel removed).
Cross-cutting:
- $locale: shared LocaleSource type consumed by fmts and fend.
- arts/README.md: artifact map, dependency graph, naming conventions.
- Test pages for every artifact under /test/<artifact>.
733 tests passing; svelte-check clean except 2 pre-existing errors on
sium/svelte provider (port pending).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
|
Rename permissions→perm, formats→format; consolidate sium error infra
Two more module renames flipping the direction of the previous pass:
- arts/permissions, libs/permissions, svrs/permissions, libs/svrs/permissions.ts
→ arts/perm, libs/perm, svrs/perm, libs/svrs/perm.ts.
Alias: $permissions → $perm. Constants: PERMISSION_* → PERM_*.
Wire: 'permissions::*' → 'perm::*'. Module value: 'perm'.
Class names: Permission*Error → Perm*Error. Helper functions:
permissionDecisionKey → permDecisionKey (and similar).
- arts/formats → arts/format (with the four sub-modules currency,
numbers, units, dates carried along). Alias: $formats → $format.
Constants: FORMATS_* → FORMAT_*. Wire: 'formats::*' → 'format::*'.
Class names: Formats*Error → Format*Error.
Both follow the auth/http/dom precedent: short word as the canonical
name. The earlier full-word forms (permissions, formats) created
asymmetric prefixes (PERMISSION_* singular, PERMISSIONS_REFRESH
plural) that were already showing as drift in this commit's call
sites.
Plus a fix to sium error structure that was carried over from the
previous audit round but never fully consolidated:
- arts/sium/errors.ts now owns the full error infra: SIUM_ERR seed,
all SIUM_ERR_* codes, SIUM_ERROR_MESSAGES catalog, error classes
(SiumValidationError, SiumAsyncSchemaError, SiumDiscriminatedUnionError),
guards and the SIUM_ERROR_MESSAGES type. The legacy SIUM_ERRORS
string catalog stays for the few non-thrown sites until those are
migrated.
- arts/sium/consts.ts no longer carries error codes — only module
identifier and diagnostic events.
- arts/sium/core/types.ts no longer carries error classes — only
schema types.
- All call sites in arts/sium/core/* and arts/sium/types/* now import
the error classes from `../errors` instead of `../core/types` /
`../consts`.
This is the canonical pattern documented in conventions.md rule 6:
all of a module's error infrastructure lives in a single errors.ts
file; consts.ts is for module configuration that has nothing to do
with errors. Sium is now compliant; the rest of the modules will
follow in subsequent commits.
All 1334 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
describe('createEngineFormat()', () => {
|
Build runtime infrastructure layer: aapp + 5 new artifacts
Adds the application composition root and six new runtime artifacts. lang
and logr alone could not cover an app surface — locale propagation, format
helpers, frontend preferences, validation, persistence and DOM service all
needed independent artifacts that aapp wires together under a single
locale source of truth and a shared logger.
New artifacts:
- aapp: composition root. createActiveApp + createTestApp +
App.createSiumEngine + frontend.persist + Storage wiring.
- stor: pluggable adapters (local/session/memory/cookie + SSR via
cookieAdapter.fromCookies), envelope versioning + migrate +
TTL, validate via Standard Schema, intra-tab + cross-tab sync,
Storage.clear(), per-entry adapter/namespace overrides.
- adom: reactive DOM service. shareViewport opt-in + per-window
tracker, dispose(). breakpoints, viewport, attribute writes.
- fend: frontend preferences (theme, mode, dir, density,
reducedMotion, reducedSound) with auto/clear/isAuto pattern.
- fmts: localized formatting (numbers, currency, units, dates) with
shared LocaleSource and per-domain auto/clear pattern.
- sium: validation engine. Standard Schema interop, Lang/Logger
injection, codec/refine/transform, domain types
(color/date/time), introspection.
Existing artifacts extended:
- lang: BCP 47 SupportedLocale (LangBase | base-region), mono lang
for monolingual apps, extend() leaf-overwrite warning,
EngineLang/ActiveLang naming alignment with the rest of the
project (no Instance suffix).
- logr: EngineLogger.dispose(), failureThrottleMs anti-cascade for
transports, README sync to the per-level filter API
(minLevel removed).
Cross-cutting:
- $locale: shared LocaleSource type consumed by fmts and fend.
- arts/README.md: artifact map, dependency graph, naming conventions.
- Test pages for every artifact under /test/<artifact>.
733 tests passing; svelte-check clean except 2 pre-existing errors on
sium/svelte provider (port pending).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
it('composes number, currency, units and dates format engines', async () => {
|
Rename permissions→perm, formats→format; consolidate sium error infra
Two more module renames flipping the direction of the previous pass:
- arts/permissions, libs/permissions, svrs/permissions, libs/svrs/permissions.ts
→ arts/perm, libs/perm, svrs/perm, libs/svrs/perm.ts.
Alias: $permissions → $perm. Constants: PERMISSION_* → PERM_*.
Wire: 'permissions::*' → 'perm::*'. Module value: 'perm'.
Class names: Permission*Error → Perm*Error. Helper functions:
permissionDecisionKey → permDecisionKey (and similar).
- arts/formats → arts/format (with the four sub-modules currency,
numbers, units, dates carried along). Alias: $formats → $format.
Constants: FORMATS_* → FORMAT_*. Wire: 'formats::*' → 'format::*'.
Class names: Formats*Error → Format*Error.
Both follow the auth/http/dom precedent: short word as the canonical
name. The earlier full-word forms (permissions, formats) created
asymmetric prefixes (PERMISSION_* singular, PERMISSIONS_REFRESH
plural) that were already showing as drift in this commit's call
sites.
Plus a fix to sium error structure that was carried over from the
previous audit round but never fully consolidated:
- arts/sium/errors.ts now owns the full error infra: SIUM_ERR seed,
all SIUM_ERR_* codes, SIUM_ERROR_MESSAGES catalog, error classes
(SiumValidationError, SiumAsyncSchemaError, SiumDiscriminatedUnionError),
guards and the SIUM_ERROR_MESSAGES type. The legacy SIUM_ERRORS
string catalog stays for the few non-thrown sites until those are
migrated.
- arts/sium/consts.ts no longer carries error codes — only module
identifier and diagnostic events.
- arts/sium/core/types.ts no longer carries error classes — only
schema types.
- All call sites in arts/sium/core/* and arts/sium/types/* now import
the error classes from `../errors` instead of `../core/types` /
`../consts`.
This is the canonical pattern documented in conventions.md rule 6:
all of a module's error infrastructure lives in a single errors.ts
file; consts.ts is for module configuration that has nothing to do
with errors. Sium is now compliant; the rest of the modules will
follow in subsequent commits.
All 1334 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const formats = createEngineFormat({
|
Build runtime infrastructure layer: aapp + 5 new artifacts
Adds the application composition root and six new runtime artifacts. lang
and logr alone could not cover an app surface — locale propagation, format
helpers, frontend preferences, validation, persistence and DOM service all
needed independent artifacts that aapp wires together under a single
locale source of truth and a shared logger.
New artifacts:
- aapp: composition root. createActiveApp + createTestApp +
App.createSiumEngine + frontend.persist + Storage wiring.
- stor: pluggable adapters (local/session/memory/cookie + SSR via
cookieAdapter.fromCookies), envelope versioning + migrate +
TTL, validate via Standard Schema, intra-tab + cross-tab sync,
Storage.clear(), per-entry adapter/namespace overrides.
- adom: reactive DOM service. shareViewport opt-in + per-window
tracker, dispose(). breakpoints, viewport, attribute writes.
- fend: frontend preferences (theme, mode, dir, density,
reducedMotion, reducedSound) with auto/clear/isAuto pattern.
- fmts: localized formatting (numbers, currency, units, dates) with
shared LocaleSource and per-domain auto/clear pattern.
- sium: validation engine. Standard Schema interop, Lang/Logger
injection, codec/refine/transform, domain types
(color/date/time), introspection.
Existing artifacts extended:
- lang: BCP 47 SupportedLocale (LangBase | base-region), mono lang
for monolingual apps, extend() leaf-overwrite warning,
EngineLang/ActiveLang naming alignment with the rest of the
project (no Instance suffix).
- logr: EngineLogger.dispose(), failureThrottleMs anti-cascade for
transports, README sync to the per-level filter API
(minLevel removed).
Cross-cutting:
- $locale: shared LocaleSource type consumed by fmts and fend.
- arts/README.md: artifact map, dependency graph, naming conventions.
- Test pages for every artifact under /test/<artifact>.
733 tests passing; svelte-check clean except 2 pre-existing errors on
sium/svelte provider (port pending).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
|
|
|
locale: 'en-US',
|
|
|
|
|
currency: {
|
|
|
|
|
rates: undefined
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
expect(formats.getLocale()).toBe('en-US');
|
|
|
|
|
expect(formats.numbers.format(1234.5)).toBe('1,234.5');
|
|
|
|
|
expect(formats.currency.getCurrency()).toBe('USD');
|
|
|
|
|
expect(formats.units.getSystem()).toBe('imperial');
|
|
|
|
|
expect(formats.units.getDefaultUnit('distance')).toBe('mile');
|
|
|
|
|
expect(formats.dates.getHourCycle()).toBe(12);
|
|
|
|
|
|
|
|
|
|
formats.setLocale('es-ES');
|
|
|
|
|
|
|
|
|
|
expect(formats.getLocale()).toBe('es-ES');
|
|
|
|
|
expect(formats.currency.getCurrency()).toBe('EUR');
|
|
|
|
|
expect(formats.units.getSystem()).toBe('metric');
|
|
|
|
|
expect(formats.units.getDefaultUnit('distance')).toBe('kilometer');
|
|
|
|
|
await expect(formats.currency.convert(1, 'EUR')).resolves.toBe(1);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
Rename permissions→perm, formats→format; consolidate sium error infra
Two more module renames flipping the direction of the previous pass:
- arts/permissions, libs/permissions, svrs/permissions, libs/svrs/permissions.ts
→ arts/perm, libs/perm, svrs/perm, libs/svrs/perm.ts.
Alias: $permissions → $perm. Constants: PERMISSION_* → PERM_*.
Wire: 'permissions::*' → 'perm::*'. Module value: 'perm'.
Class names: Permission*Error → Perm*Error. Helper functions:
permissionDecisionKey → permDecisionKey (and similar).
- arts/formats → arts/format (with the four sub-modules currency,
numbers, units, dates carried along). Alias: $formats → $format.
Constants: FORMATS_* → FORMAT_*. Wire: 'formats::*' → 'format::*'.
Class names: Formats*Error → Format*Error.
Both follow the auth/http/dom precedent: short word as the canonical
name. The earlier full-word forms (permissions, formats) created
asymmetric prefixes (PERMISSION_* singular, PERMISSIONS_REFRESH
plural) that were already showing as drift in this commit's call
sites.
Plus a fix to sium error structure that was carried over from the
previous audit round but never fully consolidated:
- arts/sium/errors.ts now owns the full error infra: SIUM_ERR seed,
all SIUM_ERR_* codes, SIUM_ERROR_MESSAGES catalog, error classes
(SiumValidationError, SiumAsyncSchemaError, SiumDiscriminatedUnionError),
guards and the SIUM_ERROR_MESSAGES type. The legacy SIUM_ERRORS
string catalog stays for the few non-thrown sites until those are
migrated.
- arts/sium/consts.ts no longer carries error codes — only module
identifier and diagnostic events.
- arts/sium/core/types.ts no longer carries error classes — only
schema types.
- All call sites in arts/sium/core/* and arts/sium/types/* now import
the error classes from `../errors` instead of `../core/types` /
`../consts`.
This is the canonical pattern documented in conventions.md rule 6:
all of a module's error infrastructure lives in a single errors.ts
file; consts.ts is for module configuration that has nothing to do
with errors. Sium is now compliant; the rest of the modules will
follow in subsequent commits.
All 1334 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
describe('createActiveFormat()', () => {
|
|
|
|
|
it('fans out locale changes to every active format module', () => {
|
Rename permissions→perm, formats→format; consolidate sium error infra
Two more module renames flipping the direction of the previous pass:
- arts/permissions, libs/permissions, svrs/permissions, libs/svrs/permissions.ts
→ arts/perm, libs/perm, svrs/perm, libs/svrs/perm.ts.
Alias: $permissions → $perm. Constants: PERMISSION_* → PERM_*.
Wire: 'permissions::*' → 'perm::*'. Module value: 'perm'.
Class names: Permission*Error → Perm*Error. Helper functions:
permissionDecisionKey → permDecisionKey (and similar).
- arts/formats → arts/format (with the four sub-modules currency,
numbers, units, dates carried along). Alias: $formats → $format.
Constants: FORMATS_* → FORMAT_*. Wire: 'formats::*' → 'format::*'.
Class names: Formats*Error → Format*Error.
Both follow the auth/http/dom precedent: short word as the canonical
name. The earlier full-word forms (permissions, formats) created
asymmetric prefixes (PERMISSION_* singular, PERMISSIONS_REFRESH
plural) that were already showing as drift in this commit's call
sites.
Plus a fix to sium error structure that was carried over from the
previous audit round but never fully consolidated:
- arts/sium/errors.ts now owns the full error infra: SIUM_ERR seed,
all SIUM_ERR_* codes, SIUM_ERROR_MESSAGES catalog, error classes
(SiumValidationError, SiumAsyncSchemaError, SiumDiscriminatedUnionError),
guards and the SIUM_ERROR_MESSAGES type. The legacy SIUM_ERRORS
string catalog stays for the few non-thrown sites until those are
migrated.
- arts/sium/consts.ts no longer carries error codes — only module
identifier and diagnostic events.
- arts/sium/core/types.ts no longer carries error classes — only
schema types.
- All call sites in arts/sium/core/* and arts/sium/types/* now import
the error classes from `../errors` instead of `../core/types` /
`../consts`.
This is the canonical pattern documented in conventions.md rule 6:
all of a module's error infrastructure lives in a single errors.ts
file; consts.ts is for module configuration that has nothing to do
with errors. Sium is now compliant; the rest of the modules will
follow in subsequent commits.
All 1334 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
const formats = createActiveFormat({ locale: 'en-US' });
|
|
|
|
|
|
|
|
|
|
expect(formats.getLocale()).toBe('en-US');
|
|
|
|
|
expect(formats.currency.getCurrency()).toBe('USD');
|
|
|
|
|
expect(formats.units.getSystem()).toBe('imperial');
|
|
|
|
|
expect(formats.dates.getHourCycle()).toBe(12);
|
|
|
|
|
|
|
|
|
|
formats.setLocale('es-ES');
|
|
|
|
|
|
|
|
|
|
expect(formats.getLocale()).toBe('es-ES');
|
|
|
|
|
expect(formats.currency.getCurrency()).toBe('EUR');
|
|
|
|
|
expect(formats.units.getSystem()).toBe('metric');
|
|
|
|
|
expect(formats.dates.getDateOrder()).toBe('DMY');
|
|
|
|
|
|
|
|
|
|
formats.dispose();
|
|
|
|
|
});
|
Bloque D — uniform lifecycle for declarable services
Audit P2: every service the app declares in `createActiveApp({
services })` should respect the same dispose contract: idempotent,
post-dispose mutators are inert, no late side effects on torn-down
subscriptions.
storage:
- New `STORAGE_ERR_DISPOSED` + `StorageDisposedError` (with
`isStorageDisposedError` guard).
- `entry()`, `clear()` and `entries()` throw `StorageDisposedError`
after `dispose()` instead of silently mutating refcounted
registries with the bus already torn down.
- Re-exports added to the index barrel.
frontend:
- `ActiveFrontend.disposed` getter on the public type.
- Every mutating setter (`setLocale`, `setDir`, `clearDir`,
`setTheme`, `setMode`, `clearMode`, `setReducedMotion`,
`clearReducedMotion`, `setReducedSound`, `setDensity`) now
short-circuits when disposed, so a late media-query event or a
locale-source emit during teardown can't rewrite the DOM through
a torn-down `applyDom()`. Read-only getters keep returning the
last applied value.
- `onPreferenceChange` returns a no-op detacher post-dispose.
- `dispose()` is idempotent (was already, now also guarded against
resurrected mutations).
format:
- `ActiveFormat.disposed` getter on the public type.
- `dispose()` is now idempotent at the root and walks each
sub-engine in stable order.
- `setLocale()` is a no-op post-dispose.
Tests: +3 regression tests (one per art) covering the new dispose
semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
|
|
|
|
|
|
|
|
it('exposes disposed flag, is idempotent, and ignores setLocale post-dispose', () => {
|
|
|
|
|
const formats = createActiveFormat({ locale: 'en-US' });
|
|
|
|
|
|
|
|
|
|
expect(formats.disposed).toBe(false);
|
|
|
|
|
formats.dispose();
|
|
|
|
|
expect(formats.disposed).toBe(true);
|
|
|
|
|
|
|
|
|
|
expect(() => formats.dispose()).not.toThrow();
|
|
|
|
|
|
|
|
|
|
// setLocale is a silent no-op after dispose; the cached values stay
|
|
|
|
|
// frozen at the last set value.
|
|
|
|
|
const lastLocale = formats.getLocale();
|
|
|
|
|
formats.setLocale('fr-FR');
|
|
|
|
|
expect(formats.getLocale()).toBe(lastLocale);
|
|
|
|
|
});
|
|
|
|
|
});
|