doxum 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -4
- package/dist/advanced-DgRnyRAc.js +233 -0
- package/dist/advanced-DgRnyRAc.js.map +1 -0
- package/dist/advanced-Dgu8-bPS.cjs +274 -0
- package/dist/advanced-Dgu8-bPS.cjs.map +1 -0
- package/dist/advanced-GTwIWcn6.d.cts +138 -0
- package/dist/advanced-c0F3gpLG.d.ts +138 -0
- package/dist/advanced.cjs +2 -165
- package/dist/advanced.d.cts +2 -42
- package/dist/advanced.d.ts +2 -42
- package/dist/advanced.js +1 -164
- package/dist/index.cjs +1195 -874
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -4
- package/dist/index.d.ts +26 -4
- package/dist/index.js +1192 -871
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +5 -10
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -8
- package/dist/react.d.ts +6 -8
- package/dist/react.js +6 -10
- package/dist/react.js.map +1 -1
- package/package.json +3 -2
- package/skills/doxum-runtime/SKILL.md +2 -1
- package/skills/doxum-runtime/references/patterns.en.md +4 -4
- package/skills/doxum-runtime/references/patterns.zh-CN.md +2 -2
- package/skills/doxum-runtime/references/projections.en.md +19 -4
- package/skills/doxum-runtime/references/projections.zh-CN.md +15 -4
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.js.map +0 -1
- package/dist/definition-C__VJqA4.d.cts +0 -136
- package/dist/definition-Dc1Udkop.d.ts +0 -136
- package/dist/definition-Z6TagMup.cjs +0 -107
- package/dist/definition-Z6TagMup.cjs.map +0 -1
- package/dist/definition-c6XQXzvK.js +0 -72
- package/dist/definition-c6XQXzvK.js.map +0 -1
package/dist/react.cjs
CHANGED
|
@@ -5,11 +5,8 @@ let react = require("react");
|
|
|
5
5
|
//#region react/src/hooks.ts
|
|
6
6
|
const ProjectionContext = (0, react.createContext)(void 0);
|
|
7
7
|
const ProjectionProvider = ProjectionContext.Provider;
|
|
8
|
-
function useProjection(projection,
|
|
9
|
-
const
|
|
10
|
-
const selector = typeof selectorOrRuntime === "function" ? selectorOrRuntime : void 0;
|
|
11
|
-
const equality = typeof equalityOrRuntime === "function" ? equalityOrRuntime : Object.is;
|
|
12
|
-
const owner = (selector ? suppliedRuntime : void 0) ?? (selector ? equalityOrRuntime && typeof equalityOrRuntime !== "function" ? equalityOrRuntime : void 0 : void 0) ?? (selector ? context : typeof selectorOrRuntime === "object" ? selectorOrRuntime : context);
|
|
8
|
+
function useProjection(projection, selector, equality = Object.is) {
|
|
9
|
+
const owner = (0, react.useContext)(ProjectionContext);
|
|
13
10
|
if (!owner) throw new Error("ProjectionRuntime is required.");
|
|
14
11
|
return useReadable((0, react.useMemo)(() => selector ? owner.readable(projection, selector, equality) : owner.readable(projection), [
|
|
15
12
|
equality,
|
|
@@ -18,11 +15,10 @@ function useProjection(projection, selectorOrRuntime, equalityOrRuntime, supplie
|
|
|
18
15
|
selector
|
|
19
16
|
]));
|
|
20
17
|
}
|
|
21
|
-
function useInput(input
|
|
22
|
-
const
|
|
23
|
-
const owner = runtime ?? context;
|
|
18
|
+
function useInput(input) {
|
|
19
|
+
const owner = (0, react.useContext)(ProjectionContext);
|
|
24
20
|
if (!owner) throw new Error("ProjectionRuntime is required.");
|
|
25
|
-
const value = useProjection(input
|
|
21
|
+
const value = useProjection(input);
|
|
26
22
|
const set = (0, react.useCallback)((next) => owner.set(input, next), [input, owner]);
|
|
27
23
|
return (0, react.useMemo)(() => [value, set], [set, value]);
|
|
28
24
|
}
|
|
@@ -123,7 +119,6 @@ function useHistory(history) {
|
|
|
123
119
|
]);
|
|
124
120
|
}
|
|
125
121
|
//#endregion
|
|
126
|
-
exports.ProjectionContext = ProjectionContext;
|
|
127
122
|
exports.ProjectionProvider = ProjectionProvider;
|
|
128
123
|
exports.useDocumentSelector = useDocumentSelector;
|
|
129
124
|
exports.useHistory = useHistory;
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.cjs","names":["sameTarget","track","subscribeDependencies"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n Projection,\n Input,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionRuntime | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(\n projection: Projection<T, unknown>,\n runtime?: ProjectionRuntime\n): T;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selectorOrRuntime?: ((value: T) => R) | ProjectionRuntime,\n equalityOrRuntime?: ((previous: R, next: R) => boolean) | ProjectionRuntime,\n suppliedRuntime?: ProjectionRuntime\n): T | R {\n const context = useContext(ProjectionContext);\n const selector = typeof selectorOrRuntime === 'function' ? selectorOrRuntime : undefined;\n const equality = typeof equalityOrRuntime === 'function' ? equalityOrRuntime : Object.is;\n const owner =\n (selector ? suppliedRuntime : undefined) ??\n (selector\n ? equalityOrRuntime && typeof equalityOrRuntime !== 'function'\n ? equalityOrRuntime\n : undefined\n : undefined) ??\n (selector ? context : typeof selectorOrRuntime === 'object' ? selectorOrRuntime : context);\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const readable = useMemo(\n () => (selector ? owner.readable(projection, selector, equality) : owner.readable(projection)),\n [equality, owner, projection, selector]\n );\n return useReadable(readable as Readable<T | R>);\n}\n\nexport function useInput<T>(\n input: Input<T>,\n runtime?: ProjectionRuntime\n): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = runtime ?? context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input, owner);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":";;;;;AAsBA,MAAa,qBAAA,GAAA,MAAA,eAAiE,KAAA,EAAU;AACxF,MAAa,qBAAqB,kBAAkB;AAiBpD,SAAgB,cACd,YACA,mBACA,mBACA,iBACO;CACP,MAAM,WAAA,GAAA,MAAA,YAAqB,kBAAkB;CAC7C,MAAM,WAAW,OAAO,sBAAsB,aAAa,oBAAoB,KAAA;CAC/E,MAAM,WAAW,OAAO,sBAAsB,aAAa,oBAAoB,OAAO;CACtF,MAAM,SACH,WAAW,kBAAkB,KAAA,OAC7B,WACG,qBAAqB,OAAO,sBAAsB,aAChD,oBACA,KAAA,IACF,KAAA,OACH,WAAW,UAAU,OAAO,sBAAsB,WAAW,oBAAoB;AACpF,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC;AAK7D,QAAO,aAAA,GAAA,MAAA,eAHE,WAAW,MAAM,SAAS,YAAY,UAAU,SAAS,GAAG,MAAM,SAAS,WAAW,EAC7F;EAAC;EAAU;EAAO;EAAY;EAAS,CAEd,CAAoB;;AAGjD,SAAgB,SACd,OACA,SACkC;CAClC,MAAM,WAAA,GAAA,MAAA,YAAqB,kBAAkB;CAC7C,MAAM,QAAQ,WAAW;AACzB,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,iCAAiC;CAC7D,MAAM,QAAQ,cAAc,OAAO,MAAM;CACzC,MAAM,OAAA,GAAA,MAAA,cAAmB,SAAY,MAAM,IAAI,OAAO,KAAK,EAAE,CAAC,OAAO,MAAM,CAAC;AAC5E,SAAA,GAAA,MAAA,eAAqB,CAAC,OAAO,IAAI,EAAW,CAAC,KAAK,MAAM,CAAC;;AAc3D,MAAM,YAAe,UAAa,SAAqB,OAAO,GAAG,UAAU,KAAK;AAChF,MAAM,eACJ,MACA,UACY;AACZ,KAAI,KAAK,WAAW,MAAM,OAAQ,QAAO;AACzC,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS,EAChD,KAAI,CAACA,qBAAAA,KAAW,KAAK,QAAQ,MAAM,OAAO,CAAE,QAAO;AACrD,QAAO;;AAGT,SAAgB,oBACd,SACA,UACA,SACS;CACT,MAAM,WAAW,SAAS,WAAW;CACrC,MAAM,SAAA,GAAA,MAAA,QAA4D,KAAA,EAAU;CAC5E,MAAM,eAAA,GAAA,MAAA,QAQJ,KAAA,EAAU;CAEZ,MAAM,QAAA,GAAA,MAAA,eAAqB;EAGzB,IAAI;AACJ,eAAsB;GACpB,MAAM,WAAW,QAAQ,UAAU;AACnC,OAAI,UAAU,aAAa,SAAU,QAAO,SAAS;GACrD,MAAM,YAAYC,oBAAAA,MAAM,SAAS,SAAS;GAC1C,MAAM,WAAW,MAAM;GACvB,MAAM,QACJ,YAAY,SAAS,YAAY,WAAW,SAAS,SAAS,OAAO,UAAU,MAAM,GACjF,SAAS,QACT,UAAU;AAChB,SAAM,UAAU;IAAE;IAAS;IAAO,SAAS,UAAU;IAAS;AAC9D,cAAW;IAAE;IAAU;IAAO;AAC9B,UAAO;;IAER;EAAC;EAAU;EAAS;EAAS,CAAC;CAEjC,MAAM,aAAA,GAAA,MAAA,cACH,aAAyB;AACxB,QAAM;EACN,IAAI,UAAU,MAAM,SAAS,WAAW,EAAE;EAC1C,IAAI,oBAAgC,KAAA;EACpC,MAAM,gBAAgB;AACpB,OAAI,QAAQ,WAAW,EAAG,cAAa,KAAA;AACvC,UAAOC,qBAAAA,sBAAsB,SAAS,SAAS,SAAS;;EAE1D,MAAM,iBAAiB;GACrB,MAAM,WAAW,MAAM;GACvB,MAAM,OAAO,MAAM;GACnB,MAAM,cAAc,MAAM,SAAS,WAAW,EAAE;AAChD,OAAI,CAAC,YAAY,SAAS,YAAY,EAAE;AACtC,iBAAa;AACb,cAAU;AACV,kBAAc,SAAS;;AAEzB,OAAI,YAAY,CAAC,OAAO,GAAG,SAAS,OAAO,KAAK,CAAE,WAAU;;AAE9D,gBAAc,SAAS;AACvB,eAAa,aAAa;IAE5B,CAAC,MAAM,QAAQ,CAChB;CAED,MAAM,SAAS,SAAS;AAexB,SAAA,GAAA,MAAA,sBAA4B,WAAW,OAAA,GAAA,MAAA,mBAdO;EAC5C,MAAM,WAAW,YAAY;AAC7B,MACE,YACA,SAAS,WAAW,UACpB,SAAS,YAAY,WACrB,SAAS,aAAa,SAEtB,QAAO,SAAS;EAClB,MAAM,QAAQ,SAAS,QAAQ,GAAG,MAAM;AACxC,cAAY,UAAU;GAAE;GAAS;GAAU,QAAQ;GAAQ;GAAO;AAClE,SAAO;IACN;EAAC;EAAM;EAAQ;EAAS;EAAS,CAEmB,CAAC;;AAG1D,SAAgB,YAAe,UAA0B;CACvD,MAAM,aAAA,GAAA,MAAA,cAAyB,aAAyB,SAAS,UAAU,SAAS,EAAE,CAAC,SAAS,CAAC;CACjG,MAAM,QAAA,GAAA,MAAA,mBAAyB,SAAS,SAAS,EAAE,CAAC,SAAS,CAAC;AAC9D,SAAA,GAAA,MAAA,sBAA4B,WAAW,MAAM,KAAK;;AAGpD,SAAgB,WAAoB,SAGlC;CACA,MAAM,aAAA,GAAA,MAAA,cAAyB,aAAyB,QAAQ,UAAU,SAAS,EAAE,CAAC,QAAQ,CAAC;CAC/F,MAAM,QAAA,GAAA,MAAA,mBAAyB,QAAQ,SAAS,EAAE,CAAC,QAAQ,CAAC;CAC5D,MAAM,SAAA,GAAA,MAAA,sBAA6B,WAAW,MAAM,KAAK;CACzD,MAAM,QAAA,GAAA,MAAA,mBAAyB,QAAQ,MAAM,EAAE,CAAC,QAAQ,CAAC;CACzD,MAAM,QAAA,GAAA,MAAA,mBAAyB,QAAQ,MAAM,EAAE,CAAC,QAAQ,CAAC;AAEzD,SAAA,GAAA,MAAA,gBAAsB;EAAE,GAAG;EAAO;EAAM;EAAM,GAAG;EAAC;EAAM;EAAO;EAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"react.cjs","names":["sameTarget","track","subscribeDependencies"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n ProjectionScope,\n Projection,\n Input,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nconst ProjectionContext = createContext<ProjectionRuntime | ProjectionScope | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(projection: Projection<T, unknown>): T;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector?: (value: T) => R,\n equality: (previous: R, next: R) => boolean = Object.is\n): T | R {\n const context = useContext(ProjectionContext);\n const owner = context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const readable = useMemo(\n () => (selector ? owner.readable(projection, selector, equality) : owner.readable(projection)),\n [equality, owner, projection, selector]\n );\n return useReadable(readable as Readable<T | R>);\n}\n\nexport function useInput<T>(input: Input<T>): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
|
package/dist/react.d.cts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import * as _$react from "react";
|
|
2
|
-
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
|
|
2
|
+
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, ProjectionScope, Readable } from "doxum";
|
|
3
3
|
|
|
4
4
|
//#region react/src/hooks.d.ts
|
|
5
|
-
declare const
|
|
6
|
-
declare
|
|
7
|
-
declare function useProjection<T>(projection: Projection<T, unknown>,
|
|
8
|
-
declare function
|
|
9
|
-
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean, runtime?: ProjectionRuntime): R;
|
|
10
|
-
declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
|
|
5
|
+
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | ProjectionScope | undefined>;
|
|
6
|
+
declare function useProjection<T>(projection: Projection<T, unknown>): T;
|
|
7
|
+
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean): R;
|
|
8
|
+
declare function useInput<T>(input: Input<T>): readonly [T, (value: T) => void];
|
|
11
9
|
type DocumentSelectorOptions<TResult> = {
|
|
12
10
|
readonly isEqual?: (previous: TResult, next: TResult) => boolean;
|
|
13
11
|
readonly server?: () => TResult;
|
|
@@ -19,5 +17,5 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
|
|
|
19
17
|
redo(): OperationResult<TCommit>;
|
|
20
18
|
};
|
|
21
19
|
//#endregion
|
|
22
|
-
export { type DocumentSelectorOptions,
|
|
20
|
+
export { type DocumentSelectorOptions, ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
|
|
23
21
|
//# sourceMappingURL=react.d.cts.map
|
package/dist/react.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import * as _$react from "react";
|
|
2
|
-
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
|
|
2
|
+
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, ProjectionScope, Readable } from "doxum";
|
|
3
3
|
|
|
4
4
|
//#region react/src/hooks.d.ts
|
|
5
|
-
declare const
|
|
6
|
-
declare
|
|
7
|
-
declare function useProjection<T>(projection: Projection<T, unknown>,
|
|
8
|
-
declare function
|
|
9
|
-
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean, runtime?: ProjectionRuntime): R;
|
|
10
|
-
declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
|
|
5
|
+
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | ProjectionScope | undefined>;
|
|
6
|
+
declare function useProjection<T>(projection: Projection<T, unknown>): T;
|
|
7
|
+
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean): R;
|
|
8
|
+
declare function useInput<T>(input: Input<T>): readonly [T, (value: T) => void];
|
|
11
9
|
type DocumentSelectorOptions<TResult> = {
|
|
12
10
|
readonly isEqual?: (previous: TResult, next: TResult) => boolean;
|
|
13
11
|
readonly server?: () => TResult;
|
|
@@ -19,5 +17,5 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
|
|
|
19
17
|
redo(): OperationResult<TCommit>;
|
|
20
18
|
};
|
|
21
19
|
//#endregion
|
|
22
|
-
export { type DocumentSelectorOptions,
|
|
20
|
+
export { type DocumentSelectorOptions, ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
|
|
23
21
|
//# sourceMappingURL=react.d.ts.map
|
package/dist/react.js
CHANGED
|
@@ -4,11 +4,8 @@ import { createContext, useCallback, useContext, useMemo, useRef, useSyncExterna
|
|
|
4
4
|
//#region react/src/hooks.ts
|
|
5
5
|
const ProjectionContext = createContext(void 0);
|
|
6
6
|
const ProjectionProvider = ProjectionContext.Provider;
|
|
7
|
-
function useProjection(projection,
|
|
8
|
-
const
|
|
9
|
-
const selector = typeof selectorOrRuntime === "function" ? selectorOrRuntime : void 0;
|
|
10
|
-
const equality = typeof equalityOrRuntime === "function" ? equalityOrRuntime : Object.is;
|
|
11
|
-
const owner = (selector ? suppliedRuntime : void 0) ?? (selector ? equalityOrRuntime && typeof equalityOrRuntime !== "function" ? equalityOrRuntime : void 0 : void 0) ?? (selector ? context : typeof selectorOrRuntime === "object" ? selectorOrRuntime : context);
|
|
7
|
+
function useProjection(projection, selector, equality = Object.is) {
|
|
8
|
+
const owner = useContext(ProjectionContext);
|
|
12
9
|
if (!owner) throw new Error("ProjectionRuntime is required.");
|
|
13
10
|
return useReadable(useMemo(() => selector ? owner.readable(projection, selector, equality) : owner.readable(projection), [
|
|
14
11
|
equality,
|
|
@@ -17,11 +14,10 @@ function useProjection(projection, selectorOrRuntime, equalityOrRuntime, supplie
|
|
|
17
14
|
selector
|
|
18
15
|
]));
|
|
19
16
|
}
|
|
20
|
-
function useInput(input
|
|
21
|
-
const
|
|
22
|
-
const owner = runtime ?? context;
|
|
17
|
+
function useInput(input) {
|
|
18
|
+
const owner = useContext(ProjectionContext);
|
|
23
19
|
if (!owner) throw new Error("ProjectionRuntime is required.");
|
|
24
|
-
const value = useProjection(input
|
|
20
|
+
const value = useProjection(input);
|
|
25
21
|
const set = useCallback((next) => owner.set(input, next), [input, owner]);
|
|
26
22
|
return useMemo(() => [value, set], [set, value]);
|
|
27
23
|
}
|
|
@@ -122,6 +118,6 @@ function useHistory(history) {
|
|
|
122
118
|
]);
|
|
123
119
|
}
|
|
124
120
|
//#endregion
|
|
125
|
-
export {
|
|
121
|
+
export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
|
|
126
122
|
|
|
127
123
|
//# sourceMappingURL=react.js.map
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["sameTarget"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n Projection,\n Input,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nexport const ProjectionContext = createContext<ProjectionRuntime | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(\n projection: Projection<T, unknown>,\n runtime?: ProjectionRuntime\n): T;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean,\n runtime?: ProjectionRuntime\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selectorOrRuntime?: ((value: T) => R) | ProjectionRuntime,\n equalityOrRuntime?: ((previous: R, next: R) => boolean) | ProjectionRuntime,\n suppliedRuntime?: ProjectionRuntime\n): T | R {\n const context = useContext(ProjectionContext);\n const selector = typeof selectorOrRuntime === 'function' ? selectorOrRuntime : undefined;\n const equality = typeof equalityOrRuntime === 'function' ? equalityOrRuntime : Object.is;\n const owner =\n (selector ? suppliedRuntime : undefined) ??\n (selector\n ? equalityOrRuntime && typeof equalityOrRuntime !== 'function'\n ? equalityOrRuntime\n : undefined\n : undefined) ??\n (selector ? context : typeof selectorOrRuntime === 'object' ? selectorOrRuntime : context);\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const readable = useMemo(\n () => (selector ? owner.readable(projection, selector, equality) : owner.readable(projection)),\n [equality, owner, projection, selector]\n );\n return useReadable(readable as Readable<T | R>);\n}\n\nexport function useInput<T>(\n input: Input<T>,\n runtime?: ProjectionRuntime\n): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = runtime ?? context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input, owner);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"react.js","names":["sameTarget"],"sources":["../react/src/hooks.ts"],"sourcesContent":["import type {\n DocumentReadable,\n ObjectNode,\n DocumentSelector,\n HistoryState,\n LocalHistory,\n OperationResult,\n Readable,\n ProjectionRuntime,\n ProjectionScope,\n Projection,\n Input,\n} from 'doxum';\nimport { track, subscribeDependencies, sameTarget, type ImpactTarget } from 'doxum/integration';\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\nconst ProjectionContext = createContext<ProjectionRuntime | ProjectionScope | undefined>(undefined);\nexport const ProjectionProvider = ProjectionContext.Provider;\n\nexport function useProjection<T>(projection: Projection<T, unknown>): T;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector: (value: T) => R,\n equality?: (previous: R, next: R) => boolean\n): R;\nexport function useProjection<T, R>(\n projection: Projection<T, unknown>,\n selector?: (value: T) => R,\n equality: (previous: R, next: R) => boolean = Object.is\n): T | R {\n const context = useContext(ProjectionContext);\n const owner = context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const readable = useMemo(\n () => (selector ? owner.readable(projection, selector, equality) : owner.readable(projection)),\n [equality, owner, projection, selector]\n );\n return useReadable(readable as Readable<T | R>);\n}\n\nexport function useInput<T>(input: Input<T>): readonly [T, (value: T) => void] {\n const context = useContext(ProjectionContext);\n const owner = context;\n if (!owner) throw new Error('ProjectionRuntime is required.');\n const value = useProjection(input);\n const set = useCallback((next: T) => owner.set(input, next), [input, owner]);\n return useMemo(() => [value, set] as const, [set, value]);\n}\n\nexport type DocumentSelectorOptions<TResult> = {\n readonly isEqual?: (previous: TResult, next: TResult) => boolean;\n readonly server?: () => TResult;\n};\n\ntype SelectorCache<TSchema extends ObjectNode, TResult> = {\n readonly runtime: DocumentReadable<TSchema>;\n readonly value: TResult;\n readonly targets: readonly ImpactTarget<unknown>[];\n};\n\nconst objectIs = <T>(previous: T, next: T): boolean => Object.is(previous, next);\nconst sameTargets = (\n left: readonly ImpactTarget<unknown>[],\n right: readonly ImpactTarget<unknown>[]\n): boolean => {\n if (left.length !== right.length) return false;\n for (let index = 0; index < left.length; index += 1)\n if (!sameTarget(left[index], right[index])) return false;\n return true;\n};\n\nexport function useDocumentSelector<TSchema extends ObjectNode, TResult>(\n runtime: DocumentReadable<TSchema>,\n selector: DocumentSelector<TSchema, TResult>,\n options?: DocumentSelectorOptions<TResult>\n): TResult {\n const equality = options?.isEqual ?? objectIs;\n const cache = useRef<SelectorCache<TSchema, TResult> | undefined>(undefined);\n const serverCache = useRef<\n | {\n readonly runtime: DocumentReadable<TSchema>;\n readonly selector: DocumentSelector<TSchema, TResult>;\n readonly source: (() => TResult) | undefined;\n readonly value: TResult;\n }\n | undefined\n >(undefined);\n\n const read = useMemo(() => {\n // Each selector closure owns its revision cache, including inline selectors\n // that allocate arrays or objects. Equality only compares distinct snapshots.\n let snapshot: { readonly revision: number; readonly value: TResult } | undefined;\n return (): TResult => {\n const revision = runtime.revision();\n if (snapshot?.revision === revision) return snapshot.value;\n const selection = track(runtime, selector);\n const previous = cache.current;\n const value =\n previous && previous.runtime === runtime && equality(previous.value, selection.value)\n ? previous.value\n : selection.value;\n cache.current = { runtime, value, targets: selection.targets };\n snapshot = { revision, value };\n return value;\n };\n }, [equality, runtime, selector]);\n\n const subscribe = useCallback(\n (listener: () => void) => {\n read();\n let targets = cache.current?.targets ?? [];\n let unsubscribe: () => void = () => undefined;\n const install = () => {\n if (targets.length === 0) return () => undefined;\n return subscribeDependencies(runtime, targets, onCommit);\n };\n const onCommit = () => {\n const previous = cache.current;\n const next = read();\n const nextTargets = cache.current?.targets ?? [];\n if (!sameTargets(targets, nextTargets)) {\n unsubscribe();\n targets = nextTargets;\n unsubscribe = install();\n }\n if (previous && !Object.is(previous.value, next)) listener();\n };\n unsubscribe = install();\n return () => unsubscribe();\n },\n [read, runtime]\n );\n\n const server = options?.server;\n const readServer = useCallback((): TResult => {\n const previous = serverCache.current;\n if (\n previous &&\n previous.source === server &&\n previous.runtime === runtime &&\n previous.selector === selector\n )\n return previous.value;\n const value = server ? server() : read();\n serverCache.current = { runtime, selector, source: server, value };\n return value;\n }, [read, server, runtime, selector]);\n\n return useSyncExternalStore(subscribe, read, readServer);\n}\n\nexport function useReadable<T>(readable: Readable<T>): T {\n const subscribe = useCallback((listener: () => void) => readable.subscribe(listener), [readable]);\n const read = useCallback(() => readable.current(), [readable]);\n return useSyncExternalStore(subscribe, read, read);\n}\n\nexport function useHistory<TCommit>(history: LocalHistory<TCommit>): HistoryState & {\n undo(): OperationResult<TCommit>;\n redo(): OperationResult<TCommit>;\n} {\n const subscribe = useCallback((listener: () => void) => history.subscribe(listener), [history]);\n const read = useCallback(() => history.current(), [history]);\n const state = useSyncExternalStore(subscribe, read, read);\n const undo = useCallback(() => history.undo(), [history]);\n const redo = useCallback(() => history.redo(), [history]);\n\n return useMemo(() => ({ ...state, undo, redo }), [redo, state, undo]);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doxum",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Doxum is a typed runtime for complex mutable documents.",
|
|
@@ -87,7 +87,8 @@
|
|
|
87
87
|
"build": "tsdown --config tsdown.config.ts",
|
|
88
88
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
89
89
|
"test": "vitest run --config vitest.config.ts",
|
|
90
|
-
"check": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run test",
|
|
90
|
+
"check": "pnpm run format:check && pnpm run lint && pnpm run typecheck && pnpm run test && pnpm run check:projection-surface",
|
|
91
|
+
"check:projection-surface": "node scripts/check-projection-surface.mjs",
|
|
91
92
|
"bench": "vitest bench --config vitest.bench.config.ts",
|
|
92
93
|
"profile": "node --expose-gc --import tsx core/bench/profile.ts",
|
|
93
94
|
"format": "prettier --write --ignore-unknown .",
|
|
@@ -33,7 +33,8 @@ Before runtime changes read [invariants](references/invariants.en.md) or
|
|
|
33
33
|
Use tuple `derive` for pure values. Advanced `incremental` processors declare every
|
|
34
34
|
source, own any forward/reverse dependency indexes, derive from final batched source
|
|
35
35
|
state, and recover from resets internally. Core projections never track reads
|
|
36
|
-
automatically; React selectors do through `
|
|
36
|
+
automatically; React selectors do through `ProjectionProvider` and
|
|
37
|
+
`useProjection(projection, selector)`.
|
|
37
38
|
- Observer errors leave commits accepted. Do not retry as if they rolled back.
|
|
38
39
|
- Core stays framework-neutral; adapters use integration capabilities.
|
|
39
40
|
- Local sync owns browser persistence/leadership. Network conflict policy and
|
|
@@ -95,8 +95,8 @@ runtime.get(scaled);
|
|
|
95
95
|
const title = runtime.get(tasks).get(taskId);
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
`useProjection(projection, selector)` for keyed reads.
|
|
100
|
-
and setter. Advanced collection processors in `doxum/advanced` stage
|
|
101
|
-
`output.set/remove/order
|
|
98
|
+
Provide the Runtime through `ProjectionProvider`, then use `useProjection` for
|
|
99
|
+
projection definitions and `useProjection(projection, selector)` for keyed reads.
|
|
100
|
+
`useInput` returns a value and setter. Advanced collection processors in `doxum/advanced` stage
|
|
101
|
+
`output.set/remove/order` and use scoped previous/next reads. Processor
|
|
102
102
|
dependencies remain explicit even though React selectors track actual reads.
|
|
@@ -94,8 +94,8 @@ runtime.get(scaled);
|
|
|
94
94
|
const title = runtime.get(tasks).get(taskId);
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
React 使用 Runtime
|
|
97
|
+
React 使用 `ProjectionProvider` 提供 Runtime,再用 `useProjection` 读取 Projection,单键读取写成
|
|
98
98
|
`useProjection(projection, selector)`;`useInput` 返回值和 setter。高级集合 processor
|
|
99
99
|
从 `doxum/advanced` 引入,在同步 callback 中使用
|
|
100
|
-
`output.set/remove/order
|
|
100
|
+
`output.set/remove/order` 与 previous/next。Processor 依赖仍显式声明,
|
|
101
101
|
React selector 追踪只属于消费端。
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Projection Reference
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Root projection definitions are lazy and reusable; scoped definitions are lazy
|
|
4
|
+
and bound to one scope. The public core consists of
|
|
4
5
|
`Projection<T>`, `ProjectionRuntime`, `input`, `observe`, and tuple `derive`.
|
|
5
6
|
|
|
6
7
|
```ts
|
|
@@ -23,8 +24,8 @@ sources use `kind: 'value'` or `kind: 'collection'`; the caller still uses only
|
|
|
23
24
|
|
|
24
25
|
External events are smaller than Runtime contexts. A value event carries the new
|
|
25
26
|
`value` and `revision`; a collection event carries a stable `previous` read,
|
|
26
|
-
`revision`, and an optional
|
|
27
|
-
|
|
27
|
+
`revision`, and an optional `impact` hint. The Runtime derives the exact
|
|
28
|
+
`CollectionChange`; processors never receive the impact directly.
|
|
28
29
|
|
|
29
30
|
`derive(dependencies, compute, equality?)` takes a tuple. Dependencies are
|
|
30
31
|
explicit and fixed when the definition is created. Processors must not discover
|
|
@@ -37,10 +38,21 @@ runtime.get(projection);
|
|
|
37
38
|
const selected = runtime.readable(projection, value => value.get(id));
|
|
38
39
|
selected.subscribe(listener);
|
|
39
40
|
runtime.set(input, value);
|
|
41
|
+
runtime.update(collectionInput, draft => draft.set(id, value));
|
|
40
42
|
runtime.batch({ cause }, run);
|
|
43
|
+
const scope = runtime.scope();
|
|
44
|
+
scope.dispose();
|
|
41
45
|
runtime.dispose();
|
|
42
46
|
```
|
|
43
47
|
|
|
48
|
+
`input.collection<K, V>(initial?)` declares keyed Runtime-local state. Its
|
|
49
|
+
`update` draft has `get`, `has`, `set`, and `remove`; edits are synchronous and
|
|
50
|
+
atomic per callback, and a Runtime batch publishes one exact net
|
|
51
|
+
`CollectionChange`. A scope declares local inputs, derives, and incremental
|
|
52
|
+
processors through `scope.input`, `scope.derive`, and `scope.incremental`. They
|
|
53
|
+
depend directly on root projections in the same graph. Disposing the scope
|
|
54
|
+
releases local state and subscriptions without disposing its root dependencies.
|
|
55
|
+
|
|
44
56
|
The Runtime exposes no graph revision, item handle, rebuild or release operation;
|
|
45
57
|
only a `Readable`'s own publication revision is public for store integrations.
|
|
46
58
|
Runtime materialization, keyed storage, recovery and disposal are one owner.
|
|
@@ -67,10 +79,13 @@ dependencies receive `reset` or grouped `added`/`updated`/`removed` entries with
|
|
|
67
79
|
complete `before`/`after` values and optional `order.before`/`order.after`.
|
|
68
80
|
The initial build reports `reset` for collection dependencies. A committed batch
|
|
69
81
|
is already coalesced into one net transition.
|
|
82
|
+
Collection values inside `sources` are callback-local lazy `ReadonlyMap` views;
|
|
83
|
+
do not retain or return them. Keyed `get`/`has` avoids a scan, while iteration is
|
|
84
|
+
an explicit full-collection read.
|
|
70
85
|
|
|
71
86
|
`incremental.collection(...)` uses a separate collection processor protocol and additionally exposes borrowed
|
|
72
87
|
`previous`/`next` keyed reads and a callback-local `output` draft. Draft methods are
|
|
73
|
-
`set`, `remove`,
|
|
88
|
+
`set`, `remove`, and `order`; the Runtime validates and seals them after
|
|
74
89
|
the synchronous callback, computes keyed transitions and publishes one immutable
|
|
75
90
|
map-like value. Reset or fault recovery is internal.
|
|
76
91
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Projection 参考
|
|
2
2
|
|
|
3
|
-
Projection
|
|
3
|
+
根 Projection 定义惰性且可跨 Runtime 复用;scope 定义惰性但只属于其局部生命周期。默认入口包含 `Projection<T>`、
|
|
4
4
|
`ProjectionRuntime`、`input`、`observe` 和 tuple 形式的 `derive`。
|
|
5
5
|
|
|
6
6
|
```ts
|
|
@@ -22,7 +22,8 @@ source 通过 `kind: 'value'` 或 `kind: 'collection'` 区分语义,但调用
|
|
|
22
22
|
|
|
23
23
|
External event 不再复用 Runtime context:value event 提供新 `value` 和
|
|
24
24
|
`revision`;collection event 提供稳定的 `previous` read、`revision` 和可选的
|
|
25
|
-
|
|
25
|
+
`impact` hint。Runtime 自己计算精确的 `CollectionChange`,processor 不会直接收到
|
|
26
|
+
impact。
|
|
26
27
|
|
|
27
28
|
`derive(dependencies, compute, equality?)` 使用 tuple,依赖在定义创建时固定。
|
|
28
29
|
Processor 不能通过读取另一个 Projection 隐式建立图依赖。
|
|
@@ -34,10 +35,18 @@ runtime.get(projection);
|
|
|
34
35
|
const selected = runtime.readable(projection, value => value.get(id));
|
|
35
36
|
selected.subscribe(listener);
|
|
36
37
|
runtime.set(input, value);
|
|
38
|
+
runtime.update(collectionInput, draft => draft.set(id, value));
|
|
37
39
|
runtime.batch({ cause }, run);
|
|
40
|
+
const scope = runtime.scope();
|
|
41
|
+
scope.dispose();
|
|
38
42
|
runtime.dispose();
|
|
39
43
|
```
|
|
40
44
|
|
|
45
|
+
`input.collection<K, V>(initial?)` 声明 Runtime 本地 keyed 状态。`update` 的借用 draft
|
|
46
|
+
提供 `get`、`has`、`set`、`remove`;单次 callback 同步且原子,Runtime batch 发布一次
|
|
47
|
+
精确的净 `CollectionChange`。scope 用 `scope.input`、`scope.derive`、
|
|
48
|
+
`scope.incremental` 声明局部投影,直接依赖同一张图中的根投影;dispose 只释放局部状态和订阅。
|
|
49
|
+
|
|
41
50
|
Runtime graph revision、item handle、rebuild、release 都是内部事实,不是应用层操作;
|
|
42
51
|
只有 `Readable` 自己的 publication revision 为 store 集成保留为公开事实。
|
|
43
52
|
Materialization、keyed storage、故障恢复和释放只有一个 owner。
|
|
@@ -62,11 +71,13 @@ const doubled = incremental.collection([tasks], ({ sources, output }) => {
|
|
|
62
71
|
标量依赖为 `undefined`,集合依赖则是 `reset`,或带完整 `before`/`after` 值的
|
|
63
72
|
`added`/`updated`/`removed` 分组,并可选提供 `order.before`/`order.after`。初次
|
|
64
73
|
build 对集合依赖报告 `reset`;一次已提交的 batch 已经合并成一个净 transition。
|
|
74
|
+
`sources` 内的集合值是 callback-local 的惰性 `ReadonlyMap` 视图,不能保存或直接
|
|
75
|
+
返回。`get`/`has` 保持按 key 读取,迭代才显式扫描整个集合。
|
|
65
76
|
|
|
66
77
|
`incremental.collection(...)` 使用独立的 collection processor 协议,另外提供借用的
|
|
67
78
|
`previous`/`next` keyed read,以及
|
|
68
|
-
只在同步 callback 内有效的 `output` draft。Draft 只有 `set`、`remove`、`order
|
|
69
|
-
|
|
79
|
+
只在同步 callback 内有效的 `output` draft。Draft 只有 `set`、`remove`、`order`;
|
|
80
|
+
Runtime 在 callback 返回后校验并 seal,计算 keyed transitions,发布
|
|
70
81
|
一个不可变 map-like 值。reset 或故障恢复由 Runtime 内部完成。
|
|
71
82
|
|
|
72
83
|
## React selector 追踪
|
package/dist/advanced.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanced.cjs","names":["snapshot","defineIncrementalValue","defineIncrementalCollection"],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type {\n Projection,\n CollectionProjection,\n ProjectionChanges,\n ProjectionValues,\n PublicCollection,\n} from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionEntryTransition,\n CollectionRead,\n GraphSources,\n} from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = (context: IncrementalCollectionContext<D, K, V>) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\ntype RuntimeCollectionSource = {\n readonly ids: () => readonly string[];\n readonly previous: CollectionRead<string, unknown>;\n readonly reset: boolean;\n readonly change?: { readonly kind: 'reset' | 'incremental'; readonly orderChanged?: boolean };\n readonly transitions: () => readonly CollectionEntryTransition<string, unknown>[];\n};\nconst resetCollectionChange = Object.freeze({ kind: 'reset' as const });\ntype IncrementalCollectionChange = Extract<\n CollectionChange<string, unknown>,\n { readonly kind: 'incremental' }\n>;\n\nconst isCollectionSource = (source: unknown): source is RuntimeCollectionSource =>\n Boolean(\n source &&\n typeof source === 'object' &&\n 'ids' in source &&\n typeof (source as { readonly ids?: unknown }).ids === 'function' &&\n 'previous' in source &&\n 'transitions' in source &&\n typeof (source as { readonly transitions?: unknown }).transitions === 'function'\n );\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!isCollectionSource(source)) return undefined;\n if (source.reset || source.change?.kind === 'reset') return resetCollectionChange;\n const impact = source.change;\n if (!impact) return undefined;\n const added: IncrementalCollectionChange['added'][number][] = [];\n const updated: IncrementalCollectionChange['updated'][number][] = [];\n const removed: IncrementalCollectionChange['removed'][number][] = [];\n for (const transition of source.transitions()) {\n if (transition.kind === 'added')\n added.push({ key: transition.key, kind: transition.kind, after: transition.after });\n else if (transition.kind === 'updated') updated.push(transition);\n else removed.push({ key: transition.key, kind: transition.kind, before: transition.before });\n }\n const order = impact.orderChanged\n ? {\n before: Object.freeze([...source.previous.ids()]),\n after: Object.freeze([...source.ids()]),\n }\n : undefined;\n if (!added.length && !updated.length && !removed.length && !order) return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze(added),\n updated: Object.freeze(updated),\n removed: Object.freeze(removed),\n ...(order ? { order: Object.freeze(order) } : {}),\n });\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicInputs = (\n sources: Record<string, unknown>,\n initial = false\n): { readonly values: readonly unknown[]; readonly changes: readonly unknown[] } => {\n const values: unknown[] = [];\n const changes: unknown[] = [];\n for (const key of Object.keys(sources).sort(\n (left, right) => Number(left.slice(1)) - Number(right.slice(1))\n )) {\n const source = sources[key];\n values.push(publicSource(source));\n changes.push(\n initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source)\n );\n }\n return { values, changes };\n};\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<D, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: undefined,\n reset: true,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const publicInputsForUpdate = publicInputs(nextSources);\n const next = processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: current,\n reset: false,\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(input.sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) => {\n const publicInputsForUpdate = publicInputs(nextInput.sources);\n return processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\n });\n },\n };\n };\n return defineIncrementalCollection({ dependencies: dependencyMap, build: build as never });\n}\n\nexport const incremental = Object.assign(createIncrementalValue, {\n collection: createIncrementalCollection,\n});\n\nexport type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> =\n DependencyMap<D>;\n\nexport type { CollectionChange } from './contract';\n"],"mappings":"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"}
|
package/dist/advanced.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"advanced.js","names":[],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type {\n Projection,\n CollectionProjection,\n ProjectionChanges,\n ProjectionValues,\n PublicCollection,\n} from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionEntryTransition,\n CollectionRead,\n GraphSources,\n} from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = (context: IncrementalCollectionContext<D, K, V>) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\ntype RuntimeCollectionSource = {\n readonly ids: () => readonly string[];\n readonly previous: CollectionRead<string, unknown>;\n readonly reset: boolean;\n readonly change?: { readonly kind: 'reset' | 'incremental'; readonly orderChanged?: boolean };\n readonly transitions: () => readonly CollectionEntryTransition<string, unknown>[];\n};\nconst resetCollectionChange = Object.freeze({ kind: 'reset' as const });\ntype IncrementalCollectionChange = Extract<\n CollectionChange<string, unknown>,\n { readonly kind: 'incremental' }\n>;\n\nconst isCollectionSource = (source: unknown): source is RuntimeCollectionSource =>\n Boolean(\n source &&\n typeof source === 'object' &&\n 'ids' in source &&\n typeof (source as { readonly ids?: unknown }).ids === 'function' &&\n 'previous' in source &&\n 'transitions' in source &&\n typeof (source as { readonly transitions?: unknown }).transitions === 'function'\n );\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!isCollectionSource(source)) return undefined;\n if (source.reset || source.change?.kind === 'reset') return resetCollectionChange;\n const impact = source.change;\n if (!impact) return undefined;\n const added: IncrementalCollectionChange['added'][number][] = [];\n const updated: IncrementalCollectionChange['updated'][number][] = [];\n const removed: IncrementalCollectionChange['removed'][number][] = [];\n for (const transition of source.transitions()) {\n if (transition.kind === 'added')\n added.push({ key: transition.key, kind: transition.kind, after: transition.after });\n else if (transition.kind === 'updated') updated.push(transition);\n else removed.push({ key: transition.key, kind: transition.kind, before: transition.before });\n }\n const order = impact.orderChanged\n ? {\n before: Object.freeze([...source.previous.ids()]),\n after: Object.freeze([...source.ids()]),\n }\n : undefined;\n if (!added.length && !updated.length && !removed.length && !order) return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze(added),\n updated: Object.freeze(updated),\n removed: Object.freeze(removed),\n ...(order ? { order: Object.freeze(order) } : {}),\n });\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicInputs = (\n sources: Record<string, unknown>,\n initial = false\n): { readonly values: readonly unknown[]; readonly changes: readonly unknown[] } => {\n const values: unknown[] = [];\n const changes: unknown[] = [];\n for (const key of Object.keys(sources).sort(\n (left, right) => Number(left.slice(1)) - Number(right.slice(1))\n )) {\n const source = sources[key];\n values.push(publicSource(source));\n changes.push(\n initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source)\n );\n }\n return { values, changes };\n};\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<D, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: undefined,\n reset: true,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const publicInputsForUpdate = publicInputs(nextSources);\n const next = processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: current,\n reset: false,\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(input.sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) => {\n const publicInputsForUpdate = publicInputs(nextInput.sources);\n return processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\n });\n },\n };\n };\n return defineIncrementalCollection({ dependencies: dependencyMap, build: build as never });\n}\n\nexport const incremental = Object.assign(createIncrementalValue, {\n collection: createIncrementalCollection,\n});\n\nexport type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> =\n DependencyMap<D>;\n\nexport type { CollectionChange } from './contract';\n"],"mappings":"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"}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { J as Infer, L as CollectionId, R as CollectionNode, Z as ObjectNode, _ as Unsubscribe, et as PathValueOf, m as Synchronous, nt as SchemaPath, s as DocumentReadable, tt as ReadonlyValue, v as Readable, x as CollectionImpact, z as CollectionPath } from "./contract-XmKnroJq.cjs";
|
|
2
|
-
|
|
3
|
-
//#region core/src/projection/contract.d.ts
|
|
4
|
-
/** Opaque application metadata identifying the action that produced a source event. */
|
|
5
|
-
type Cause = unknown;
|
|
6
|
-
type BatchOptions = {
|
|
7
|
-
readonly cause?: Cause;
|
|
8
|
-
};
|
|
9
|
-
type CollectionEntryTransition<K extends string, V> = {
|
|
10
|
-
readonly key: K;
|
|
11
|
-
readonly kind: 'added';
|
|
12
|
-
readonly before: undefined;
|
|
13
|
-
readonly after: V;
|
|
14
|
-
} | {
|
|
15
|
-
readonly key: K;
|
|
16
|
-
readonly kind: 'updated';
|
|
17
|
-
readonly before: V;
|
|
18
|
-
readonly after: V;
|
|
19
|
-
} | {
|
|
20
|
-
readonly key: K;
|
|
21
|
-
readonly kind: 'removed';
|
|
22
|
-
readonly before: V;
|
|
23
|
-
readonly after: undefined;
|
|
24
|
-
};
|
|
25
|
-
type CollectionChange<K extends string, V> = {
|
|
26
|
-
readonly kind: 'reset';
|
|
27
|
-
} | {
|
|
28
|
-
readonly kind: 'incremental';
|
|
29
|
-
readonly added: readonly Omit<Extract<CollectionEntryTransition<K, V>, {
|
|
30
|
-
readonly kind: 'added';
|
|
31
|
-
}>, 'before'>[];
|
|
32
|
-
readonly updated: readonly Extract<CollectionEntryTransition<K, V>, {
|
|
33
|
-
readonly kind: 'updated';
|
|
34
|
-
}>[];
|
|
35
|
-
readonly removed: readonly Omit<Extract<CollectionEntryTransition<K, V>, {
|
|
36
|
-
readonly kind: 'removed';
|
|
37
|
-
}>, 'after'>[];
|
|
38
|
-
readonly order?: {
|
|
39
|
-
readonly before: readonly K[];
|
|
40
|
-
readonly after: readonly K[];
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
type CollectionRead<K extends string, V> = {
|
|
44
|
-
get(key: K): V | undefined;
|
|
45
|
-
has(key: K): boolean;
|
|
46
|
-
ids(): readonly K[];
|
|
47
|
-
};
|
|
48
|
-
type ExternalCollectionRead<K extends string, V> = {
|
|
49
|
-
readonly get: (key: K) => V | undefined;
|
|
50
|
-
readonly has: (key: K) => boolean;
|
|
51
|
-
readonly ids: () => readonly K[];
|
|
52
|
-
};
|
|
53
|
-
type ExternalValueSource<T, D = unknown> = {
|
|
54
|
-
readonly kind: 'value';
|
|
55
|
-
current(): T;
|
|
56
|
-
revision(): number;
|
|
57
|
-
subscribe(listener: (event: ExternalValueEvent<T, D>) => void): Unsubscribe;
|
|
58
|
-
};
|
|
59
|
-
type ExternalCollectionSource<K extends string, V, D = unknown> = {
|
|
60
|
-
readonly kind: 'collection';
|
|
61
|
-
current(): ExternalCollectionRead<K, V>;
|
|
62
|
-
revision(): number;
|
|
63
|
-
subscribe(listener: (event: ExternalCollectionEvent<K, V, D>) => void): Unsubscribe;
|
|
64
|
-
};
|
|
65
|
-
type ExternalValueEvent<T, D = unknown> = {
|
|
66
|
-
readonly value: T;
|
|
67
|
-
readonly revision: number;
|
|
68
|
-
readonly reset?: boolean;
|
|
69
|
-
readonly detail?: D;
|
|
70
|
-
readonly cause?: Cause;
|
|
71
|
-
readonly batch?: {
|
|
72
|
-
readonly id: number;
|
|
73
|
-
readonly cause?: Cause;
|
|
74
|
-
};
|
|
75
|
-
};
|
|
76
|
-
type ExternalCollectionEvent<K extends string, V, D = unknown> = {
|
|
77
|
-
readonly previous: ExternalCollectionRead<K, V>;
|
|
78
|
-
readonly revision: number;
|
|
79
|
-
readonly reset?: boolean;
|
|
80
|
-
readonly change?: CollectionImpact<K>;
|
|
81
|
-
readonly detail?: D;
|
|
82
|
-
readonly cause?: Cause;
|
|
83
|
-
readonly batch?: {
|
|
84
|
-
readonly id: number;
|
|
85
|
-
readonly cause?: Cause;
|
|
86
|
-
};
|
|
87
|
-
};
|
|
88
|
-
type CollectionDraft<K extends string, V> = {
|
|
89
|
-
set(key: K, value: V): void;
|
|
90
|
-
remove(key: K): void;
|
|
91
|
-
order(ids: readonly K[]): void;
|
|
92
|
-
replace(entries: readonly (readonly [K, V])[]): void;
|
|
93
|
-
};
|
|
94
|
-
declare class ProjectionError extends Error {
|
|
95
|
-
readonly phase: 'processor' | 'listener' | 'source' | 'blocked';
|
|
96
|
-
readonly identity: string;
|
|
97
|
-
readonly revisions: readonly number[];
|
|
98
|
-
constructor(phase: 'processor' | 'listener' | 'source' | 'blocked', identity: string, revisions: readonly number[], cause: unknown);
|
|
99
|
-
}
|
|
100
|
-
declare class ProjectionDisposedError extends Error {
|
|
101
|
-
constructor();
|
|
102
|
-
}
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region core/src/projection/definition.d.ts
|
|
105
|
-
declare const projectionDefinition: unique symbol;
|
|
106
|
-
declare const projectionChanges: unique symbol;
|
|
107
|
-
declare const writableInput: unique symbol;
|
|
108
|
-
/** A lazy, reusable projection definition. Its value is materialized per runtime. */
|
|
109
|
-
type Projection<T, C = undefined> = {
|
|
110
|
-
readonly [projectionDefinition]: T;
|
|
111
|
-
readonly [projectionChanges]: C;
|
|
112
|
-
};
|
|
113
|
-
/** A runtime-local writable projection definition. */
|
|
114
|
-
type Input<T> = Projection<T> & {
|
|
115
|
-
readonly [writableInput]: true;
|
|
116
|
-
};
|
|
117
|
-
type ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never };
|
|
118
|
-
type ProjectionChanges<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D]: D[K] extends Projection<unknown, infer C> ? [C] extends [undefined] ? undefined : C | undefined : undefined };
|
|
119
|
-
type PublicCollection<K extends string, V> = ReadonlyMap<K, V>;
|
|
120
|
-
type CollectionProjection<K extends string, V> = Projection<PublicCollection<K, V>, CollectionChange<K, V>>;
|
|
121
|
-
declare const input: <T>(initial: T, equality?: (previous: T, next: T) => boolean) => Input<T>;
|
|
122
|
-
/**
|
|
123
|
-
* Establishes a reactive boundary from a document, readable, or external
|
|
124
|
-
* source. The selector is compiled when the definition is materialized, so
|
|
125
|
-
* declarations stay lazy and reusable.
|
|
126
|
-
*/
|
|
127
|
-
declare function observe<S extends ObjectNode>(document: DocumentReadable<S>): Projection<Infer<S>>;
|
|
128
|
-
declare function observe<T, D>(source: ExternalValueSource<T, D>): Projection<T>;
|
|
129
|
-
declare function observe<K extends string, V, D>(source: ExternalCollectionSource<K, V, D>): CollectionProjection<K, V>;
|
|
130
|
-
declare function observe<T>(readable: Readable<T>): Projection<T>;
|
|
131
|
-
declare function observe<S extends ObjectNode, P extends CollectionPath>(document: DocumentReadable<S>, selector: (path: SchemaPath<S['shape']>) => P): CollectionProjection<CollectionId<P>, ReadonlyValue<Infer<CollectionNode<P>>>>;
|
|
132
|
-
declare function observe<S extends ObjectNode, P>(document: DocumentReadable<S>, selector: (path: SchemaPath<S['shape']>) => P): Projection<PathValueOf<P>>;
|
|
133
|
-
declare function derive<const D extends readonly Projection<unknown, unknown>[], T>(dependencies: D, compute: (...values: ProjectionValues<D>) => Synchronous<T>, equality?: (previous: T, next: T) => boolean): Projection<T>;
|
|
134
|
-
//#endregion
|
|
135
|
-
export { ExternalValueEvent as _, ProjectionValues as a, ProjectionError as b, input as c, CollectionChange as d, CollectionDraft as f, ExternalCollectionSource as g, ExternalCollectionRead as h, ProjectionChanges as i, observe as l, ExternalCollectionEvent as m, Input as n, PublicCollection as o, CollectionRead as p, Projection as r, derive as s, CollectionProjection as t, BatchOptions as u, ExternalValueSource as v, ProjectionDisposedError as y };
|
|
136
|
-
//# sourceMappingURL=definition-C__VJqA4.d.cts.map
|