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.

96 lines
3.1 KiB

import {
createActivePrefs,
createPrefsStorageBridge,
type ActivePrefs,
type EnginePrefsOptions,
type PrefsIntentStorage,
type PrefsStorageBridge,
type PrefsStorageOp
} from '$prefs';
import type { AppServiceFactory } from '../services.ts';
/**
* Options for `defineActivePrefs`. A thin alias of `EnginePrefsOptions`
* — exported here so callers can `import { type DefineActivePrefsOptions }
* from '$active-app'` without reaching into `$prefs`.
*/
export type DefineActivePrefsOptions = EnginePrefsOptions;
/**
* Options for `defineActivePrefsWithStorage`. Adds a `PrefsIntentStorage`
* port and an optional error reporter on top of the base prefs config.
*/
export interface DefineActivePrefsWithStorageOptions extends DefineActivePrefsOptions {
readonly storage: PrefsIntentStorage;
readonly onError?: (error: unknown, op: PrefsStorageOp) => void;
}
/**
* `defineActivePrefs(options)` produces a service factory for the
* `prefs` slot. Adds the runtime to the App schema as
* `App.prefs: ActivePrefs`, where downstream service factories
* (`defineActiveLang`, `defineActiveFormat`, `defineActiveFrontend`)
* read capability sources via the helpers in `$prefs/sources`.
*
* No core dependencies: the engine is pure data — capabilities,
* environment and intent are passed in by the caller. Environment
* detection lives in `$prefs/adapters/*` and is invoked by the
* application's bootstrap code, not by this factory.
*
* `initMode: 'immediate'` because consumer factories ask for `prefs`
* via `serviceDependencies` at construction time; deferring the build
* would make the dependency graph order-sensitive.
*/
export function defineActivePrefs(
options: DefineActivePrefsOptions
): AppServiceFactory<'prefs', readonly [], readonly [], ActivePrefs> {
return {
name: 'prefs',
coreDependencies: [],
initMode: 'immediate',
create(): ActivePrefs {
return createActivePrefs(options);
},
dispose(instance) {
instance.dispose();
}
};
}
/**
* `defineActivePrefsWithStorage(options)` is the storage-bundled variant
* of `defineActivePrefs`. Bootstraps the engine and immediately attaches
* a `PrefsStorageBridge` so persisted intent loads on hydrate and every
* subsequent commit is saved back. Bridge teardown runs before the
* engine disposes.
*
* Use this when the application has a `PrefsIntentStorage` ready to
* inject (typically a thin adapter over `arts/storage`). Apps that wire
* persistence by hand can stay on `defineActivePrefs(...)` and call
* `createPrefsStorageBridge(...)` themselves.
*/
export function defineActivePrefsWithStorage(
options: DefineActivePrefsWithStorageOptions
): AppServiceFactory<'prefs', readonly [], readonly [], ActivePrefs> {
let bridge: PrefsStorageBridge | undefined;
return {
name: 'prefs',
coreDependencies: [],
initMode: 'immediate',
create(): ActivePrefs {
const prefs = createActivePrefs(options);
bridge = createPrefsStorageBridge({
engine: prefs,
storage: options.storage,
onError: options.onError
});
return prefs;
},
dispose(instance) {
bridge?.dispose();
bridge = undefined;
instance.dispose();
}
};
}

Powered by TurnKey Linux.