doxum 0.1.16 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -4
- package/dist/advanced-DgRnyRAc.js +233 -0
- package/dist/advanced-DgRnyRAc.js.map +1 -0
- package/dist/advanced-Dgu8-bPS.cjs +274 -0
- package/dist/advanced-Dgu8-bPS.cjs.map +1 -0
- package/dist/advanced-GTwIWcn6.d.cts +138 -0
- package/dist/advanced-c0F3gpLG.d.ts +138 -0
- package/dist/advanced.cjs +2 -165
- package/dist/advanced.d.cts +2 -42
- package/dist/advanced.d.ts +2 -42
- package/dist/advanced.js +1 -164
- package/dist/index.cjs +1195 -874
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -4
- package/dist/index.d.ts +26 -4
- package/dist/index.js +1192 -871
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +5 -10
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -8
- package/dist/react.d.ts +6 -8
- package/dist/react.js +6 -10
- package/dist/react.js.map +1 -1
- package/package.json +3 -2
- package/skills/doxum-runtime/SKILL.md +2 -1
- package/skills/doxum-runtime/references/patterns.en.md +4 -4
- package/skills/doxum-runtime/references/patterns.zh-CN.md +2 -2
- package/skills/doxum-runtime/references/projections.en.md +19 -4
- package/skills/doxum-runtime/references/projections.zh-CN.md +15 -4
- package/dist/advanced.cjs.map +0 -1
- package/dist/advanced.js.map +0 -1
- package/dist/definition-C__VJqA4.d.cts +0 -136
- package/dist/definition-Dc1Udkop.d.ts +0 -136
- package/dist/definition-Z6TagMup.cjs +0 -107
- package/dist/definition-Z6TagMup.cjs.map +0 -1
- package/dist/definition-c6XQXzvK.js +0 -72
- package/dist/definition-c6XQXzvK.js.map +0 -1
package/README.md
CHANGED
|
@@ -232,12 +232,39 @@ runtime.batch({ cause: { action: 'refresh' } }, () => {
|
|
|
232
232
|
stop();
|
|
233
233
|
```
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
235
|
+
Root projection declarations are lazy and reusable; scoped declarations are
|
|
236
|
+
lazy but tied to their scope. The Runtime owns `get`,
|
|
237
|
+
`readable`, scalar `set`, keyed `update`, `batch`, `scope` and `dispose`;
|
|
238
|
+
materialization, incremental state, publication and recovery stay inside that
|
|
239
|
+
one Runtime. Collection values are
|
|
238
240
|
immutable `ReadonlyMap`-like snapshots, while a `Readable` owns selector
|
|
239
241
|
tracking, equality and subscription lifecycle.
|
|
240
242
|
|
|
243
|
+
Local projections live in the same graph as their parent definitions:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
const scope = runtime.scope();
|
|
247
|
+
const localFilter = scope.input<'all' | 'open'>('all');
|
|
248
|
+
const localVisible = scope.derive([tasks, localFilter], (tasks, filter) =>
|
|
249
|
+
filter === 'all' ? tasks : new Map([...tasks].filter(([, task]) => !task.done))
|
|
250
|
+
);
|
|
251
|
+
scope.get(localVisible);
|
|
252
|
+
scope.dispose(); // Releases local nodes, state and subscriptions; parent tasks remain.
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
For Runtime-local keyed state, `input.collection` publishes the same exact
|
|
256
|
+
`CollectionChange` as document collections. One `update` edits one or many keys
|
|
257
|
+
atomically; the enclosing Runtime batch coalesces accepted edits into one net
|
|
258
|
+
change:
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
const overrides = input.collection<string, Task>();
|
|
262
|
+
runtime.update(overrides, draft => {
|
|
263
|
+
draft.set(taskId, task);
|
|
264
|
+
draft.remove(oldTaskId);
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
241
268
|
`observe` is the single source boundary for documents, Doxum `Readable` values,
|
|
242
269
|
and eventful external sources. External sources declare `kind: 'value'` or
|
|
243
270
|
`kind: 'collection'`; collection invalidation remains keyed internally.
|
|
@@ -255,7 +282,7 @@ const doubled = incremental.collection([tasks], ({ sources, output }) => {
|
|
|
255
282
|
```
|
|
256
283
|
|
|
257
284
|
Incremental processors receive a dependency-aligned `changes` tuple. Collection
|
|
258
|
-
entries carry
|
|
285
|
+
entries carry `added`/`updated`/`removed` transitions with complete
|
|
259
286
|
`before`/`after` values, so a processor can patch indexes without rescanning the
|
|
260
287
|
collection; scalar dependencies use `undefined` and the initial collection build
|
|
261
288
|
reports `{ kind: 'reset' }`.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { i as snapshot } from "./scope-d-L87NeC.js";
|
|
2
|
+
//#region core/src/projection/definition.ts
|
|
3
|
+
const definitions = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
const owners = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
const define = (definition) => {
|
|
6
|
+
const handle = Object.freeze({});
|
|
7
|
+
definitions.set(handle, definition);
|
|
8
|
+
return handle;
|
|
9
|
+
};
|
|
10
|
+
const definitionOf = (projection) => {
|
|
11
|
+
const definition = definitions.get(projection);
|
|
12
|
+
if (!definition) throw new TypeError("Unknown projection definition.");
|
|
13
|
+
return definition;
|
|
14
|
+
};
|
|
15
|
+
const ownerOf = (projection) => owners.get(projection);
|
|
16
|
+
const ownDefinition = (projection, owner) => {
|
|
17
|
+
if (!definitions.has(projection) || owners.has(projection)) throw new TypeError("Projection definition already has an owner.");
|
|
18
|
+
owners.set(projection, owner);
|
|
19
|
+
return projection;
|
|
20
|
+
};
|
|
21
|
+
const valueInput = (initial, equality = Object.is) => define({
|
|
22
|
+
kind: "input",
|
|
23
|
+
initial,
|
|
24
|
+
isEqual: equality
|
|
25
|
+
});
|
|
26
|
+
const collectionInput = (initial = /* @__PURE__ */ new Map()) => {
|
|
27
|
+
const entries = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const [key, value] of initial) {
|
|
29
|
+
if (typeof key !== "string") throw new TypeError("Projection keys must be strings.");
|
|
30
|
+
entries.set(key, value);
|
|
31
|
+
}
|
|
32
|
+
return define({
|
|
33
|
+
kind: "collection-input",
|
|
34
|
+
initial: entries
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const input = Object.assign(valueInput, { collection: collectionInput });
|
|
38
|
+
function observe(document, selector) {
|
|
39
|
+
if (isExternalSource(document)) return document.kind === "collection" ? defineExternalCollection(document) : defineExternalValue(document);
|
|
40
|
+
if ("current" in document && typeof document.current === "function") return defineReadable(document);
|
|
41
|
+
return define({
|
|
42
|
+
kind: "document",
|
|
43
|
+
document,
|
|
44
|
+
selector
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const isExternalSource = (source) => {
|
|
48
|
+
if (!source || typeof source !== "object") return false;
|
|
49
|
+
const candidate = source;
|
|
50
|
+
return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
|
|
51
|
+
};
|
|
52
|
+
function derive(dependencies, compute, equality = Object.is) {
|
|
53
|
+
if (!Array.isArray(dependencies) || dependencies.some((value) => !definitions.has(value))) throw new TypeError("derive dependencies must be projections.");
|
|
54
|
+
return define({
|
|
55
|
+
kind: "derive",
|
|
56
|
+
dependencies: Object.freeze([...dependencies]),
|
|
57
|
+
compute,
|
|
58
|
+
isEqual: equality
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const defineReadable = (readable, equality = Object.is) => define({
|
|
62
|
+
kind: "readable",
|
|
63
|
+
readable,
|
|
64
|
+
isEqual: equality
|
|
65
|
+
});
|
|
66
|
+
const defineExternalValue = (source) => define({
|
|
67
|
+
kind: "source-value",
|
|
68
|
+
source
|
|
69
|
+
});
|
|
70
|
+
const defineExternalCollection = (source) => define({
|
|
71
|
+
kind: "source-collection",
|
|
72
|
+
source
|
|
73
|
+
});
|
|
74
|
+
const defineIncrementalValue = (definition) => define({
|
|
75
|
+
kind: "incremental-value",
|
|
76
|
+
dependencies: definition.dependencies,
|
|
77
|
+
build: definition.build,
|
|
78
|
+
isEqual: definition.isEqual,
|
|
79
|
+
name: definition.name
|
|
80
|
+
});
|
|
81
|
+
const defineIncrementalCollection = (definition) => define({
|
|
82
|
+
kind: "incremental-collection",
|
|
83
|
+
dependencies: definition.dependencies,
|
|
84
|
+
build: definition.build,
|
|
85
|
+
isEqual: definition.isEqual,
|
|
86
|
+
name: definition.name
|
|
87
|
+
});
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region core/src/projection/advanced.ts
|
|
90
|
+
const resetCollectionChange = Object.freeze({ kind: "reset" });
|
|
91
|
+
const isRebuild = (value) => value !== null && typeof value === "object" && value.kind === "rebuild";
|
|
92
|
+
const collectionChange = (source) => {
|
|
93
|
+
if (!source || typeof source !== "object" || !("kind" in source)) return void 0;
|
|
94
|
+
if (source.kind !== "collection") return void 0;
|
|
95
|
+
return source.change;
|
|
96
|
+
};
|
|
97
|
+
const sourceCause = (sources) => {
|
|
98
|
+
for (const source of Object.values(sources)) if (source && typeof source === "object" && "kind" in source) {
|
|
99
|
+
const cause = source.cause;
|
|
100
|
+
if (cause !== void 0) return cause;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const collectionView = (read) => {
|
|
104
|
+
const entries = function* () {
|
|
105
|
+
for (const key of read.ids()) yield [key, read.get(key)];
|
|
106
|
+
};
|
|
107
|
+
const values = function* () {
|
|
108
|
+
for (const key of read.ids()) yield read.get(key);
|
|
109
|
+
};
|
|
110
|
+
const view = {
|
|
111
|
+
get: (key) => read.get(key),
|
|
112
|
+
has: (key) => read.has(key),
|
|
113
|
+
get size() {
|
|
114
|
+
return read.ids().length;
|
|
115
|
+
},
|
|
116
|
+
keys: () => read.ids()[Symbol.iterator](),
|
|
117
|
+
values,
|
|
118
|
+
entries,
|
|
119
|
+
forEach: (callback, thisArg) => {
|
|
120
|
+
for (const key of read.ids()) callback.call(thisArg, read.get(key), key, view);
|
|
121
|
+
},
|
|
122
|
+
[Symbol.iterator]: entries
|
|
123
|
+
};
|
|
124
|
+
return Object.freeze(view);
|
|
125
|
+
};
|
|
126
|
+
const publicSource = (source) => {
|
|
127
|
+
if (!source || typeof source !== "object") return source;
|
|
128
|
+
if (!("kind" in source)) return source;
|
|
129
|
+
if (source.kind === "value") return source.value;
|
|
130
|
+
if (source.kind === "document") return snapshot(source.read);
|
|
131
|
+
if (source.kind === "collection") {
|
|
132
|
+
const read = source.read;
|
|
133
|
+
return collectionView(read);
|
|
134
|
+
}
|
|
135
|
+
return source;
|
|
136
|
+
};
|
|
137
|
+
const publicInputs = (sources, initial = false) => {
|
|
138
|
+
const values = [];
|
|
139
|
+
const changes = [];
|
|
140
|
+
for (const key of Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))) {
|
|
141
|
+
const source = sources[key];
|
|
142
|
+
values.push(publicSource(source));
|
|
143
|
+
changes.push(initial && source && typeof source === "object" && "kind" in source && source.kind === "collection" ? resetCollectionChange : collectionChange(source));
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
values,
|
|
147
|
+
changes
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
function createIncrementalValue(dependencies, processor) {
|
|
151
|
+
const dependencyMap = dependenciesOf(dependencies);
|
|
152
|
+
const build = (sources) => {
|
|
153
|
+
const state = Object.create(null);
|
|
154
|
+
let current;
|
|
155
|
+
const publicInputsForBuild = publicInputs(sources, true);
|
|
156
|
+
const result = processor({
|
|
157
|
+
sources: publicInputsForBuild.values,
|
|
158
|
+
changes: publicInputsForBuild.changes,
|
|
159
|
+
previous: void 0,
|
|
160
|
+
reset: true,
|
|
161
|
+
cause: sourceCause(sources),
|
|
162
|
+
state
|
|
163
|
+
});
|
|
164
|
+
if (isRebuild(result)) throw new TypeError("Initial incremental processor cannot rebuild.");
|
|
165
|
+
current = result;
|
|
166
|
+
return {
|
|
167
|
+
value: current,
|
|
168
|
+
update: (nextSources) => {
|
|
169
|
+
const publicInputsForUpdate = publicInputs(nextSources);
|
|
170
|
+
const next = processor({
|
|
171
|
+
sources: publicInputsForUpdate.values,
|
|
172
|
+
changes: publicInputsForUpdate.changes,
|
|
173
|
+
previous: current,
|
|
174
|
+
reset: false,
|
|
175
|
+
cause: sourceCause(nextSources),
|
|
176
|
+
state
|
|
177
|
+
});
|
|
178
|
+
if (isRebuild(next)) return next;
|
|
179
|
+
current = next;
|
|
180
|
+
return {
|
|
181
|
+
kind: "changed",
|
|
182
|
+
value: current
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
return defineIncrementalValue({
|
|
188
|
+
dependencies: dependencyMap,
|
|
189
|
+
build
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function dependenciesOf(dependencies) {
|
|
193
|
+
return Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency]));
|
|
194
|
+
}
|
|
195
|
+
function createIncrementalCollection(dependencies, processor) {
|
|
196
|
+
const dependencyMap = dependenciesOf(dependencies);
|
|
197
|
+
const build = (input) => {
|
|
198
|
+
const state = Object.create(null);
|
|
199
|
+
const publicInputsForBuild = publicInputs(input.sources, true);
|
|
200
|
+
if (processor({
|
|
201
|
+
sources: publicInputsForBuild.values,
|
|
202
|
+
changes: publicInputsForBuild.changes,
|
|
203
|
+
previous: input.previous,
|
|
204
|
+
next: input.next,
|
|
205
|
+
reset: true,
|
|
206
|
+
cause: sourceCause(input.sources),
|
|
207
|
+
state,
|
|
208
|
+
output: input.output
|
|
209
|
+
})?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
|
|
210
|
+
return { update: (nextInput) => {
|
|
211
|
+
const publicInputsForUpdate = publicInputs(nextInput.sources);
|
|
212
|
+
return processor({
|
|
213
|
+
sources: publicInputsForUpdate.values,
|
|
214
|
+
changes: publicInputsForUpdate.changes,
|
|
215
|
+
previous: nextInput.previous,
|
|
216
|
+
next: nextInput.next,
|
|
217
|
+
reset: false,
|
|
218
|
+
cause: sourceCause(nextInput.sources),
|
|
219
|
+
state,
|
|
220
|
+
output: nextInput.output
|
|
221
|
+
});
|
|
222
|
+
} };
|
|
223
|
+
};
|
|
224
|
+
return defineIncrementalCollection({
|
|
225
|
+
dependencies: dependencyMap,
|
|
226
|
+
build
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
const incremental = Object.assign(createIncrementalValue, { collection: createIncrementalCollection });
|
|
230
|
+
//#endregion
|
|
231
|
+
export { observe as a, input as i, definitionOf as n, ownDefinition as o, derive as r, ownerOf as s, incremental as t };
|
|
232
|
+
|
|
233
|
+
//# sourceMappingURL=advanced-DgRnyRAc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advanced-DgRnyRAc.js","names":[],"sources":["../core/src/projection/definition.ts","../core/src/projection/advanced.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 definition with no materialized state; root definitions are reusable. */\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, C = undefined> = Projection<T, C> & { 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: 'collection-input'; readonly initial: ReadonlyMap<string, unknown> }\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>();\nconst owners = new WeakMap<object, object>();\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 ownerOf = (projection: DefinitionProjection): object | undefined =>\n owners.get(projection);\n\nexport const ownDefinition = <T, C>(\n projection: Projection<T, C>,\n owner: object\n): Projection<T, C> => {\n if (!definitions.has(projection) || owners.has(projection))\n throw new TypeError('Projection definition already has an owner.');\n owners.set(projection, owner);\n return projection;\n};\n\nconst valueInput = <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\nconst collectionInput = <K extends string, V>(\n initial: ReadonlyMap<K, V> = new Map<K, V>()\n): Input<ReadonlyMap<K, V>, CollectionChange<K, V>> => {\n const entries = new Map<K, V>();\n for (const [key, value] of initial) {\n if (typeof key !== 'string') throw new TypeError('Projection keys must be strings.');\n entries.set(key, value);\n }\n return define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'collection-input',\n initial: entries,\n }) as Input<ReadonlyMap<K, V>, CollectionChange<K, V>>;\n};\n\nexport const input = Object.assign(valueInput, { collection: collectionInput });\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","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 const build = (sources: Record<string, unknown>) => {\n const state: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n let current!: T;\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 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 const state: Record<string, unknown> = 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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"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
const require_scope = require("./scope-Ezs-Y3TY.cjs");
|
|
2
|
+
//#region core/src/projection/definition.ts
|
|
3
|
+
const definitions = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
const owners = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
const define = (definition) => {
|
|
6
|
+
const handle = Object.freeze({});
|
|
7
|
+
definitions.set(handle, definition);
|
|
8
|
+
return handle;
|
|
9
|
+
};
|
|
10
|
+
const definitionOf = (projection) => {
|
|
11
|
+
const definition = definitions.get(projection);
|
|
12
|
+
if (!definition) throw new TypeError("Unknown projection definition.");
|
|
13
|
+
return definition;
|
|
14
|
+
};
|
|
15
|
+
const ownerOf = (projection) => owners.get(projection);
|
|
16
|
+
const ownDefinition = (projection, owner) => {
|
|
17
|
+
if (!definitions.has(projection) || owners.has(projection)) throw new TypeError("Projection definition already has an owner.");
|
|
18
|
+
owners.set(projection, owner);
|
|
19
|
+
return projection;
|
|
20
|
+
};
|
|
21
|
+
const valueInput = (initial, equality = Object.is) => define({
|
|
22
|
+
kind: "input",
|
|
23
|
+
initial,
|
|
24
|
+
isEqual: equality
|
|
25
|
+
});
|
|
26
|
+
const collectionInput = (initial = /* @__PURE__ */ new Map()) => {
|
|
27
|
+
const entries = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const [key, value] of initial) {
|
|
29
|
+
if (typeof key !== "string") throw new TypeError("Projection keys must be strings.");
|
|
30
|
+
entries.set(key, value);
|
|
31
|
+
}
|
|
32
|
+
return define({
|
|
33
|
+
kind: "collection-input",
|
|
34
|
+
initial: entries
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const input = Object.assign(valueInput, { collection: collectionInput });
|
|
38
|
+
function observe(document, selector) {
|
|
39
|
+
if (isExternalSource(document)) return document.kind === "collection" ? defineExternalCollection(document) : defineExternalValue(document);
|
|
40
|
+
if ("current" in document && typeof document.current === "function") return defineReadable(document);
|
|
41
|
+
return define({
|
|
42
|
+
kind: "document",
|
|
43
|
+
document,
|
|
44
|
+
selector
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const isExternalSource = (source) => {
|
|
48
|
+
if (!source || typeof source !== "object") return false;
|
|
49
|
+
const candidate = source;
|
|
50
|
+
return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
|
|
51
|
+
};
|
|
52
|
+
function derive(dependencies, compute, equality = Object.is) {
|
|
53
|
+
if (!Array.isArray(dependencies) || dependencies.some((value) => !definitions.has(value))) throw new TypeError("derive dependencies must be projections.");
|
|
54
|
+
return define({
|
|
55
|
+
kind: "derive",
|
|
56
|
+
dependencies: Object.freeze([...dependencies]),
|
|
57
|
+
compute,
|
|
58
|
+
isEqual: equality
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
const defineReadable = (readable, equality = Object.is) => define({
|
|
62
|
+
kind: "readable",
|
|
63
|
+
readable,
|
|
64
|
+
isEqual: equality
|
|
65
|
+
});
|
|
66
|
+
const defineExternalValue = (source) => define({
|
|
67
|
+
kind: "source-value",
|
|
68
|
+
source
|
|
69
|
+
});
|
|
70
|
+
const defineExternalCollection = (source) => define({
|
|
71
|
+
kind: "source-collection",
|
|
72
|
+
source
|
|
73
|
+
});
|
|
74
|
+
const defineIncrementalValue = (definition) => define({
|
|
75
|
+
kind: "incremental-value",
|
|
76
|
+
dependencies: definition.dependencies,
|
|
77
|
+
build: definition.build,
|
|
78
|
+
isEqual: definition.isEqual,
|
|
79
|
+
name: definition.name
|
|
80
|
+
});
|
|
81
|
+
const defineIncrementalCollection = (definition) => define({
|
|
82
|
+
kind: "incremental-collection",
|
|
83
|
+
dependencies: definition.dependencies,
|
|
84
|
+
build: definition.build,
|
|
85
|
+
isEqual: definition.isEqual,
|
|
86
|
+
name: definition.name
|
|
87
|
+
});
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region core/src/projection/advanced.ts
|
|
90
|
+
const resetCollectionChange = Object.freeze({ kind: "reset" });
|
|
91
|
+
const isRebuild = (value) => value !== null && typeof value === "object" && value.kind === "rebuild";
|
|
92
|
+
const collectionChange = (source) => {
|
|
93
|
+
if (!source || typeof source !== "object" || !("kind" in source)) return void 0;
|
|
94
|
+
if (source.kind !== "collection") return void 0;
|
|
95
|
+
return source.change;
|
|
96
|
+
};
|
|
97
|
+
const sourceCause = (sources) => {
|
|
98
|
+
for (const source of Object.values(sources)) if (source && typeof source === "object" && "kind" in source) {
|
|
99
|
+
const cause = source.cause;
|
|
100
|
+
if (cause !== void 0) return cause;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const collectionView = (read) => {
|
|
104
|
+
const entries = function* () {
|
|
105
|
+
for (const key of read.ids()) yield [key, read.get(key)];
|
|
106
|
+
};
|
|
107
|
+
const values = function* () {
|
|
108
|
+
for (const key of read.ids()) yield read.get(key);
|
|
109
|
+
};
|
|
110
|
+
const view = {
|
|
111
|
+
get: (key) => read.get(key),
|
|
112
|
+
has: (key) => read.has(key),
|
|
113
|
+
get size() {
|
|
114
|
+
return read.ids().length;
|
|
115
|
+
},
|
|
116
|
+
keys: () => read.ids()[Symbol.iterator](),
|
|
117
|
+
values,
|
|
118
|
+
entries,
|
|
119
|
+
forEach: (callback, thisArg) => {
|
|
120
|
+
for (const key of read.ids()) callback.call(thisArg, read.get(key), key, view);
|
|
121
|
+
},
|
|
122
|
+
[Symbol.iterator]: entries
|
|
123
|
+
};
|
|
124
|
+
return Object.freeze(view);
|
|
125
|
+
};
|
|
126
|
+
const publicSource = (source) => {
|
|
127
|
+
if (!source || typeof source !== "object") return source;
|
|
128
|
+
if (!("kind" in source)) return source;
|
|
129
|
+
if (source.kind === "value") return source.value;
|
|
130
|
+
if (source.kind === "document") return require_scope.snapshot(source.read);
|
|
131
|
+
if (source.kind === "collection") {
|
|
132
|
+
const read = source.read;
|
|
133
|
+
return collectionView(read);
|
|
134
|
+
}
|
|
135
|
+
return source;
|
|
136
|
+
};
|
|
137
|
+
const publicInputs = (sources, initial = false) => {
|
|
138
|
+
const values = [];
|
|
139
|
+
const changes = [];
|
|
140
|
+
for (const key of Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))) {
|
|
141
|
+
const source = sources[key];
|
|
142
|
+
values.push(publicSource(source));
|
|
143
|
+
changes.push(initial && source && typeof source === "object" && "kind" in source && source.kind === "collection" ? resetCollectionChange : collectionChange(source));
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
values,
|
|
147
|
+
changes
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
function createIncrementalValue(dependencies, processor) {
|
|
151
|
+
const dependencyMap = dependenciesOf(dependencies);
|
|
152
|
+
const build = (sources) => {
|
|
153
|
+
const state = Object.create(null);
|
|
154
|
+
let current;
|
|
155
|
+
const publicInputsForBuild = publicInputs(sources, true);
|
|
156
|
+
const result = processor({
|
|
157
|
+
sources: publicInputsForBuild.values,
|
|
158
|
+
changes: publicInputsForBuild.changes,
|
|
159
|
+
previous: void 0,
|
|
160
|
+
reset: true,
|
|
161
|
+
cause: sourceCause(sources),
|
|
162
|
+
state
|
|
163
|
+
});
|
|
164
|
+
if (isRebuild(result)) throw new TypeError("Initial incremental processor cannot rebuild.");
|
|
165
|
+
current = result;
|
|
166
|
+
return {
|
|
167
|
+
value: current,
|
|
168
|
+
update: (nextSources) => {
|
|
169
|
+
const publicInputsForUpdate = publicInputs(nextSources);
|
|
170
|
+
const next = processor({
|
|
171
|
+
sources: publicInputsForUpdate.values,
|
|
172
|
+
changes: publicInputsForUpdate.changes,
|
|
173
|
+
previous: current,
|
|
174
|
+
reset: false,
|
|
175
|
+
cause: sourceCause(nextSources),
|
|
176
|
+
state
|
|
177
|
+
});
|
|
178
|
+
if (isRebuild(next)) return next;
|
|
179
|
+
current = next;
|
|
180
|
+
return {
|
|
181
|
+
kind: "changed",
|
|
182
|
+
value: current
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
return defineIncrementalValue({
|
|
188
|
+
dependencies: dependencyMap,
|
|
189
|
+
build
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function dependenciesOf(dependencies) {
|
|
193
|
+
return Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency]));
|
|
194
|
+
}
|
|
195
|
+
function createIncrementalCollection(dependencies, processor) {
|
|
196
|
+
const dependencyMap = dependenciesOf(dependencies);
|
|
197
|
+
const build = (input) => {
|
|
198
|
+
const state = Object.create(null);
|
|
199
|
+
const publicInputsForBuild = publicInputs(input.sources, true);
|
|
200
|
+
if (processor({
|
|
201
|
+
sources: publicInputsForBuild.values,
|
|
202
|
+
changes: publicInputsForBuild.changes,
|
|
203
|
+
previous: input.previous,
|
|
204
|
+
next: input.next,
|
|
205
|
+
reset: true,
|
|
206
|
+
cause: sourceCause(input.sources),
|
|
207
|
+
state,
|
|
208
|
+
output: input.output
|
|
209
|
+
})?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
|
|
210
|
+
return { update: (nextInput) => {
|
|
211
|
+
const publicInputsForUpdate = publicInputs(nextInput.sources);
|
|
212
|
+
return processor({
|
|
213
|
+
sources: publicInputsForUpdate.values,
|
|
214
|
+
changes: publicInputsForUpdate.changes,
|
|
215
|
+
previous: nextInput.previous,
|
|
216
|
+
next: nextInput.next,
|
|
217
|
+
reset: false,
|
|
218
|
+
cause: sourceCause(nextInput.sources),
|
|
219
|
+
state,
|
|
220
|
+
output: nextInput.output
|
|
221
|
+
});
|
|
222
|
+
} };
|
|
223
|
+
};
|
|
224
|
+
return defineIncrementalCollection({
|
|
225
|
+
dependencies: dependencyMap,
|
|
226
|
+
build
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
const incremental = Object.assign(createIncrementalValue, { collection: createIncrementalCollection });
|
|
230
|
+
//#endregion
|
|
231
|
+
Object.defineProperty(exports, "definitionOf", {
|
|
232
|
+
enumerable: true,
|
|
233
|
+
get: function() {
|
|
234
|
+
return definitionOf;
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
Object.defineProperty(exports, "derive", {
|
|
238
|
+
enumerable: true,
|
|
239
|
+
get: function() {
|
|
240
|
+
return derive;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
Object.defineProperty(exports, "incremental", {
|
|
244
|
+
enumerable: true,
|
|
245
|
+
get: function() {
|
|
246
|
+
return incremental;
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
Object.defineProperty(exports, "input", {
|
|
250
|
+
enumerable: true,
|
|
251
|
+
get: function() {
|
|
252
|
+
return input;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
Object.defineProperty(exports, "observe", {
|
|
256
|
+
enumerable: true,
|
|
257
|
+
get: function() {
|
|
258
|
+
return observe;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
Object.defineProperty(exports, "ownDefinition", {
|
|
262
|
+
enumerable: true,
|
|
263
|
+
get: function() {
|
|
264
|
+
return ownDefinition;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
Object.defineProperty(exports, "ownerOf", {
|
|
268
|
+
enumerable: true,
|
|
269
|
+
get: function() {
|
|
270
|
+
return ownerOf;
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
//# sourceMappingURL=advanced-Dgu8-bPS.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"advanced-Dgu8-bPS.cjs","names":["snapshot"],"sources":["../core/src/projection/definition.ts","../core/src/projection/advanced.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 definition with no materialized state; root definitions are reusable. */\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, C = undefined> = Projection<T, C> & { 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: 'collection-input'; readonly initial: ReadonlyMap<string, unknown> }\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>();\nconst owners = new WeakMap<object, object>();\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 ownerOf = (projection: DefinitionProjection): object | undefined =>\n owners.get(projection);\n\nexport const ownDefinition = <T, C>(\n projection: Projection<T, C>,\n owner: object\n): Projection<T, C> => {\n if (!definitions.has(projection) || owners.has(projection))\n throw new TypeError('Projection definition already has an owner.');\n owners.set(projection, owner);\n return projection;\n};\n\nconst valueInput = <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\nconst collectionInput = <K extends string, V>(\n initial: ReadonlyMap<K, V> = new Map<K, V>()\n): Input<ReadonlyMap<K, V>, CollectionChange<K, V>> => {\n const entries = new Map<K, V>();\n for (const [key, value] of initial) {\n if (typeof key !== 'string') throw new TypeError('Projection keys must be strings.');\n entries.set(key, value);\n }\n return define<ReadonlyMap<K, V>, CollectionChange<K, V>>({\n kind: 'collection-input',\n initial: entries,\n }) as Input<ReadonlyMap<K, V>, CollectionChange<K, V>>;\n};\n\nexport const input = Object.assign(valueInput, { collection: collectionInput });\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","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 const build = (sources: Record<string, unknown>) => {\n const state: Record<string, unknown> = Object.create(null) as Record<string, unknown>;\n let current!: T;\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 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 const state: Record<string, unknown> = 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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"}
|