#2201 landed three moves this branch sits on top of. `bindSettingsScope` became `ctx.settingsScope.bind` on the Settings surface, so the section injects that service and the Remote face instead of importing a free function; the `SettingsScope` types moved into the runtime contract module, which is where this branch's `base`, `user`, and `unset` now live; and the client `credentials/changed` event became the forwarded owner event `credentials/updated`, which the web-search card subscribes to through `ctx.remote.$on`. The generated module graph crossed mermaid's 1000-edge render guard with this branch's 14 new edges. The guard doubles again, exactly as it did at 500 — the graph counts real package edges, and trimming them to fit a renderer default would make the document lie about the dependency set.
82 lines
3.5 KiB
TypeScript
82 lines
3.5 KiB
TypeScript
/**
|
|
* The settings-namespace scope contract. The type lives here, in the common
|
|
* dependency of every feature that owns a preference, while the implementation
|
|
* and its Host transport live with the Settings surface
|
|
* (`dsh-client-ui-settings`): a feature service accepts a scope through
|
|
* `attachSettings` without depending on the surface that binds it, which would
|
|
* otherwise close a reference cycle.
|
|
*/
|
|
|
|
/** Client-side sync state of one settings namespace. */
|
|
export interface SettingsScopeSnapshot<T> {
|
|
/**
|
|
* `loading` until the first accepted section, `ready` while one stands, and
|
|
* `unavailable` when the namespace is not exposed to this client or the
|
|
* connection keeps preferences process-local (memory mode).
|
|
*/
|
|
status: 'loading' | 'ready' | 'unavailable'
|
|
/** Last accepted schema-resolved section; undefined before the first acceptance. */
|
|
value: T | undefined
|
|
/**
|
|
* Composition layer the Host resolved {@link value} over, when the owning
|
|
* plugin declared one. What a field reverts to once cleared.
|
|
*/
|
|
base: unknown
|
|
/**
|
|
* Raw user layer as stored, when one exists. A field's PRESENCE here is what
|
|
* marks it overridden — an override whose value equals the composition
|
|
* default is still an override, and comparing values could not see it.
|
|
*/
|
|
user: unknown
|
|
/** Namespace revision fencing the next write; undefined before the first Host view. */
|
|
revision: number | undefined
|
|
/** Whether the Host document accepts writes; memory mode never does. */
|
|
writable: boolean
|
|
/** `host` syncs with the Host document; `memory` keeps a remote browser process-local. */
|
|
mode: 'host' | 'memory'
|
|
}
|
|
|
|
/** Domain-owned description of one settings namespace consumed by a browser plugin. */
|
|
export interface SettingsScopeSpec<T> {
|
|
/** Settings namespace registered by the owning Host plugin. */
|
|
namespace: string
|
|
/**
|
|
* Narrow one wire section; undefined keeps the last accepted value. The
|
|
* default validates the section against the namespace's own serialized wire
|
|
* schema, so domains add a decoder only to narrow beyond that schema.
|
|
*/
|
|
decode?: (section: unknown) => T | undefined
|
|
}
|
|
|
|
/**
|
|
* Reactive owner handle over one namespace's durable section — the browser
|
|
* mirror of the Host-side `SettingsScope` owner seam. Domain services read
|
|
* and observe the snapshot and route explicit user choices through `set`.
|
|
*/
|
|
export interface SettingsScope<T> {
|
|
/** @returns the current sync snapshot (stable reference until the next change). */
|
|
getSnapshot(): SettingsScopeSnapshot<T>
|
|
/**
|
|
* Observe snapshot replacements.
|
|
* @param listener - invoked after each snapshot change.
|
|
* @returns the disposer removing this listener.
|
|
*/
|
|
subscribe(listener: () => void): () => void
|
|
/**
|
|
* Queue one field write. Rapid writes preserve mutation order, each carries
|
|
* the latest known namespace revision, and only the latest settlement may
|
|
* publish; a rejected or failed latest write reloads Host state instead.
|
|
* @param field - scalar field inside the namespace section.
|
|
* @param value - JSON-shaped value selected by the user.
|
|
* @returns settlement after the write and any latest-write recovery read.
|
|
*/
|
|
set(field: string, value: unknown): Promise<void>
|
|
/**
|
|
* Queue one field clear, so the field re-inherits the composition layer.
|
|
* Shares {@link set}'s ordering, revision, and recovery contract.
|
|
* @param field - scalar field inside the namespace section.
|
|
* @returns settlement after the clear and any latest-write recovery read.
|
|
*/
|
|
unset(field: string): Promise<void>
|
|
}
|