You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
7.9 KiB

Rename modules from 4-letter aliases to full English words Drops the 4-letter alias convention in favour of a single homogeneous naming axis: full English words across filesystem, alias, wire format and constants. Module renames: - arts/aapp → arts/active-app (libs/aapp also) - arts/buss → arts/bus (libs/buss also) - arts/cach → arts/cache (libs/cach + svrs/cach also) - arts/conn → arts/connection - arts/fend → arts/frontend - arts/fmts → arts/formats (curr→currency, nums→numbers, unts→units) - arts/logr → arts/logger (libs/logr also) - arts/perm → arts/permissions (libs/perm + svrs/perm also) - arts/sess → arts/session - arts/stor → arts/storage - arts/timr → arts/timer (libs/timers → libs/timer) Modules left as-is: auth, dom, errs, http, lang, sium (already match their canonical name or are proper names). Special case: `aapp` could not become `app` because `$app` is reserved by SvelteKit (`$app/stores`, `$app/navigation`, ...). Compromise: - Filesystem and alias use `active-app` / `$active-app`. - Constants and class names use `App` / `APP_*` (no `active-` prefix). The `active-` prefix only disambiguates the alias from SvelteKit's namespace; the module is App. Special case: `permissions` keeps the plural for filesystem/alias/wire but constants and classes use the singular `PERMISSION_*` / `Permission*` because they describe the concept ("a permission effect"), not the module collection. Constants follow the new module name in caps: `STORAGE_*`, `BUS_*`, `CACHE_*`, `CONNECTION_*`, `FORMATS_*`, `LOGGER_*`, `SESSION_*`, `TIMER_*`, etc. Module values: `STORAGE_MODULE = 'storage'`, `BUS_MODULE = 'bus'`, `APP_MODULE = 'app'`, `PERMISSION_MODULE = 'permissions'`, etc. Wire/code format moved accordingly: `'storage::*'`, `'bus::*'`, `'session::*'`, `'permissions::*'`, etc. Diagnostic event values updated: `'storage.error'`, `'bus.event.published'`, `'connection.auth_failed'`, etc. App events use `'app.*'`: `AAPP_EVENT_* → APP_EVENT_*` with values `'app.user.identity.changed'`. Class renames (where they used the abbreviation): - AappAlreadyCreatedError → AppAlreadyCreatedError - BussError* → BusError* (where applicable) - Cach* → Cache* - Conn* → Connection* (e.g. ConnDisposedError → ConnectionDisposedError; ConnConnection* collapsed to Connection*) - Logr*Error → Logger*Error - Sess* → Session* (SessInvalidSessionError → SessionInvalidError) - Stor* → Storage* - Timr* → Timer* (TimrInactiveTimerError → TimerInactiveError) - AuthCachPort → AuthCachePort - AuthClientCach* → AuthClientCache* - AuthPermPort → AuthPermissionsPort Property renames in option types: - `cach?:` → `cache?:` in AuthClient options - `logr:` → `logger:` in svrs/auth ports - `timr:` → `timer:` in svrs/auth ports `docs/conventions.md` rewritten: - Rule 1 dropped the 4-letter alias mandate; lists the full English module names and special-cases active-app, lang, sium, permissions. - Rule 2 documents the new constant prefix convention and its two exceptions (APP_* for active-app, PERMISSION_* singular for permissions). - Rule 6 codifies that all error infrastructure (codes, messages, classes, guards) lives in a single `errors.ts` per module — removing the `consts.ts` / `errors.ts` split for error-related symbols. `libs/errs` adds `ErrorMessages` type so every module can declare its catalog as `<MOD>_ERROR_MESSAGES: ErrorMessages` instead of repeating the `Readonly<Record<ErrCode, string | (...args) => string>>` shape. Storage migrated as the first proof of the canonical pattern. All 1334 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
import {
CodeError,
errCode,
moduleSeed,
type ErrCode,
type ErrorMessages,
type ModuleSeed
} from '$libs/errs';
import { STORAGE_MODULE } from './consts.ts';
// ── Error codes ────────────────────────────────────────────────────────
//
// All error identity for the `stor` artifact lives here. Each constant
// is the code passed to `CodeError`; consumers that need to discriminate
// errors by family (logs, error boundaries, i18n) match against these.
export const STORAGE_ERR: ModuleSeed = moduleSeed(STORAGE_MODULE);
/** Generic kind: a value did not match the expected type (e.g. a serializer
* received an unparseable string). The native `TypeError` carrying the
* specific failure goes into `cause`. */
export const STORAGE_ERR_INVALID_TYPE: ErrCode = errCode(STORAGE_ERR, 'invalid_type');
/** `entry()` was registered with `defaults: undefined` — use `null` instead. */
export const STORAGE_ERR_UNDEFINED_DEFAULT: ErrCode = errCode(STORAGE_ERR, 'undefined_default');
/** Standard Schema validation failed for the value being read/written. */
export const STORAGE_ERR_VALIDATION_FAILED: ErrCode = errCode(STORAGE_ERR, 'validation_failed');
/** Standard Schema returned a Promise — async validators are not supported
* by the synchronous storage adapter contract. */
export const STORAGE_ERR_ASYNC_VALIDATE_UNSUPPORTED: ErrCode = errCode(
STORAGE_ERR,
'async_validate_unsupported'
);
/** `entry()` called twice with different defaults — first registration wins. */
export const STORAGE_ERR_ENTRY_DEFAULTS_MISMATCH: ErrCode = errCode(
STORAGE_ERR,
'entry_defaults_mismatch'
);
/** `cookieAdapter()` invoked from server context — use `cookieAdapter.fromCookies()`. */
export const STORAGE_ERR_COOKIE_SERVER_REQUIRED: ErrCode = errCode(
STORAGE_ERR,
'cookie_server_required'
);
/** Stored envelope had a non-numeric `v` (version) field. Surfaces as the
* `error` on `EnvelopeRead { kind: 'invalid' }` rather than thrown. */
export const STORAGE_ERR_ENVELOPE_INVALID_VERSION: ErrCode = errCode(
STORAGE_ERR,
'envelope_invalid_version'
);
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
/**
* `entry()`, `clear()`, `entries()` or any other public surface was
* invoked after `dispose()`. The engine's bus and adapter
* subscriptions are already torn down at that point — re-creating
* entries would silently leak.
*/
export const STORAGE_ERR_DISPOSED: ErrCode = errCode(STORAGE_ERR, 'disposed');
Rename modules from 4-letter aliases to full English words Drops the 4-letter alias convention in favour of a single homogeneous naming axis: full English words across filesystem, alias, wire format and constants. Module renames: - arts/aapp → arts/active-app (libs/aapp also) - arts/buss → arts/bus (libs/buss also) - arts/cach → arts/cache (libs/cach + svrs/cach also) - arts/conn → arts/connection - arts/fend → arts/frontend - arts/fmts → arts/formats (curr→currency, nums→numbers, unts→units) - arts/logr → arts/logger (libs/logr also) - arts/perm → arts/permissions (libs/perm + svrs/perm also) - arts/sess → arts/session - arts/stor → arts/storage - arts/timr → arts/timer (libs/timers → libs/timer) Modules left as-is: auth, dom, errs, http, lang, sium (already match their canonical name or are proper names). Special case: `aapp` could not become `app` because `$app` is reserved by SvelteKit (`$app/stores`, `$app/navigation`, ...). Compromise: - Filesystem and alias use `active-app` / `$active-app`. - Constants and class names use `App` / `APP_*` (no `active-` prefix). The `active-` prefix only disambiguates the alias from SvelteKit's namespace; the module is App. Special case: `permissions` keeps the plural for filesystem/alias/wire but constants and classes use the singular `PERMISSION_*` / `Permission*` because they describe the concept ("a permission effect"), not the module collection. Constants follow the new module name in caps: `STORAGE_*`, `BUS_*`, `CACHE_*`, `CONNECTION_*`, `FORMATS_*`, `LOGGER_*`, `SESSION_*`, `TIMER_*`, etc. Module values: `STORAGE_MODULE = 'storage'`, `BUS_MODULE = 'bus'`, `APP_MODULE = 'app'`, `PERMISSION_MODULE = 'permissions'`, etc. Wire/code format moved accordingly: `'storage::*'`, `'bus::*'`, `'session::*'`, `'permissions::*'`, etc. Diagnostic event values updated: `'storage.error'`, `'bus.event.published'`, `'connection.auth_failed'`, etc. App events use `'app.*'`: `AAPP_EVENT_* → APP_EVENT_*` with values `'app.user.identity.changed'`. Class renames (where they used the abbreviation): - AappAlreadyCreatedError → AppAlreadyCreatedError - BussError* → BusError* (where applicable) - Cach* → Cache* - Conn* → Connection* (e.g. ConnDisposedError → ConnectionDisposedError; ConnConnection* collapsed to Connection*) - Logr*Error → Logger*Error - Sess* → Session* (SessInvalidSessionError → SessionInvalidError) - Stor* → Storage* - Timr* → Timer* (TimrInactiveTimerError → TimerInactiveError) - AuthCachPort → AuthCachePort - AuthClientCach* → AuthClientCache* - AuthPermPort → AuthPermissionsPort Property renames in option types: - `cach?:` → `cache?:` in AuthClient options - `logr:` → `logger:` in svrs/auth ports - `timr:` → `timer:` in svrs/auth ports `docs/conventions.md` rewritten: - Rule 1 dropped the 4-letter alias mandate; lists the full English module names and special-cases active-app, lang, sium, permissions. - Rule 2 documents the new constant prefix convention and its two exceptions (APP_* for active-app, PERMISSION_* singular for permissions). - Rule 6 codifies that all error infrastructure (codes, messages, classes, guards) lives in a single `errors.ts` per module — removing the `consts.ts` / `errors.ts` split for error-related symbols. `libs/errs` adds `ErrorMessages` type so every module can declare its catalog as `<MOD>_ERROR_MESSAGES: ErrorMessages` instead of repeating the `Readonly<Record<ErrCode, string | (...args) => string>>` shape. Storage migrated as the first proof of the canonical pattern. All 1334 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
/**
* Human-readable messages for every error declared by `arts/stor`.
* Indexed by `ErrCode` so the link to identity is direct. Each entry
* is either a static string or a function that builds the message
* from contextual fields.
*/
export const STORAGE_ERROR_MESSAGES: ErrorMessages = {
[STORAGE_ERR_INVALID_TYPE]: (kind: string, value: string): string =>
`[${STORAGE_MODULE}] ${kind} could not parse "${value}".`,
[STORAGE_ERR_UNDEFINED_DEFAULT]:
`[${STORAGE_MODULE}] defaults must not be undefined. Use null when you need an empty value.`,
[STORAGE_ERR_VALIDATION_FAILED]: (issues: unknown): string =>
`[${STORAGE_MODULE}] Standard Schema validation failed: ${JSON.stringify(issues)}`,
[STORAGE_ERR_ASYNC_VALIDATE_UNSUPPORTED]:
`[${STORAGE_MODULE}] Async Standard Schema validation is not supported in v1 (SyncStorageAdapter only). Use a sync schema or a sync validate() function.`,
[STORAGE_ERR_ENTRY_DEFAULTS_MISMATCH]: (key: string): string =>
`[${STORAGE_MODULE}] entry("${key}", ...) was called more than once with different defaults. The first registration wins; the second default is ignored.`,
[STORAGE_ERR_COOKIE_SERVER_REQUIRED]:
`[${STORAGE_MODULE}] cookieAdapter() runs in the browser only. For SSR use cookieAdapter.fromCookies(event.cookies, options).`,
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
[STORAGE_ERR_ENVELOPE_INVALID_VERSION]: `[${STORAGE_MODULE}] envelope.v not a number`,
[STORAGE_ERR_DISPOSED]: (op: string): string =>
`[${STORAGE_MODULE}] ${op}() called on disposed storage`
Rename modules from 4-letter aliases to full English words Drops the 4-letter alias convention in favour of a single homogeneous naming axis: full English words across filesystem, alias, wire format and constants. Module renames: - arts/aapp → arts/active-app (libs/aapp also) - arts/buss → arts/bus (libs/buss also) - arts/cach → arts/cache (libs/cach + svrs/cach also) - arts/conn → arts/connection - arts/fend → arts/frontend - arts/fmts → arts/formats (curr→currency, nums→numbers, unts→units) - arts/logr → arts/logger (libs/logr also) - arts/perm → arts/permissions (libs/perm + svrs/perm also) - arts/sess → arts/session - arts/stor → arts/storage - arts/timr → arts/timer (libs/timers → libs/timer) Modules left as-is: auth, dom, errs, http, lang, sium (already match their canonical name or are proper names). Special case: `aapp` could not become `app` because `$app` is reserved by SvelteKit (`$app/stores`, `$app/navigation`, ...). Compromise: - Filesystem and alias use `active-app` / `$active-app`. - Constants and class names use `App` / `APP_*` (no `active-` prefix). The `active-` prefix only disambiguates the alias from SvelteKit's namespace; the module is App. Special case: `permissions` keeps the plural for filesystem/alias/wire but constants and classes use the singular `PERMISSION_*` / `Permission*` because they describe the concept ("a permission effect"), not the module collection. Constants follow the new module name in caps: `STORAGE_*`, `BUS_*`, `CACHE_*`, `CONNECTION_*`, `FORMATS_*`, `LOGGER_*`, `SESSION_*`, `TIMER_*`, etc. Module values: `STORAGE_MODULE = 'storage'`, `BUS_MODULE = 'bus'`, `APP_MODULE = 'app'`, `PERMISSION_MODULE = 'permissions'`, etc. Wire/code format moved accordingly: `'storage::*'`, `'bus::*'`, `'session::*'`, `'permissions::*'`, etc. Diagnostic event values updated: `'storage.error'`, `'bus.event.published'`, `'connection.auth_failed'`, etc. App events use `'app.*'`: `AAPP_EVENT_* → APP_EVENT_*` with values `'app.user.identity.changed'`. Class renames (where they used the abbreviation): - AappAlreadyCreatedError → AppAlreadyCreatedError - BussError* → BusError* (where applicable) - Cach* → Cache* - Conn* → Connection* (e.g. ConnDisposedError → ConnectionDisposedError; ConnConnection* collapsed to Connection*) - Logr*Error → Logger*Error - Sess* → Session* (SessInvalidSessionError → SessionInvalidError) - Stor* → Storage* - Timr* → Timer* (TimrInactiveTimerError → TimerInactiveError) - AuthCachPort → AuthCachePort - AuthClientCach* → AuthClientCache* - AuthPermPort → AuthPermissionsPort Property renames in option types: - `cach?:` → `cache?:` in AuthClient options - `logr:` → `logger:` in svrs/auth ports - `timr:` → `timer:` in svrs/auth ports `docs/conventions.md` rewritten: - Rule 1 dropped the 4-letter alias mandate; lists the full English module names and special-cases active-app, lang, sium, permissions. - Rule 2 documents the new constant prefix convention and its two exceptions (APP_* for active-app, PERMISSION_* singular for permissions). - Rule 6 codifies that all error infrastructure (codes, messages, classes, guards) lives in a single `errors.ts` per module — removing the `consts.ts` / `errors.ts` split for error-related symbols. `libs/errs` adds `ErrorMessages` type so every module can declare its catalog as `<MOD>_ERROR_MESSAGES: ErrorMessages` instead of repeating the `Readonly<Record<ErrCode, string | (...args) => string>>` shape. Storage migrated as the first proof of the canonical pattern. All 1334 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
};
/**
* Generic type-violation kind for stor. Thrown when a serializer or
* validator receives a value that does not match the expected type
* (e.g. `numberSerializer.deserialize("abc")`). The original `TypeError`
* with the specific detail is preserved on `cause`.
*/
export class StorageInvalidTypeError extends CodeError {
readonly kind: string;
readonly value: string;
constructor(kind: string, value: string, cause: unknown) {
const message = STORAGE_ERROR_MESSAGES[STORAGE_ERR_INVALID_TYPE] as (
kind: string,
value: string
) => string;
super(STORAGE_ERR_INVALID_TYPE, { message: message(kind, value), cause });
this.kind = kind;
this.value = value;
}
}
export class StorageUndefinedDefaultError extends CodeError {
constructor() {
super(STORAGE_ERR_UNDEFINED_DEFAULT, {
message: STORAGE_ERROR_MESSAGES[STORAGE_ERR_UNDEFINED_DEFAULT] as string
});
}
}
export class StorageValidationFailedError extends CodeError {
readonly issues: unknown;
constructor(issues: unknown) {
const message = STORAGE_ERROR_MESSAGES[STORAGE_ERR_VALIDATION_FAILED] as (
issues: unknown
) => string;
super(STORAGE_ERR_VALIDATION_FAILED, { message: message(issues) });
this.issues = issues;
}
}
export class StorageAsyncValidateUnsupportedError extends CodeError {
constructor() {
super(STORAGE_ERR_ASYNC_VALIDATE_UNSUPPORTED, {
message: STORAGE_ERROR_MESSAGES[STORAGE_ERR_ASYNC_VALIDATE_UNSUPPORTED] as string
});
}
}
export class StorageEntryDefaultsMismatchError extends CodeError {
readonly key: string;
constructor(key: string) {
const message = STORAGE_ERROR_MESSAGES[STORAGE_ERR_ENTRY_DEFAULTS_MISMATCH] as (
key: string
) => string;
super(STORAGE_ERR_ENTRY_DEFAULTS_MISMATCH, { message: message(key) });
this.key = key;
}
}
export class StorageCookieServerRequiredError extends CodeError {
constructor() {
super(STORAGE_ERR_COOKIE_SERVER_REQUIRED, {
message: STORAGE_ERROR_MESSAGES[STORAGE_ERR_COOKIE_SERVER_REQUIRED] as string
});
}
}
export class StorageEnvelopeInvalidVersionError extends CodeError {
constructor(cause: unknown) {
super(STORAGE_ERR_ENVELOPE_INVALID_VERSION, {
message: STORAGE_ERROR_MESSAGES[STORAGE_ERR_ENVELOPE_INVALID_VERSION] as string,
cause
});
}
}
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
export class StorageDisposedError extends CodeError {
readonly op: string;
constructor(op: string) {
const message = STORAGE_ERROR_MESSAGES[STORAGE_ERR_DISPOSED] as (op: string) => string;
super(STORAGE_ERR_DISPOSED, { message: message(op) });
this.op = op;
}
}
Rename modules from 4-letter aliases to full English words Drops the 4-letter alias convention in favour of a single homogeneous naming axis: full English words across filesystem, alias, wire format and constants. Module renames: - arts/aapp → arts/active-app (libs/aapp also) - arts/buss → arts/bus (libs/buss also) - arts/cach → arts/cache (libs/cach + svrs/cach also) - arts/conn → arts/connection - arts/fend → arts/frontend - arts/fmts → arts/formats (curr→currency, nums→numbers, unts→units) - arts/logr → arts/logger (libs/logr also) - arts/perm → arts/permissions (libs/perm + svrs/perm also) - arts/sess → arts/session - arts/stor → arts/storage - arts/timr → arts/timer (libs/timers → libs/timer) Modules left as-is: auth, dom, errs, http, lang, sium (already match their canonical name or are proper names). Special case: `aapp` could not become `app` because `$app` is reserved by SvelteKit (`$app/stores`, `$app/navigation`, ...). Compromise: - Filesystem and alias use `active-app` / `$active-app`. - Constants and class names use `App` / `APP_*` (no `active-` prefix). The `active-` prefix only disambiguates the alias from SvelteKit's namespace; the module is App. Special case: `permissions` keeps the plural for filesystem/alias/wire but constants and classes use the singular `PERMISSION_*` / `Permission*` because they describe the concept ("a permission effect"), not the module collection. Constants follow the new module name in caps: `STORAGE_*`, `BUS_*`, `CACHE_*`, `CONNECTION_*`, `FORMATS_*`, `LOGGER_*`, `SESSION_*`, `TIMER_*`, etc. Module values: `STORAGE_MODULE = 'storage'`, `BUS_MODULE = 'bus'`, `APP_MODULE = 'app'`, `PERMISSION_MODULE = 'permissions'`, etc. Wire/code format moved accordingly: `'storage::*'`, `'bus::*'`, `'session::*'`, `'permissions::*'`, etc. Diagnostic event values updated: `'storage.error'`, `'bus.event.published'`, `'connection.auth_failed'`, etc. App events use `'app.*'`: `AAPP_EVENT_* → APP_EVENT_*` with values `'app.user.identity.changed'`. Class renames (where they used the abbreviation): - AappAlreadyCreatedError → AppAlreadyCreatedError - BussError* → BusError* (where applicable) - Cach* → Cache* - Conn* → Connection* (e.g. ConnDisposedError → ConnectionDisposedError; ConnConnection* collapsed to Connection*) - Logr*Error → Logger*Error - Sess* → Session* (SessInvalidSessionError → SessionInvalidError) - Stor* → Storage* - Timr* → Timer* (TimrInactiveTimerError → TimerInactiveError) - AuthCachPort → AuthCachePort - AuthClientCach* → AuthClientCache* - AuthPermPort → AuthPermissionsPort Property renames in option types: - `cach?:` → `cache?:` in AuthClient options - `logr:` → `logger:` in svrs/auth ports - `timr:` → `timer:` in svrs/auth ports `docs/conventions.md` rewritten: - Rule 1 dropped the 4-letter alias mandate; lists the full English module names and special-cases active-app, lang, sium, permissions. - Rule 2 documents the new constant prefix convention and its two exceptions (APP_* for active-app, PERMISSION_* singular for permissions). - Rule 6 codifies that all error infrastructure (codes, messages, classes, guards) lives in a single `errors.ts` per module — removing the `consts.ts` / `errors.ts` split for error-related symbols. `libs/errs` adds `ErrorMessages` type so every module can declare its catalog as `<MOD>_ERROR_MESSAGES: ErrorMessages` instead of repeating the `Readonly<Record<ErrCode, string | (...args) => string>>` shape. Storage migrated as the first proof of the canonical pattern. All 1334 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
// ── Type guards ─────────────────────────────────────────────────────────
export function isStorageInvalidTypeError(value: unknown): value is StorageInvalidTypeError {
return value instanceof StorageInvalidTypeError;
}
export function isStorageUndefinedDefaultError(
value: unknown
): value is StorageUndefinedDefaultError {
return value instanceof StorageUndefinedDefaultError;
}
export function isStorageValidationFailedError(
value: unknown
): value is StorageValidationFailedError {
return value instanceof StorageValidationFailedError;
}
export function isStorageAsyncValidateUnsupportedError(
value: unknown
): value is StorageAsyncValidateUnsupportedError {
return value instanceof StorageAsyncValidateUnsupportedError;
}
export function isStorageEntryDefaultsMismatchError(
value: unknown
): value is StorageEntryDefaultsMismatchError {
return value instanceof StorageEntryDefaultsMismatchError;
}
export function isStorageCookieServerRequiredError(
value: unknown
): value is StorageCookieServerRequiredError {
return value instanceof StorageCookieServerRequiredError;
}
export function isStorageEnvelopeInvalidVersionError(
value: unknown
): value is StorageEnvelopeInvalidVersionError {
return value instanceof StorageEnvelopeInvalidVersionError;
}
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
export function isStorageDisposedError(value: unknown): value is StorageDisposedError {
return value instanceof StorageDisposedError;
}

Powered by TurnKey Linux.