doxum 0.1.16 → 0.1.17
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 +1 -1
- package/dist/advanced.cjs +47 -63
- package/dist/advanced.cjs.map +1 -1
- package/dist/advanced.d.cts +7 -10
- package/dist/advanced.d.ts +7 -10
- package/dist/advanced.js +47 -63
- package/dist/advanced.js.map +1 -1
- package/dist/definition-BdLGD8Rq.d.ts +101 -0
- package/dist/definition-Bf8Z7xtX.d.cts +101 -0
- package/dist/{definition-c6XQXzvK.js → definition-DUo1lfQ8.js} +1 -2
- package/dist/definition-DUo1lfQ8.js.map +1 -0
- package/dist/{definition-Z6TagMup.cjs → definition-De6rhTlZ.cjs} +1 -2
- package/dist/definition-De6rhTlZ.cjs.map +1 -0
- package/dist/index.cjs +808 -796
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -4
- package/dist/index.d.ts +6 -4
- package/dist/index.js +809 -797
- 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 +4 -6
- package/dist/react.d.ts +4 -6
- 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 +6 -3
- package/skills/doxum-runtime/references/projections.zh-CN.md +6 -3
- package/dist/definition-C__VJqA4.d.cts +0 -136
- package/dist/definition-Dc1Udkop.d.ts +0 -136
- package/dist/definition-Z6TagMup.cjs.map +0 -1
- 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":"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"}
|
|
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\nconst ProjectionContext = createContext<ProjectionRuntime | 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
|
@@ -2,12 +2,10 @@ import * as _$react from "react";
|
|
|
2
2
|
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
|
|
3
3
|
|
|
4
4
|
//#region react/src/hooks.d.ts
|
|
5
|
-
declare const ProjectionContext: _$react.Context<ProjectionRuntime | undefined>;
|
|
6
5
|
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
|
|
7
|
-
declare function useProjection<T>(projection: Projection<T, unknown
|
|
8
|
-
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R,
|
|
9
|
-
declare function
|
|
10
|
-
declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
|
|
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
|
@@ -2,12 +2,10 @@ import * as _$react from "react";
|
|
|
2
2
|
import { DocumentReadable, DocumentSelector, HistoryState, Input, LocalHistory, ObjectNode, OperationResult, Projection, ProjectionRuntime, Readable } from "doxum";
|
|
3
3
|
|
|
4
4
|
//#region react/src/hooks.d.ts
|
|
5
|
-
declare const ProjectionContext: _$react.Context<ProjectionRuntime | undefined>;
|
|
6
5
|
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
|
|
7
|
-
declare function useProjection<T>(projection: Projection<T, unknown
|
|
8
|
-
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R,
|
|
9
|
-
declare function
|
|
10
|
-
declare function useInput<T>(input: Input<T>, runtime?: ProjectionRuntime): readonly [T, (value: T) => void];
|
|
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 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 | 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.17",
|
|
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 追踪只属于消费端。
|
|
@@ -23,8 +23,8 @@ sources use `kind: 'value'` or `kind: 'collection'`; the caller still uses only
|
|
|
23
23
|
|
|
24
24
|
External events are smaller than Runtime contexts. A value event carries the new
|
|
25
25
|
`value` and `revision`; a collection event carries a stable `previous` read,
|
|
26
|
-
`revision`, and an optional
|
|
27
|
-
|
|
26
|
+
`revision`, and an optional `impact` hint. The Runtime derives the exact
|
|
27
|
+
`CollectionChange`; processors never receive the impact directly.
|
|
28
28
|
|
|
29
29
|
`derive(dependencies, compute, equality?)` takes a tuple. Dependencies are
|
|
30
30
|
explicit and fixed when the definition is created. Processors must not discover
|
|
@@ -67,10 +67,13 @@ dependencies receive `reset` or grouped `added`/`updated`/`removed` entries with
|
|
|
67
67
|
complete `before`/`after` values and optional `order.before`/`order.after`.
|
|
68
68
|
The initial build reports `reset` for collection dependencies. A committed batch
|
|
69
69
|
is already coalesced into one net transition.
|
|
70
|
+
Collection values inside `sources` are callback-local lazy `ReadonlyMap` views;
|
|
71
|
+
do not retain or return them. Keyed `get`/`has` avoids a scan, while iteration is
|
|
72
|
+
an explicit full-collection read.
|
|
70
73
|
|
|
71
74
|
`incremental.collection(...)` uses a separate collection processor protocol and additionally exposes borrowed
|
|
72
75
|
`previous`/`next` keyed reads and a callback-local `output` draft. Draft methods are
|
|
73
|
-
`set`, `remove`,
|
|
76
|
+
`set`, `remove`, and `order`; the Runtime validates and seals them after
|
|
74
77
|
the synchronous callback, computes keyed transitions and publishes one immutable
|
|
75
78
|
map-like value. Reset or fault recovery is internal.
|
|
76
79
|
|
|
@@ -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 隐式建立图依赖。
|
|
@@ -62,11 +63,13 @@ const doubled = incremental.collection([tasks], ({ sources, output }) => {
|
|
|
62
63
|
标量依赖为 `undefined`,集合依赖则是 `reset`,或带完整 `before`/`after` 值的
|
|
63
64
|
`added`/`updated`/`removed` 分组,并可选提供 `order.before`/`order.after`。初次
|
|
64
65
|
build 对集合依赖报告 `reset`;一次已提交的 batch 已经合并成一个净 transition。
|
|
66
|
+
`sources` 内的集合值是 callback-local 的惰性 `ReadonlyMap` 视图,不能保存或直接
|
|
67
|
+
返回。`get`/`has` 保持按 key 读取,迭代才显式扫描整个集合。
|
|
65
68
|
|
|
66
69
|
`incremental.collection(...)` 使用独立的 collection processor 协议,另外提供借用的
|
|
67
70
|
`previous`/`next` keyed read,以及
|
|
68
|
-
只在同步 callback 内有效的 `output` draft。Draft 只有 `set`、`remove`、`order
|
|
69
|
-
|
|
71
|
+
只在同步 callback 内有效的 `output` draft。Draft 只有 `set`、`remove`、`order`;
|
|
72
|
+
Runtime 在 callback 返回后校验并 seal,计算 keyed transitions,发布
|
|
70
73
|
一个不可变 map-like 值。reset 或故障恢复由 Runtime 内部完成。
|
|
71
74
|
|
|
72
75
|
## React selector 追踪
|
|
@@ -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
|
|
@@ -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-CATCCVu5.js";
|
|
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-Dc1Udkop.d.ts.map
|