Files
deepseek-harness/packages/storage/storage/src/index.ts
imccyu 2e986ee1e3 style(storage,workspace): satisfy the repository lint gate
eslint --fix formatting sweep plus the manual residue: sync method
bodies drop async behind Promise-returning signatures (the sqlite unit
routes primitives through a settle() guard preserving the never-throws-
synchronously contract), catch callbacks type their reason as unknown,
loadAll's global slot is plain unknown (null semantics stay in JSDoc),
a non-null assertion becomes a narrowing, and unsafe any assignments in
tests gain explicit types. One justified eslint-disable for
prefer-promise-reject-errors follows the core/session precedent —
wrapping would discard the original StorageError code.
2026-07-25 11:08:04 +08:00

87 lines
2.9 KiB
TypeScript

/**
* Storage hub (`ctx.storage`): a named backend registry plus mounted
* data-form facilities. The hub itself performs no IO — backends own media,
* data forms (the domain layer first) own semantics.
* @module @deepseek-ai/dsh-storage
*/
import { Context, Service } from 'cordis'
import { StorageError } from './error.ts'
import { BackendRegistry } from './registry.ts'
export { BackendRegistry } from './registry.ts'
export { StorageError } from './error.ts'
export type { StorageErrorCode } from './error.ts'
export { UNIT_NAME_RE } from './backend.ts'
export type { StorageBackend, KvFacet, KvUnit, KvUnitDescriptor } from './backend.ts'
declare module 'cordis' {
interface Context {
storage: Storage
}
}
/**
* Data forms mountable on the hub, keyed by form name. Form owners extend
* this map via declaration merging (the domain layer merges
* `domain: DomainFacility`) and mount the facility in their `apply`.
*/
export interface StorageForms {}
/**
* The storage hub service. Backends register under `backend`; data forms
* mount under their `StorageForms` key and are reached as `ctx.storage.<form>`.
*/
export class Storage extends Service {
/** Named backend table; multiple backends stay mounted side by side. */
readonly backend = new BackendRegistry()
private readonly forms = new Map<keyof StorageForms, unknown>()
constructor(ctx: Context) {
super(ctx, 'storage')
}
/**
* Mount a data-form facility on the hub. Mounting is an effect: the
* returned disposer unmounts the form.
* @param form - Form key declared in {@link StorageForms}.
* @param facility - The facility instance to expose.
* @returns the disposer that unmounts the form.
*/
mount<K extends keyof StorageForms>(form: K, facility: StorageForms[K]): () => void {
if (this.forms.has(form)) {
throw new StorageError('duplicate-mount', `storage form '${String(form)}' is already mounted`)
}
this.forms.set(form, facility)
return () => {
// Same stale-disposer guard as BackendRegistry.register.
if (this.forms.get(form) === facility) {
this.forms.delete(form)
}
}
}
/**
* Resolve a mounted data form.
* @param form - Form key declared in {@link StorageForms}.
* @returns the mounted facility.
*/
form<K extends keyof StorageForms>(form: K): StorageForms[K] {
if (!this.forms.has(form)) {
throw new StorageError('form-not-mounted', `storage form '${String(form)}' is not mounted`)
}
return this.forms.get(form) as StorageForms[K]
}
/** Domain data form; present once the domain layer plugin is loaded. */
get domain(): StorageForms extends { domain: infer D } ? D : never {
return this.form('domain' as keyof StorageForms)
}
}
// Service packages default-export their service class and nothing else
// plugin-shaped (packages/AGENTS.md): mixing a default export with a
// function-plugin `apply` makes the Loader drop the plugin namespace.
export default Storage