doxum 0.1.17 → 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 +30 -3
- 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/{definition-Bf8Z7xtX.d.cts → advanced-GTwIWcn6.d.cts} +44 -7
- package/dist/{definition-BdLGD8Rq.d.ts → advanced-c0F3gpLG.d.ts} +44 -7
- package/dist/advanced.cjs +2 -149
- package/dist/advanced.d.cts +2 -39
- package/dist/advanced.d.ts +2 -39
- package/dist/advanced.js +1 -148
- package/dist/index.cjs +346 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +342 -33
- package/dist/index.js.map +1 -1
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/skills/doxum-runtime/references/projections.en.md +13 -1
- package/skills/doxum-runtime/references/projections.zh-CN.md +9 -1
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.js.map +0 -1
- package/dist/definition-DUo1lfQ8.js +0 -71
- package/dist/definition-DUo1lfQ8.js.map +0 -1
- package/dist/definition-De6rhTlZ.cjs +0 -106
- package/dist/definition-De6rhTlZ.cjs.map +0 -1
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\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":";;;;;
|
|
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,8 +1,8 @@
|
|
|
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 ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
|
|
5
|
+
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | ProjectionScope | undefined>;
|
|
6
6
|
declare function useProjection<T>(projection: Projection<T, unknown>): T;
|
|
7
7
|
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean): R;
|
|
8
8
|
declare function useInput<T>(input: Input<T>): readonly [T, (value: T) => void];
|
package/dist/react.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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 ProjectionProvider: _$react.Provider<ProjectionRuntime | undefined>;
|
|
5
|
+
declare const ProjectionProvider: _$react.Provider<ProjectionRuntime | ProjectionScope | undefined>;
|
|
6
6
|
declare function useProjection<T>(projection: Projection<T, unknown>): T;
|
|
7
7
|
declare function useProjection<T, R>(projection: Projection<T, unknown>, selector: (value: T) => R, equality?: (previous: R, next: R) => boolean): R;
|
|
8
8
|
declare function useInput<T>(input: Input<T>): readonly [T, (value: T) => void];
|
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\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":";;;;
|
|
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,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
|
|
@@ -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.
|
|
@@ -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
|
|
@@ -35,10 +35,18 @@ runtime.get(projection);
|
|
|
35
35
|
const selected = runtime.readable(projection, value => value.get(id));
|
|
36
36
|
selected.subscribe(listener);
|
|
37
37
|
runtime.set(input, value);
|
|
38
|
+
runtime.update(collectionInput, draft => draft.set(id, value));
|
|
38
39
|
runtime.batch({ cause }, run);
|
|
40
|
+
const scope = runtime.scope();
|
|
41
|
+
scope.dispose();
|
|
39
42
|
runtime.dispose();
|
|
40
43
|
```
|
|
41
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
|
+
|
|
42
50
|
Runtime graph revision、item handle、rebuild、release 都是内部事实,不是应用层操作;
|
|
43
51
|
只有 `Readable` 自己的 publication revision 为 store 集成保留为公开事实。
|
|
44
52
|
Materialization、keyed storage、故障恢复和释放只有一个 owner。
|
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 { Projection } from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type { CollectionChange, CollectionDraft, CollectionRead, GraphSources } from './contract';\nimport { snapshot } from '../access/scope';\n\ntype ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never;\n};\n\ntype ProjectionChanges<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<unknown, infer C>\n ? [C] extends [undefined]\n ? undefined\n : C | undefined\n : undefined;\n};\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: Record<string, unknown>;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) => T | { 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: Record<string, unknown>;\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 resetCollectionChange = Object.freeze({ kind: 'reset' as const });\n\nconst isRebuild = (value: unknown): value is { readonly kind: 'rebuild' } =>\n value !== null &&\n typeof value === 'object' &&\n (value as { readonly kind?: unknown }).kind === 'rebuild';\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!source || typeof source !== 'object' || !('kind' in source)) return undefined;\n if (source.kind !== 'collection') return undefined;\n return (source as { readonly change?: CollectionChange<string, unknown> }).change;\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (source && typeof source === 'object' && 'kind' in source) {\n const cause = (source as { readonly cause?: unknown }).cause;\n if (cause !== undefined) return cause;\n }\n }\n return undefined;\n};\n\nconst collectionView = <K extends string, V>(read: CollectionRead<K, V>): ReadonlyMap<K, V> => {\n const entries = function* (): IterableIterator<[K, V]> {\n for (const key of read.ids()) yield [key, read.get(key) as V];\n };\n const values = function* (): IterableIterator<V> {\n for (const key of read.ids()) yield read.get(key) as V;\n };\n const view: ReadonlyMap<K, V> = {\n get: key => read.get(key),\n has: key => read.has(key),\n get size() {\n return read.ids().length;\n },\n keys: () => read.ids()[Symbol.iterator](),\n values,\n entries,\n forEach: (callback, thisArg) => {\n for (const key of read.ids()) callback.call(thisArg, read.get(key) as V, key, view);\n },\n [Symbol.iterator]: entries,\n };\n return Object.freeze(view);\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if (!('kind' in source)) return source;\n if (source.kind === 'value') return (source as unknown as { readonly value: unknown }).value;\n if (source.kind === 'document')\n return snapshot((source as unknown as { readonly read: unknown }).read as never);\n if (source.kind === 'collection') {\n const read = (source as unknown as { readonly read: CollectionRead<string, unknown> }).read;\n return collectionView(read);\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 &&\n source &&\n typeof source === 'object' &&\n 'kind' in source &&\n source.kind === 'collection'\n ? resetCollectionChange\n : collectionChange(source)\n );\n }\n return { values, changes };\n};\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: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as Record<string, unknown>;\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 (isRebuild(result)) throw new TypeError('Initial incremental processor cannot rebuild.');\n current = result as T;\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 (isRebuild(next)) return next;\n current = next as T;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction dependenciesOf<D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources {\n return Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(\n dependencies: D,\n processor: IncrementalCollectionProcessor<D, K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly output: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as Record<string, unknown>;\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.output,\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.output,\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 { Projection } from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type { CollectionChange, CollectionDraft, CollectionRead, GraphSources } from './contract';\nimport { snapshot } from '../access/scope';\n\ntype ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never;\n};\n\ntype ProjectionChanges<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<unknown, infer C>\n ? [C] extends [undefined]\n ? undefined\n : C | undefined\n : undefined;\n};\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: Record<string, unknown>;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) => T | { 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: Record<string, unknown>;\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 resetCollectionChange = Object.freeze({ kind: 'reset' as const });\n\nconst isRebuild = (value: unknown): value is { readonly kind: 'rebuild' } =>\n value !== null &&\n typeof value === 'object' &&\n (value as { readonly kind?: unknown }).kind === 'rebuild';\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!source || typeof source !== 'object' || !('kind' in source)) return undefined;\n if (source.kind !== 'collection') return undefined;\n return (source as { readonly change?: CollectionChange<string, unknown> }).change;\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (source && typeof source === 'object' && 'kind' in source) {\n const cause = (source as { readonly cause?: unknown }).cause;\n if (cause !== undefined) return cause;\n }\n }\n return undefined;\n};\n\nconst collectionView = <K extends string, V>(read: CollectionRead<K, V>): ReadonlyMap<K, V> => {\n const entries = function* (): IterableIterator<[K, V]> {\n for (const key of read.ids()) yield [key, read.get(key) as V];\n };\n const values = function* (): IterableIterator<V> {\n for (const key of read.ids()) yield read.get(key) as V;\n };\n const view: ReadonlyMap<K, V> = {\n get: key => read.get(key),\n has: key => read.has(key),\n get size() {\n return read.ids().length;\n },\n keys: () => read.ids()[Symbol.iterator](),\n values,\n entries,\n forEach: (callback, thisArg) => {\n for (const key of read.ids()) callback.call(thisArg, read.get(key) as V, key, view);\n },\n [Symbol.iterator]: entries,\n };\n return Object.freeze(view);\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if (!('kind' in source)) return source;\n if (source.kind === 'value') return (source as unknown as { readonly value: unknown }).value;\n if (source.kind === 'document')\n return snapshot((source as unknown as { readonly read: unknown }).read as never);\n if (source.kind === 'collection') {\n const read = (source as unknown as { readonly read: CollectionRead<string, unknown> }).read;\n return collectionView(read);\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 &&\n source &&\n typeof source === 'object' &&\n 'kind' in source &&\n source.kind === 'collection'\n ? resetCollectionChange\n : collectionChange(source)\n );\n }\n return { values, changes };\n};\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: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as Record<string, unknown>;\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 (isRebuild(result)) throw new TypeError('Initial incremental processor cannot rebuild.');\n current = result as T;\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 (isRebuild(next)) return next;\n current = next as T;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction dependenciesOf<D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources {\n return Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(\n dependencies: D,\n processor: IncrementalCollectionProcessor<D, K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly output: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as Record<string, unknown>;\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.output,\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.output,\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,71 +0,0 @@
|
|
|
1
|
-
//#region core/src/projection/definition.ts
|
|
2
|
-
const definitions = /* @__PURE__ */ new WeakMap();
|
|
3
|
-
const define = (definition) => {
|
|
4
|
-
const handle = Object.freeze({});
|
|
5
|
-
definitions.set(handle, definition);
|
|
6
|
-
return handle;
|
|
7
|
-
};
|
|
8
|
-
const definitionOf = (projection) => {
|
|
9
|
-
const definition = definitions.get(projection);
|
|
10
|
-
if (!definition) throw new TypeError("Unknown projection definition.");
|
|
11
|
-
return definition;
|
|
12
|
-
};
|
|
13
|
-
const input = (initial, equality = Object.is) => define({
|
|
14
|
-
kind: "input",
|
|
15
|
-
initial,
|
|
16
|
-
isEqual: equality
|
|
17
|
-
});
|
|
18
|
-
function observe(document, selector) {
|
|
19
|
-
if (isExternalSource(document)) return document.kind === "collection" ? defineExternalCollection(document) : defineExternalValue(document);
|
|
20
|
-
if ("current" in document && typeof document.current === "function") return defineReadable(document);
|
|
21
|
-
return define({
|
|
22
|
-
kind: "document",
|
|
23
|
-
document,
|
|
24
|
-
selector
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const isExternalSource = (source) => {
|
|
28
|
-
if (!source || typeof source !== "object") return false;
|
|
29
|
-
const candidate = source;
|
|
30
|
-
return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
|
|
31
|
-
};
|
|
32
|
-
function derive(dependencies, compute, equality = Object.is) {
|
|
33
|
-
if (!Array.isArray(dependencies) || dependencies.some((value) => !definitions.has(value))) throw new TypeError("derive dependencies must be projections.");
|
|
34
|
-
return define({
|
|
35
|
-
kind: "derive",
|
|
36
|
-
dependencies: Object.freeze([...dependencies]),
|
|
37
|
-
compute,
|
|
38
|
-
isEqual: equality
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
const defineReadable = (readable, equality = Object.is) => define({
|
|
42
|
-
kind: "readable",
|
|
43
|
-
readable,
|
|
44
|
-
isEqual: equality
|
|
45
|
-
});
|
|
46
|
-
const defineExternalValue = (source) => define({
|
|
47
|
-
kind: "source-value",
|
|
48
|
-
source
|
|
49
|
-
});
|
|
50
|
-
const defineExternalCollection = (source) => define({
|
|
51
|
-
kind: "source-collection",
|
|
52
|
-
source
|
|
53
|
-
});
|
|
54
|
-
const defineIncrementalValue = (definition) => define({
|
|
55
|
-
kind: "incremental-value",
|
|
56
|
-
dependencies: definition.dependencies,
|
|
57
|
-
build: definition.build,
|
|
58
|
-
isEqual: definition.isEqual,
|
|
59
|
-
name: definition.name
|
|
60
|
-
});
|
|
61
|
-
const defineIncrementalCollection = (definition) => define({
|
|
62
|
-
kind: "incremental-collection",
|
|
63
|
-
dependencies: definition.dependencies,
|
|
64
|
-
build: definition.build,
|
|
65
|
-
isEqual: definition.isEqual,
|
|
66
|
-
name: definition.name
|
|
67
|
-
});
|
|
68
|
-
//#endregion
|
|
69
|
-
export { input as a, derive as i, defineIncrementalValue as n, observe as o, definitionOf as r, defineIncrementalCollection as t };
|
|
70
|
-
|
|
71
|
-
//# sourceMappingURL=definition-DUo1lfQ8.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-DUo1lfQ8.js","names":[],"sources":["../core/src/projection/definition.ts"],"sourcesContent":["import type { DocumentReadable, Synchronous } from '../runtime/contract';\nimport type {\n CollectionId,\n CollectionPath,\n CollectionNode as SchemaCollectionNode,\n Infer,\n ObjectNode,\n ReadonlyValue,\n SchemaPath,\n PathValueOf,\n} from '../schema';\nimport type { Readable } from './readable';\nimport type {\n CollectionChange,\n ExternalCollectionSource,\n ExternalValueSource,\n GraphSources,\n} from './contract';\n\ndeclare const projectionDefinition: unique symbol;\ndeclare const projectionChanges: unique symbol;\ndeclare const writableInput: unique symbol;\n\n/** A lazy, reusable projection definition with no runtime-owned state. */\nexport type Projection<T, C = undefined> = {\n readonly [projectionDefinition]: T;\n readonly [projectionChanges]: C;\n};\n\n/** A runtime-local writable projection definition. */\nexport type Input<T> = Projection<T> & { readonly [writableInput]: true };\n\ntype ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never;\n};\n\ntype Equality = (a: unknown, b: unknown) => boolean;\ntype PathSelector<S extends ObjectNode> = (path: SchemaPath<S['shape']>) => unknown;\n\ntype Definition =\n | { readonly kind: 'input'; readonly initial: unknown; readonly isEqual?: Equality }\n | { readonly kind: 'readable'; readonly readable: Readable<unknown>; readonly isEqual?: Equality }\n | { readonly kind: 'source-value'; readonly source: ExternalValueSource<unknown> }\n | {\n readonly kind: 'source-collection';\n readonly source: ExternalCollectionSource<string, unknown>;\n }\n | {\n readonly kind: 'document';\n readonly document: DocumentReadable<ObjectNode>;\n readonly selector?: PathSelector<ObjectNode>;\n }\n | {\n readonly kind: 'derive';\n readonly dependencies: readonly Projection<unknown, unknown>[];\n readonly compute: (...values: readonly unknown[]) => unknown;\n readonly isEqual?: Equality;\n }\n | {\n readonly kind: 'incremental-value';\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: Equality;\n readonly name?: string;\n }\n | {\n readonly kind: 'incremental-collection';\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: Equality;\n readonly name?: string;\n };\n\ntype DefinitionProjection = Projection<unknown, unknown>;\nconst definitions = new WeakMap<object, Definition>();\n\nconst define = <T, C = undefined>(definition: Definition): Projection<T, C> => {\n const handle = Object.freeze({}) as Projection<T, C>;\n definitions.set(handle, definition);\n return handle;\n};\n\nexport const definitionOf = (projection: DefinitionProjection): Definition => {\n const definition = definitions.get(projection);\n if (!definition) throw new TypeError('Unknown projection definition.');\n return definition;\n};\n\nexport const input = <T>(\n initial: T,\n equality: (previous: T, next: T) => boolean = Object.is\n): Input<T> => define<T>({ kind: 'input', initial, isEqual: equality as Equality }) as Input<T>;\n\n/** Establish a lazy reactive boundary from a document, readable, or external source. */\nexport function observe<S extends ObjectNode>(document: DocumentReadable<S>): Projection<Infer<S>>;\nexport function observe<T>(source: ExternalValueSource<T>): Projection<T>;\nexport function observe<K extends string, V>(\n source: ExternalCollectionSource<K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>>;\nexport function observe<T>(readable: Readable<T>): Projection<T>;\nexport function observe<S extends ObjectNode, P extends CollectionPath>(\n document: DocumentReadable<S>,\n selector: (path: SchemaPath<S['shape']>) => P\n): Projection<\n ReadonlyMap<CollectionId<P>, ReadonlyValue<Infer<SchemaCollectionNode<P>>>>,\n CollectionChange<CollectionId<P>, ReadonlyValue<Infer<SchemaCollectionNode<P>>>>\n>;\nexport function observe<S extends ObjectNode, P>(\n document: DocumentReadable<S>,\n selector: (path: SchemaPath<S['shape']>) => P\n): Projection<PathValueOf<P>>;\nexport function observe<S extends ObjectNode>(\n document:\n | DocumentReadable<S>\n | Readable<unknown>\n | ExternalValueSource<unknown>\n | ExternalCollectionSource<string, unknown>,\n selector?: PathSelector<S>\n): Projection<unknown, unknown> {\n if (isExternalSource(document))\n return document.kind === 'collection'\n ? defineExternalCollection(document)\n : defineExternalValue(document);\n if ('current' in document && typeof document.current === 'function')\n return defineReadable(document as Readable<unknown>);\n return define({\n kind: 'document',\n document: document as DocumentReadable<ObjectNode>,\n selector: selector as PathSelector<ObjectNode> | undefined,\n });\n}\n\nconst isExternalSource = (\n source: unknown\n): source is ExternalValueSource<unknown> | ExternalCollectionSource<string, unknown> => {\n if (!source || typeof source !== 'object') return false;\n const candidate = source as {\n readonly kind?: unknown;\n readonly current?: unknown;\n readonly revision?: unknown;\n readonly subscribe?: unknown;\n };\n return (\n (candidate.kind === 'value' || candidate.kind === 'collection') &&\n typeof candidate.current === 'function' &&\n typeof candidate.revision === 'function' &&\n typeof candidate.subscribe === 'function'\n );\n};\n\nexport function derive<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n compute: (...values: ProjectionValues<D>) => Synchronous<T>,\n equality: (previous: T, next: T) => boolean = Object.is\n): Projection<T> {\n if (!Array.isArray(dependencies) || dependencies.some(value => !definitions.has(value)))\n throw new TypeError('derive dependencies must be projections.');\n const frozen = Object.freeze([...dependencies]) as readonly Projection<unknown, unknown>[];\n return define<T>({\n kind: 'derive',\n dependencies: frozen,\n compute: compute as (...values: readonly unknown[]) => unknown,\n isEqual: equality as Equality,\n });\n}\n\nexport const defineReadable = <T>(\n readable: Readable<T>,\n equality: (a: T, b: T) => boolean = Object.is\n): Projection<T> => define<T>({ kind: 'readable', readable, isEqual: equality as Equality });\n\nexport const defineExternalValue = <T>(source: ExternalValueSource<T>): Projection<T> =>\n define<T>({ kind: 'source-value', source: source as ExternalValueSource<unknown> });\n\nexport const defineExternalCollection = <K extends string, V>(\n source: ExternalCollectionSource<K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> =>\n define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'source-collection',\n source: source as unknown as ExternalCollectionSource<string, unknown>,\n });\n\nexport const defineIncrementalValue = <T>(definition: {\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: (a: T, b: T) => boolean;\n readonly name?: string;\n}): Projection<T> =>\n define<T>({\n kind: 'incremental-value',\n dependencies: definition.dependencies,\n build: definition.build,\n isEqual: definition.isEqual as Equality | undefined,\n name: definition.name,\n });\n\nexport const defineIncrementalCollection = <K extends string, V>(definition: {\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: (a: V, b: V) => boolean;\n readonly name?: string;\n}): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> =>\n define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'incremental-collection',\n dependencies: definition.dependencies,\n build: definition.build,\n isEqual: definition.isEqual as Equality | undefined,\n name: definition.name,\n });\n"],"mappings":";AA0EA,MAAM,8BAAc,IAAI,SAA6B;AAErD,MAAM,UAA4B,eAA6C;CAC7E,MAAM,SAAS,OAAO,OAAO,EAAE,CAAC;AAChC,aAAY,IAAI,QAAQ,WAAW;AACnC,QAAO;;AAGT,MAAa,gBAAgB,eAAiD;CAC5E,MAAM,aAAa,YAAY,IAAI,WAAW;AAC9C,KAAI,CAAC,WAAY,OAAM,IAAI,UAAU,iCAAiC;AACtE,QAAO;;AAGT,MAAa,SACX,SACA,WAA8C,OAAO,OACxC,OAAU;CAAE,MAAM;CAAS;CAAS,SAAS;CAAsB,CAAC;AAoBnF,SAAgB,QACd,UAKA,UAC8B;AAC9B,KAAI,iBAAiB,SAAS,CAC5B,QAAO,SAAS,SAAS,eACrB,yBAAyB,SAAS,GAClC,oBAAoB,SAAS;AACnC,KAAI,aAAa,YAAY,OAAO,SAAS,YAAY,WACvD,QAAO,eAAe,SAA8B;AACtD,QAAO,OAAO;EACZ,MAAM;EACI;EACA;EACX,CAAC;;AAGJ,MAAM,oBACJ,WACuF;AACvF,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;CAClD,MAAM,YAAY;AAMlB,SACG,UAAU,SAAS,WAAW,UAAU,SAAS,iBAClD,OAAO,UAAU,YAAY,cAC7B,OAAO,UAAU,aAAa,cAC9B,OAAO,UAAU,cAAc;;AAInC,SAAgB,OACd,cACA,SACA,WAA8C,OAAO,IACtC;AACf,KAAI,CAAC,MAAM,QAAQ,aAAa,IAAI,aAAa,MAAK,UAAS,CAAC,YAAY,IAAI,MAAM,CAAC,CACrF,OAAM,IAAI,UAAU,2CAA2C;AAEjE,QAAO,OAAU;EACf,MAAM;EACN,cAHa,OAAO,OAAO,CAAC,GAAG,aAAa,CAGxB;EACX;EACT,SAAS;EACV,CAAC;;AAGJ,MAAa,kBACX,UACA,WAAoC,OAAO,OACzB,OAAU;CAAE,MAAM;CAAY;CAAU,SAAS;CAAsB,CAAC;AAE5F,MAAa,uBAA0B,WACrC,OAAU;CAAE,MAAM;CAAwB;CAAwC,CAAC;AAErF,MAAa,4BACX,WAEA,OAAkD;CAChD,MAAM;CACE;CACT,CAAC;AAEJ,MAAa,0BAA6B,eAMxC,OAAU;CACR,MAAM;CACN,cAAc,WAAW;CACzB,OAAO,WAAW;CAClB,SAAS,WAAW;CACpB,MAAM,WAAW;CAClB,CAAC;AAEJ,MAAa,+BAAoD,eAM/D,OAAkD;CAChD,MAAM;CACN,cAAc,WAAW;CACzB,OAAO,WAAW;CAClB,SAAS,WAAW;CACpB,MAAM,WAAW;CAClB,CAAC"}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
//#region core/src/projection/definition.ts
|
|
2
|
-
const definitions = /* @__PURE__ */ new WeakMap();
|
|
3
|
-
const define = (definition) => {
|
|
4
|
-
const handle = Object.freeze({});
|
|
5
|
-
definitions.set(handle, definition);
|
|
6
|
-
return handle;
|
|
7
|
-
};
|
|
8
|
-
const definitionOf = (projection) => {
|
|
9
|
-
const definition = definitions.get(projection);
|
|
10
|
-
if (!definition) throw new TypeError("Unknown projection definition.");
|
|
11
|
-
return definition;
|
|
12
|
-
};
|
|
13
|
-
const input = (initial, equality = Object.is) => define({
|
|
14
|
-
kind: "input",
|
|
15
|
-
initial,
|
|
16
|
-
isEqual: equality
|
|
17
|
-
});
|
|
18
|
-
function observe(document, selector) {
|
|
19
|
-
if (isExternalSource(document)) return document.kind === "collection" ? defineExternalCollection(document) : defineExternalValue(document);
|
|
20
|
-
if ("current" in document && typeof document.current === "function") return defineReadable(document);
|
|
21
|
-
return define({
|
|
22
|
-
kind: "document",
|
|
23
|
-
document,
|
|
24
|
-
selector
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
const isExternalSource = (source) => {
|
|
28
|
-
if (!source || typeof source !== "object") return false;
|
|
29
|
-
const candidate = source;
|
|
30
|
-
return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
|
|
31
|
-
};
|
|
32
|
-
function derive(dependencies, compute, equality = Object.is) {
|
|
33
|
-
if (!Array.isArray(dependencies) || dependencies.some((value) => !definitions.has(value))) throw new TypeError("derive dependencies must be projections.");
|
|
34
|
-
return define({
|
|
35
|
-
kind: "derive",
|
|
36
|
-
dependencies: Object.freeze([...dependencies]),
|
|
37
|
-
compute,
|
|
38
|
-
isEqual: equality
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
const defineReadable = (readable, equality = Object.is) => define({
|
|
42
|
-
kind: "readable",
|
|
43
|
-
readable,
|
|
44
|
-
isEqual: equality
|
|
45
|
-
});
|
|
46
|
-
const defineExternalValue = (source) => define({
|
|
47
|
-
kind: "source-value",
|
|
48
|
-
source
|
|
49
|
-
});
|
|
50
|
-
const defineExternalCollection = (source) => define({
|
|
51
|
-
kind: "source-collection",
|
|
52
|
-
source
|
|
53
|
-
});
|
|
54
|
-
const defineIncrementalValue = (definition) => define({
|
|
55
|
-
kind: "incremental-value",
|
|
56
|
-
dependencies: definition.dependencies,
|
|
57
|
-
build: definition.build,
|
|
58
|
-
isEqual: definition.isEqual,
|
|
59
|
-
name: definition.name
|
|
60
|
-
});
|
|
61
|
-
const defineIncrementalCollection = (definition) => define({
|
|
62
|
-
kind: "incremental-collection",
|
|
63
|
-
dependencies: definition.dependencies,
|
|
64
|
-
build: definition.build,
|
|
65
|
-
isEqual: definition.isEqual,
|
|
66
|
-
name: definition.name
|
|
67
|
-
});
|
|
68
|
-
//#endregion
|
|
69
|
-
Object.defineProperty(exports, "defineIncrementalCollection", {
|
|
70
|
-
enumerable: true,
|
|
71
|
-
get: function() {
|
|
72
|
-
return defineIncrementalCollection;
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
Object.defineProperty(exports, "defineIncrementalValue", {
|
|
76
|
-
enumerable: true,
|
|
77
|
-
get: function() {
|
|
78
|
-
return defineIncrementalValue;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
Object.defineProperty(exports, "definitionOf", {
|
|
82
|
-
enumerable: true,
|
|
83
|
-
get: function() {
|
|
84
|
-
return definitionOf;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
Object.defineProperty(exports, "derive", {
|
|
88
|
-
enumerable: true,
|
|
89
|
-
get: function() {
|
|
90
|
-
return derive;
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
Object.defineProperty(exports, "input", {
|
|
94
|
-
enumerable: true,
|
|
95
|
-
get: function() {
|
|
96
|
-
return input;
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
Object.defineProperty(exports, "observe", {
|
|
100
|
-
enumerable: true,
|
|
101
|
-
get: function() {
|
|
102
|
-
return observe;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
//# sourceMappingURL=definition-De6rhTlZ.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"definition-De6rhTlZ.cjs","names":[],"sources":["../core/src/projection/definition.ts"],"sourcesContent":["import type { DocumentReadable, Synchronous } from '../runtime/contract';\nimport type {\n CollectionId,\n CollectionPath,\n CollectionNode as SchemaCollectionNode,\n Infer,\n ObjectNode,\n ReadonlyValue,\n SchemaPath,\n PathValueOf,\n} from '../schema';\nimport type { Readable } from './readable';\nimport type {\n CollectionChange,\n ExternalCollectionSource,\n ExternalValueSource,\n GraphSources,\n} from './contract';\n\ndeclare const projectionDefinition: unique symbol;\ndeclare const projectionChanges: unique symbol;\ndeclare const writableInput: unique symbol;\n\n/** A lazy, reusable projection definition with no runtime-owned state. */\nexport type Projection<T, C = undefined> = {\n readonly [projectionDefinition]: T;\n readonly [projectionChanges]: C;\n};\n\n/** A runtime-local writable projection definition. */\nexport type Input<T> = Projection<T> & { readonly [writableInput]: true };\n\ntype ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never;\n};\n\ntype Equality = (a: unknown, b: unknown) => boolean;\ntype PathSelector<S extends ObjectNode> = (path: SchemaPath<S['shape']>) => unknown;\n\ntype Definition =\n | { readonly kind: 'input'; readonly initial: unknown; readonly isEqual?: Equality }\n | { readonly kind: 'readable'; readonly readable: Readable<unknown>; readonly isEqual?: Equality }\n | { readonly kind: 'source-value'; readonly source: ExternalValueSource<unknown> }\n | {\n readonly kind: 'source-collection';\n readonly source: ExternalCollectionSource<string, unknown>;\n }\n | {\n readonly kind: 'document';\n readonly document: DocumentReadable<ObjectNode>;\n readonly selector?: PathSelector<ObjectNode>;\n }\n | {\n readonly kind: 'derive';\n readonly dependencies: readonly Projection<unknown, unknown>[];\n readonly compute: (...values: readonly unknown[]) => unknown;\n readonly isEqual?: Equality;\n }\n | {\n readonly kind: 'incremental-value';\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: Equality;\n readonly name?: string;\n }\n | {\n readonly kind: 'incremental-collection';\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: Equality;\n readonly name?: string;\n };\n\ntype DefinitionProjection = Projection<unknown, unknown>;\nconst definitions = new WeakMap<object, Definition>();\n\nconst define = <T, C = undefined>(definition: Definition): Projection<T, C> => {\n const handle = Object.freeze({}) as Projection<T, C>;\n definitions.set(handle, definition);\n return handle;\n};\n\nexport const definitionOf = (projection: DefinitionProjection): Definition => {\n const definition = definitions.get(projection);\n if (!definition) throw new TypeError('Unknown projection definition.');\n return definition;\n};\n\nexport const input = <T>(\n initial: T,\n equality: (previous: T, next: T) => boolean = Object.is\n): Input<T> => define<T>({ kind: 'input', initial, isEqual: equality as Equality }) as Input<T>;\n\n/** Establish a lazy reactive boundary from a document, readable, or external source. */\nexport function observe<S extends ObjectNode>(document: DocumentReadable<S>): Projection<Infer<S>>;\nexport function observe<T>(source: ExternalValueSource<T>): Projection<T>;\nexport function observe<K extends string, V>(\n source: ExternalCollectionSource<K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>>;\nexport function observe<T>(readable: Readable<T>): Projection<T>;\nexport function observe<S extends ObjectNode, P extends CollectionPath>(\n document: DocumentReadable<S>,\n selector: (path: SchemaPath<S['shape']>) => P\n): Projection<\n ReadonlyMap<CollectionId<P>, ReadonlyValue<Infer<SchemaCollectionNode<P>>>>,\n CollectionChange<CollectionId<P>, ReadonlyValue<Infer<SchemaCollectionNode<P>>>>\n>;\nexport function observe<S extends ObjectNode, P>(\n document: DocumentReadable<S>,\n selector: (path: SchemaPath<S['shape']>) => P\n): Projection<PathValueOf<P>>;\nexport function observe<S extends ObjectNode>(\n document:\n | DocumentReadable<S>\n | Readable<unknown>\n | ExternalValueSource<unknown>\n | ExternalCollectionSource<string, unknown>,\n selector?: PathSelector<S>\n): Projection<unknown, unknown> {\n if (isExternalSource(document))\n return document.kind === 'collection'\n ? defineExternalCollection(document)\n : defineExternalValue(document);\n if ('current' in document && typeof document.current === 'function')\n return defineReadable(document as Readable<unknown>);\n return define({\n kind: 'document',\n document: document as DocumentReadable<ObjectNode>,\n selector: selector as PathSelector<ObjectNode> | undefined,\n });\n}\n\nconst isExternalSource = (\n source: unknown\n): source is ExternalValueSource<unknown> | ExternalCollectionSource<string, unknown> => {\n if (!source || typeof source !== 'object') return false;\n const candidate = source as {\n readonly kind?: unknown;\n readonly current?: unknown;\n readonly revision?: unknown;\n readonly subscribe?: unknown;\n };\n return (\n (candidate.kind === 'value' || candidate.kind === 'collection') &&\n typeof candidate.current === 'function' &&\n typeof candidate.revision === 'function' &&\n typeof candidate.subscribe === 'function'\n );\n};\n\nexport function derive<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n compute: (...values: ProjectionValues<D>) => Synchronous<T>,\n equality: (previous: T, next: T) => boolean = Object.is\n): Projection<T> {\n if (!Array.isArray(dependencies) || dependencies.some(value => !definitions.has(value)))\n throw new TypeError('derive dependencies must be projections.');\n const frozen = Object.freeze([...dependencies]) as readonly Projection<unknown, unknown>[];\n return define<T>({\n kind: 'derive',\n dependencies: frozen,\n compute: compute as (...values: readonly unknown[]) => unknown,\n isEqual: equality as Equality,\n });\n}\n\nexport const defineReadable = <T>(\n readable: Readable<T>,\n equality: (a: T, b: T) => boolean = Object.is\n): Projection<T> => define<T>({ kind: 'readable', readable, isEqual: equality as Equality });\n\nexport const defineExternalValue = <T>(source: ExternalValueSource<T>): Projection<T> =>\n define<T>({ kind: 'source-value', source: source as ExternalValueSource<unknown> });\n\nexport const defineExternalCollection = <K extends string, V>(\n source: ExternalCollectionSource<K, V>\n): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> =>\n define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'source-collection',\n source: source as unknown as ExternalCollectionSource<string, unknown>,\n });\n\nexport const defineIncrementalValue = <T>(definition: {\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: (a: T, b: T) => boolean;\n readonly name?: string;\n}): Projection<T> =>\n define<T>({\n kind: 'incremental-value',\n dependencies: definition.dependencies,\n build: definition.build,\n isEqual: definition.isEqual as Equality | undefined,\n name: definition.name,\n });\n\nexport const defineIncrementalCollection = <K extends string, V>(definition: {\n readonly dependencies: GraphSources;\n readonly build: (...args: never[]) => unknown;\n readonly isEqual?: (a: V, b: V) => boolean;\n readonly name?: string;\n}): Projection<ReadonlyMap<K, V>, CollectionChange<K, V>> =>\n define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'incremental-collection',\n dependencies: definition.dependencies,\n build: definition.build,\n isEqual: definition.isEqual as Equality | undefined,\n name: definition.name,\n });\n"],"mappings":";AA0EA,MAAM,8BAAc,IAAI,SAA6B;AAErD,MAAM,UAA4B,eAA6C;CAC7E,MAAM,SAAS,OAAO,OAAO,EAAE,CAAC;AAChC,aAAY,IAAI,QAAQ,WAAW;AACnC,QAAO;;AAGT,MAAa,gBAAgB,eAAiD;CAC5E,MAAM,aAAa,YAAY,IAAI,WAAW;AAC9C,KAAI,CAAC,WAAY,OAAM,IAAI,UAAU,iCAAiC;AACtE,QAAO;;AAGT,MAAa,SACX,SACA,WAA8C,OAAO,OACxC,OAAU;CAAE,MAAM;CAAS;CAAS,SAAS;CAAsB,CAAC;AAoBnF,SAAgB,QACd,UAKA,UAC8B;AAC9B,KAAI,iBAAiB,SAAS,CAC5B,QAAO,SAAS,SAAS,eACrB,yBAAyB,SAAS,GAClC,oBAAoB,SAAS;AACnC,KAAI,aAAa,YAAY,OAAO,SAAS,YAAY,WACvD,QAAO,eAAe,SAA8B;AACtD,QAAO,OAAO;EACZ,MAAM;EACI;EACA;EACX,CAAC;;AAGJ,MAAM,oBACJ,WACuF;AACvF,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;CAClD,MAAM,YAAY;AAMlB,SACG,UAAU,SAAS,WAAW,UAAU,SAAS,iBAClD,OAAO,UAAU,YAAY,cAC7B,OAAO,UAAU,aAAa,cAC9B,OAAO,UAAU,cAAc;;AAInC,SAAgB,OACd,cACA,SACA,WAA8C,OAAO,IACtC;AACf,KAAI,CAAC,MAAM,QAAQ,aAAa,IAAI,aAAa,MAAK,UAAS,CAAC,YAAY,IAAI,MAAM,CAAC,CACrF,OAAM,IAAI,UAAU,2CAA2C;AAEjE,QAAO,OAAU;EACf,MAAM;EACN,cAHa,OAAO,OAAO,CAAC,GAAG,aAAa,CAGxB;EACX;EACT,SAAS;EACV,CAAC;;AAGJ,MAAa,kBACX,UACA,WAAoC,OAAO,OACzB,OAAU;CAAE,MAAM;CAAY;CAAU,SAAS;CAAsB,CAAC;AAE5F,MAAa,uBAA0B,WACrC,OAAU;CAAE,MAAM;CAAwB;CAAwC,CAAC;AAErF,MAAa,4BACX,WAEA,OAAkD;CAChD,MAAM;CACE;CACT,CAAC;AAEJ,MAAa,0BAA6B,eAMxC,OAAU;CACR,MAAM;CACN,cAAc,WAAW;CACzB,OAAO,WAAW;CAClB,SAAS,WAAW;CACpB,MAAM,WAAW;CAClB,CAAC;AAEJ,MAAa,+BAAoD,eAM/D,OAAkD;CAChD,MAAM;CACN,cAAc,WAAW;CACzB,OAAO,WAAW;CAClB,SAAS,WAAW;CACpB,MAAM,WAAW;CAClB,CAAC"}
|