doxum 0.1.14 → 0.1.16

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.
Files changed (56) hide show
  1. package/README.md +12 -2
  2. package/dist/advanced.cjs +71 -21
  3. package/dist/advanced.cjs.map +1 -1
  4. package/dist/advanced.d.cts +14 -14
  5. package/dist/advanced.d.ts +14 -14
  6. package/dist/advanced.js +70 -20
  7. package/dist/advanced.js.map +1 -1
  8. package/dist/{contract-BT53Gg94.d.ts → contract-CATCCVu5.d.ts} +1 -1
  9. package/dist/{definition-DN6yW2vi.d.cts → definition-C__VJqA4.d.cts} +45 -8
  10. package/dist/{definition-Dr8tHwTD.d.ts → definition-Dc1Udkop.d.ts} +46 -9
  11. package/dist/definition-Z6TagMup.cjs +107 -0
  12. package/dist/definition-Z6TagMup.cjs.map +1 -0
  13. package/dist/definition-c6XQXzvK.js +72 -0
  14. package/dist/definition-c6XQXzvK.js.map +1 -0
  15. package/dist/index.cjs +2080 -55
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +16 -3
  18. package/dist/index.d.ts +17 -4
  19. package/dist/index.js +2027 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/{integration-WniqaEPW.cjs → integration-B7VDgAOJ.cjs} +4 -4
  22. package/dist/integration-B7VDgAOJ.cjs.map +1 -0
  23. package/dist/{integration-zB8e-uNP.js → integration-CxVhq-KD.js} +2 -2
  24. package/dist/integration-CxVhq-KD.js.map +1 -0
  25. package/dist/integration.cjs +4 -6
  26. package/dist/integration.d.cts +1 -2
  27. package/dist/integration.d.ts +2 -3
  28. package/dist/integration.js +3 -3
  29. package/dist/local-sync.d.ts +1 -1
  30. package/dist/notification-CDSUfiip.cjs +398 -0
  31. package/dist/notification-CDSUfiip.cjs.map +1 -0
  32. package/dist/notification-IQIJyH3Q.js +285 -0
  33. package/dist/notification-IQIJyH3Q.js.map +1 -0
  34. package/dist/react.cjs +6 -52
  35. package/dist/react.cjs.map +1 -1
  36. package/dist/react.d.cts +3 -3
  37. package/dist/react.d.ts +3 -3
  38. package/dist/react.js +4 -50
  39. package/dist/react.js.map +1 -1
  40. package/dist/{definition-BDW6i7fp.cjs → scope-Ezs-Y3TY.cjs} +1 -106
  41. package/dist/scope-Ezs-Y3TY.cjs.map +1 -0
  42. package/dist/{definition-wOvuklwp.js → scope-d-L87NeC.js} +2 -71
  43. package/dist/scope-d-L87NeC.js.map +1 -0
  44. package/package.json +1 -1
  45. package/skills/doxum-runtime/references/projections.en.md +16 -8
  46. package/skills/doxum-runtime/references/projections.zh-CN.md +14 -7
  47. package/dist/definition-BDW6i7fp.cjs.map +0 -1
  48. package/dist/definition-wOvuklwp.js.map +0 -1
  49. package/dist/integration-WniqaEPW.cjs.map +0 -1
  50. package/dist/integration-zB8e-uNP.js.map +0 -1
  51. package/dist/store-6wMvZthf.cjs +0 -2399
  52. package/dist/store-6wMvZthf.cjs.map +0 -1
  53. package/dist/store-BCR20XSb.d.ts +0 -28
  54. package/dist/store-PLKs1KnS.js +0 -2220
  55. package/dist/store-PLKs1KnS.js.map +0 -1
  56. package/dist/store-jJ3SNYKH.d.cts +0 -28
package/README.md CHANGED
@@ -220,6 +220,8 @@ const visible = derive([tasks, filter], (all, mode) => {
220
220
 
221
221
  const runtime = createProjectionRuntime({ onError: console.error });
222
222
  runtime.get(visible);
223
+ const selected = runtime.readable(visible, tasks => tasks.get('a'));
224
+ const stop = selected.subscribe(() => selected.current());
223
225
  runtime.set(filter, 'open');
224
226
  runtime.batch({ cause: { action: 'refresh' } }, () => {
225
227
  runtime.set(filter, 'all');
@@ -227,12 +229,14 @@ runtime.batch({ cause: { action: 'refresh' } }, () => {
227
229
  draft.title = 'Updated';
228
230
  });
229
231
  });
232
+ stop();
230
233
  ```
231
234
 
232
235
  Projection declarations are lazy and reusable. The only Runtime operations are
233
- `get`, `subscribe`, `set`, `batch` and `dispose`; materialization, incremental
236
+ `get`, `readable`, `set`, `batch` and `dispose`; materialization, incremental
234
237
  state, publication and recovery stay inside the Runtime. Collection values are
235
- immutable `ReadonlyMap`-like snapshots, so callers do not hold lifecycle handles.
238
+ immutable `ReadonlyMap`-like snapshots, while a `Readable` owns selector
239
+ tracking, equality and subscription lifecycle.
236
240
 
237
241
  `observe` is the single source boundary for documents, Doxum `Readable` values,
238
242
  and eventful external sources. External sources declare `kind: 'value'` or
@@ -250,6 +254,12 @@ const doubled = incremental.collection([tasks], ({ sources, output }) => {
250
254
  });
251
255
  ```
252
256
 
257
+ Incremental processors receive a dependency-aligned `changes` tuple. Collection
258
+ entries carry discriminated `added`/`updated`/`removed` transitions with complete
259
+ `before`/`after` values, so a processor can patch indexes without rescanning the
260
+ collection; scalar dependencies use `undefined` and the initial collection build
261
+ reports `{ kind: 'reset' }`.
262
+
253
263
  In React, `useProjection(projection)` reads a value and
254
264
  `useProjection(projection, selector, equality?)` tracks keyed reads such as
255
265
  `tasks => tasks.get(taskId)`. Unrelated key changes do not execute that selector;
package/dist/advanced.cjs CHANGED
@@ -1,9 +1,41 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_definition = require("./definition-BDW6i7fp.cjs");
2
+ const require_scope = require("./scope-Ezs-Y3TY.cjs");
3
+ const require_definition = require("./definition-Z6TagMup.cjs");
3
4
  //#region core/src/projection/advanced.ts
4
5
  const dependenciesOf = (dependencies) => Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency]));
5
- const sourceChange = (sources) => {
6
- for (const source of Object.values(sources)) if (source && typeof source === "object" && "change" in source && source.change !== void 0) return source.change;
6
+ const resetCollectionChange = Object.freeze({ kind: "reset" });
7
+ const isCollectionSource = (source) => Boolean(source && typeof source === "object" && "ids" in source && typeof source.ids === "function" && "previous" in source && "transitions" in source && typeof source.transitions === "function");
8
+ const collectionChange = (source) => {
9
+ if (!isCollectionSource(source)) return void 0;
10
+ if (source.reset || source.change?.kind === "reset") return resetCollectionChange;
11
+ const impact = source.change;
12
+ if (!impact) return void 0;
13
+ const added = [];
14
+ const updated = [];
15
+ const removed = [];
16
+ for (const transition of source.transitions()) if (transition.kind === "added") added.push({
17
+ key: transition.key,
18
+ kind: transition.kind,
19
+ after: transition.after
20
+ });
21
+ else if (transition.kind === "updated") updated.push(transition);
22
+ else removed.push({
23
+ key: transition.key,
24
+ kind: transition.kind,
25
+ before: transition.before
26
+ });
27
+ const order = impact.orderChanged ? {
28
+ before: Object.freeze([...source.previous.ids()]),
29
+ after: Object.freeze([...source.ids()])
30
+ } : void 0;
31
+ if (!added.length && !updated.length && !removed.length && !order) return void 0;
32
+ return Object.freeze({
33
+ kind: "incremental",
34
+ added: Object.freeze(added),
35
+ updated: Object.freeze(updated),
36
+ removed: Object.freeze(removed),
37
+ ...order ? { order: Object.freeze(order) } : {}
38
+ });
7
39
  };
8
40
  const sourceCause = (sources) => {
9
41
  for (const source of Object.values(sources)) if (source && typeof source === "object" && "cause" in source && source.cause !== void 0) return source.cause;
@@ -18,7 +50,7 @@ const publicSource = (source) => {
18
50
  for (const id of read.ids()) result.set(id, read.get(id));
19
51
  return result;
20
52
  }
21
- return require_definition.snapshot(read);
53
+ return require_scope.snapshot(read);
22
54
  }
23
55
  if ("ids" in source && typeof source.ids === "function") {
24
56
  const result = /* @__PURE__ */ new Map();
@@ -28,7 +60,19 @@ const publicSource = (source) => {
28
60
  }
29
61
  return source;
30
62
  };
31
- const publicTuple = (sources) => Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1))).map((key) => publicSource(sources[key]));
63
+ const publicInputs = (sources, initial = false) => {
64
+ const values = [];
65
+ const changes = [];
66
+ for (const key of Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))) {
67
+ const source = sources[key];
68
+ values.push(publicSource(source));
69
+ changes.push(initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source));
70
+ }
71
+ return {
72
+ values,
73
+ changes
74
+ };
75
+ };
32
76
  const normalizeValue = (result) => result && typeof result === "object" && result.kind === "value" ? {
33
77
  value: result.value,
34
78
  state: result.state
@@ -39,11 +83,12 @@ function createIncrementalValue(dependencies, processor) {
39
83
  let current;
40
84
  const build = (sources) => {
41
85
  state = Object.create(null);
86
+ const publicInputsForBuild = publicInputs(sources, true);
42
87
  const result = processor({
43
- sources: publicTuple(sources),
88
+ sources: publicInputsForBuild.values,
89
+ changes: publicInputsForBuild.changes,
44
90
  previous: void 0,
45
91
  reset: true,
46
- change: void 0,
47
92
  cause: sourceCause(sources),
48
93
  state
49
94
  });
@@ -54,11 +99,12 @@ function createIncrementalValue(dependencies, processor) {
54
99
  return {
55
100
  value: current,
56
101
  update: (nextSources) => {
102
+ const publicInputsForUpdate = publicInputs(nextSources);
57
103
  const next = processor({
58
- sources: publicTuple(nextSources),
104
+ sources: publicInputsForUpdate.values,
105
+ changes: publicInputsForUpdate.changes,
59
106
  previous: current,
60
107
  reset: false,
61
- change: sourceChange(nextSources),
62
108
  cause: sourceCause(nextSources),
63
109
  state
64
110
  });
@@ -83,26 +129,30 @@ function createIncrementalCollection(dependencies, processor) {
83
129
  let state = Object.create(null);
84
130
  const build = (input) => {
85
131
  state = Object.create(null);
132
+ const publicInputsForBuild = publicInputs(input.sources, true);
86
133
  if (processor({
87
- sources: publicTuple(input.sources),
134
+ sources: publicInputsForBuild.values,
135
+ changes: publicInputsForBuild.changes,
88
136
  previous: input.previous,
89
137
  next: input.next,
90
138
  reset: true,
91
- change: void 0,
92
139
  cause: sourceCause(input.sources),
93
140
  state,
94
141
  output: input.writer
95
142
  })?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
96
- return { update: (nextInput) => processor({
97
- sources: publicTuple(nextInput.sources),
98
- previous: nextInput.previous,
99
- next: nextInput.next,
100
- reset: false,
101
- change: sourceChange(nextInput.sources),
102
- cause: sourceCause(nextInput.sources),
103
- state,
104
- output: nextInput.writer
105
- }) };
143
+ return { update: (nextInput) => {
144
+ const publicInputsForUpdate = publicInputs(nextInput.sources);
145
+ return processor({
146
+ sources: publicInputsForUpdate.values,
147
+ changes: publicInputsForUpdate.changes,
148
+ previous: nextInput.previous,
149
+ next: nextInput.next,
150
+ reset: false,
151
+ cause: sourceCause(nextInput.sources),
152
+ state,
153
+ output: nextInput.writer
154
+ });
155
+ } };
106
156
  };
107
157
  return require_definition.defineIncrementalCollection({
108
158
  dependencies: dependencyMap,
@@ -1 +1 @@
1
- {"version":3,"file":"advanced.cjs","names":["snapshot","defineIncrementalValue","defineIncrementalCollection"],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type { Projection, ProjectionValues, PublicCollection } from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type { CollectionDraft, CollectionRead, GraphSources } from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<S, T> = {\n readonly sources: S;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly change: unknown;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<S, T> = (\n context: IncrementalValueContext<S, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<S, K extends string, V> = {\n readonly sources: S;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly change: unknown;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<S, K extends string, V> = (\n context: IncrementalCollectionContext<S, K, V>\n) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown>[]>(dependencies: D): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\nconst sourceChange = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'change' in source &&\n (source as { readonly change?: unknown }).change !== undefined\n )\n return (source as { readonly change?: unknown }).change;\n }\n return undefined;\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicTuple = (sources: Record<string, unknown>): readonly unknown[] =>\n Object.keys(sources)\n .sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))\n .map(key => publicSource(sources[key]));\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<ProjectionValues<D>, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const result = processor({\n sources: publicTuple(sources) as ProjectionValues<D>,\n previous: undefined,\n reset: true,\n change: undefined,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const next = processor({\n sources: publicTuple(nextSources) as ProjectionValues<D>,\n previous: current,\n reset: false,\n change: sourceChange(nextSources),\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown>[],\n K extends string,\n V,\n>(\n dependencies: D,\n processor: IncrementalCollectionProcessor<ProjectionValues<D>, K, V>\n): Projection<PublicCollection<K, V>> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const result = processor({\n sources: publicTuple(input.sources) as ProjectionValues<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n change: undefined,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) =>\n processor({\n sources: publicTuple(nextInput.sources) as ProjectionValues<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n change: sourceChange(nextInput.sources),\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\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>[]> = DependencyMap<D>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"advanced.cjs","names":["snapshot","defineIncrementalValue","defineIncrementalCollection"],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type {\n Projection,\n CollectionProjection,\n ProjectionChanges,\n ProjectionValues,\n PublicCollection,\n} from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionEntryTransition,\n CollectionRead,\n GraphSources,\n} from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = (context: IncrementalCollectionContext<D, K, V>) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\ntype RuntimeCollectionSource = {\n readonly ids: () => readonly string[];\n readonly previous: CollectionRead<string, unknown>;\n readonly reset: boolean;\n readonly change?: { readonly kind: 'reset' | 'incremental'; readonly orderChanged?: boolean };\n readonly transitions: () => readonly CollectionEntryTransition<string, unknown>[];\n};\nconst resetCollectionChange = Object.freeze({ kind: 'reset' as const });\ntype IncrementalCollectionChange = Extract<\n CollectionChange<string, unknown>,\n { readonly kind: 'incremental' }\n>;\n\nconst isCollectionSource = (source: unknown): source is RuntimeCollectionSource =>\n Boolean(\n source &&\n typeof source === 'object' &&\n 'ids' in source &&\n typeof (source as { readonly ids?: unknown }).ids === 'function' &&\n 'previous' in source &&\n 'transitions' in source &&\n typeof (source as { readonly transitions?: unknown }).transitions === 'function'\n );\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!isCollectionSource(source)) return undefined;\n if (source.reset || source.change?.kind === 'reset') return resetCollectionChange;\n const impact = source.change;\n if (!impact) return undefined;\n const added: IncrementalCollectionChange['added'][number][] = [];\n const updated: IncrementalCollectionChange['updated'][number][] = [];\n const removed: IncrementalCollectionChange['removed'][number][] = [];\n for (const transition of source.transitions()) {\n if (transition.kind === 'added')\n added.push({ key: transition.key, kind: transition.kind, after: transition.after });\n else if (transition.kind === 'updated') updated.push(transition);\n else removed.push({ key: transition.key, kind: transition.kind, before: transition.before });\n }\n const order = impact.orderChanged\n ? {\n before: Object.freeze([...source.previous.ids()]),\n after: Object.freeze([...source.ids()]),\n }\n : undefined;\n if (!added.length && !updated.length && !removed.length && !order) return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze(added),\n updated: Object.freeze(updated),\n removed: Object.freeze(removed),\n ...(order ? { order: Object.freeze(order) } : {}),\n });\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicInputs = (\n sources: Record<string, unknown>,\n initial = false\n): { readonly values: readonly unknown[]; readonly changes: readonly unknown[] } => {\n const values: unknown[] = [];\n const changes: unknown[] = [];\n for (const key of Object.keys(sources).sort(\n (left, right) => Number(left.slice(1)) - Number(right.slice(1))\n )) {\n const source = sources[key];\n values.push(publicSource(source));\n changes.push(\n initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source)\n );\n }\n return { values, changes };\n};\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<D, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: undefined,\n reset: true,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const publicInputsForUpdate = publicInputs(nextSources);\n const next = processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: current,\n reset: false,\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(input.sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) => {\n const publicInputsForUpdate = publicInputs(nextInput.sources);\n return processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\n });\n },\n };\n };\n return defineIncrementalCollection({ dependencies: dependencyMap, build: build as never });\n}\n\nexport const incremental = Object.assign(createIncrementalValue, {\n collection: createIncrementalCollection,\n});\n\nexport type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> =\n DependencyMap<D>;\n\nexport type { CollectionChange } from './contract';\n"],"mappings":"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"}
@@ -1,42 +1,42 @@
1
- import { i as PublicCollection, l as CollectionDraft, n as Projection, r as ProjectionValues, u as CollectionRead } from "./definition-DN6yW2vi.cjs";
1
+ import { a as ProjectionValues, d as CollectionChange, f as CollectionDraft, i as ProjectionChanges, p as CollectionRead, r as Projection, t as CollectionProjection } from "./definition-C__VJqA4.cjs";
2
2
 
3
3
  //#region core/src/projection/advanced.d.ts
4
4
  type IncrementalState = Record<string, unknown>;
5
- type IncrementalValueContext<S, T> = {
6
- readonly sources: S;
5
+ type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {
6
+ readonly sources: ProjectionValues<D>;
7
+ readonly changes: ProjectionChanges<D>;
7
8
  readonly previous: T | undefined;
8
9
  readonly reset: boolean;
9
- readonly change: unknown;
10
10
  readonly cause: unknown;
11
11
  readonly state: IncrementalState;
12
12
  };
13
- type IncrementalValueProcessor<S, T> = (context: IncrementalValueContext<S, T>) => T | {
13
+ type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (context: IncrementalValueContext<D, T>) => T | {
14
14
  readonly kind: 'value';
15
15
  readonly value: T;
16
16
  readonly state?: IncrementalState;
17
17
  } | {
18
18
  readonly kind: 'rebuild';
19
19
  };
20
- type IncrementalCollectionContext<S, K extends string, V> = {
21
- readonly sources: S;
20
+ type IncrementalCollectionContext<D extends readonly Projection<unknown, unknown>[], K extends string, V> = {
21
+ readonly sources: ProjectionValues<D>;
22
+ readonly changes: ProjectionChanges<D>;
22
23
  readonly previous: CollectionRead<K, V>;
23
24
  readonly next: CollectionRead<K, V>;
24
- readonly change: unknown;
25
25
  readonly reset: boolean;
26
26
  readonly cause: unknown;
27
27
  readonly state: IncrementalState;
28
28
  readonly output: CollectionDraft<K, V>;
29
29
  };
30
- type IncrementalCollectionProcessor<S, K extends string, V> = (context: IncrementalCollectionContext<S, K, V>) => void | {
30
+ type IncrementalCollectionProcessor<D extends readonly Projection<unknown, unknown>[], K extends string, V> = (context: IncrementalCollectionContext<D, K, V>) => void | {
31
31
  readonly kind: 'rebuild';
32
32
  };
33
- type DependencyMap<D extends readonly Projection<unknown>[]> = { readonly [K in keyof D as `d${Extract<K, number>}`]: D[K] };
34
- declare function createIncrementalValue<const D extends readonly Projection<unknown>[], T>(dependencies: D, processor: IncrementalValueProcessor<ProjectionValues<D>, T>): Projection<T>;
35
- declare function createIncrementalCollection<const D extends readonly Projection<unknown>[], K extends string, V>(dependencies: D, processor: IncrementalCollectionProcessor<ProjectionValues<D>, K, V>): Projection<PublicCollection<K, V>>;
33
+ type DependencyMap<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D as `d${Extract<K, number>}`]: D[K] };
34
+ declare function createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(dependencies: D, processor: IncrementalValueProcessor<D, T>): Projection<T>;
35
+ declare function createIncrementalCollection<const D extends readonly Projection<unknown, unknown>[], K extends string, V>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V>;
36
36
  declare const incremental: typeof createIncrementalValue & {
37
37
  collection: typeof createIncrementalCollection;
38
38
  };
39
- type IncrementalDependencies<D extends readonly Projection<unknown>[]> = DependencyMap<D>;
39
+ type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> = DependencyMap<D>;
40
40
  //#endregion
41
- export { IncrementalCollectionContext, IncrementalCollectionProcessor, IncrementalDependencies, IncrementalState, IncrementalValueContext, IncrementalValueProcessor, incremental };
41
+ export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionProcessor, IncrementalDependencies, IncrementalState, IncrementalValueContext, IncrementalValueProcessor, incremental };
42
42
  //# sourceMappingURL=advanced.d.cts.map
@@ -1,42 +1,42 @@
1
- import { i as PublicCollection, l as CollectionDraft, n as Projection, r as ProjectionValues, u as CollectionRead } from "./definition-Dr8tHwTD.js";
1
+ import { a as ProjectionValues, d as CollectionChange, f as CollectionDraft, i as ProjectionChanges, p as CollectionRead, r as Projection, t as CollectionProjection } from "./definition-Dc1Udkop.js";
2
2
 
3
3
  //#region core/src/projection/advanced.d.ts
4
4
  type IncrementalState = Record<string, unknown>;
5
- type IncrementalValueContext<S, T> = {
6
- readonly sources: S;
5
+ type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {
6
+ readonly sources: ProjectionValues<D>;
7
+ readonly changes: ProjectionChanges<D>;
7
8
  readonly previous: T | undefined;
8
9
  readonly reset: boolean;
9
- readonly change: unknown;
10
10
  readonly cause: unknown;
11
11
  readonly state: IncrementalState;
12
12
  };
13
- type IncrementalValueProcessor<S, T> = (context: IncrementalValueContext<S, T>) => T | {
13
+ type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (context: IncrementalValueContext<D, T>) => T | {
14
14
  readonly kind: 'value';
15
15
  readonly value: T;
16
16
  readonly state?: IncrementalState;
17
17
  } | {
18
18
  readonly kind: 'rebuild';
19
19
  };
20
- type IncrementalCollectionContext<S, K extends string, V> = {
21
- readonly sources: S;
20
+ type IncrementalCollectionContext<D extends readonly Projection<unknown, unknown>[], K extends string, V> = {
21
+ readonly sources: ProjectionValues<D>;
22
+ readonly changes: ProjectionChanges<D>;
22
23
  readonly previous: CollectionRead<K, V>;
23
24
  readonly next: CollectionRead<K, V>;
24
- readonly change: unknown;
25
25
  readonly reset: boolean;
26
26
  readonly cause: unknown;
27
27
  readonly state: IncrementalState;
28
28
  readonly output: CollectionDraft<K, V>;
29
29
  };
30
- type IncrementalCollectionProcessor<S, K extends string, V> = (context: IncrementalCollectionContext<S, K, V>) => void | {
30
+ type IncrementalCollectionProcessor<D extends readonly Projection<unknown, unknown>[], K extends string, V> = (context: IncrementalCollectionContext<D, K, V>) => void | {
31
31
  readonly kind: 'rebuild';
32
32
  };
33
- type DependencyMap<D extends readonly Projection<unknown>[]> = { readonly [K in keyof D as `d${Extract<K, number>}`]: D[K] };
34
- declare function createIncrementalValue<const D extends readonly Projection<unknown>[], T>(dependencies: D, processor: IncrementalValueProcessor<ProjectionValues<D>, T>): Projection<T>;
35
- declare function createIncrementalCollection<const D extends readonly Projection<unknown>[], K extends string, V>(dependencies: D, processor: IncrementalCollectionProcessor<ProjectionValues<D>, K, V>): Projection<PublicCollection<K, V>>;
33
+ type DependencyMap<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D as `d${Extract<K, number>}`]: D[K] };
34
+ declare function createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(dependencies: D, processor: IncrementalValueProcessor<D, T>): Projection<T>;
35
+ declare function createIncrementalCollection<const D extends readonly Projection<unknown, unknown>[], K extends string, V>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V>;
36
36
  declare const incremental: typeof createIncrementalValue & {
37
37
  collection: typeof createIncrementalCollection;
38
38
  };
39
- type IncrementalDependencies<D extends readonly Projection<unknown>[]> = DependencyMap<D>;
39
+ type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> = DependencyMap<D>;
40
40
  //#endregion
41
- export { IncrementalCollectionContext, IncrementalCollectionProcessor, IncrementalDependencies, IncrementalState, IncrementalValueContext, IncrementalValueProcessor, incremental };
41
+ export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionProcessor, IncrementalDependencies, IncrementalState, IncrementalValueContext, IncrementalValueProcessor, incremental };
42
42
  //# sourceMappingURL=advanced.d.ts.map
package/dist/advanced.js CHANGED
@@ -1,8 +1,40 @@
1
- import { n as defineIncrementalValue, t as defineIncrementalCollection, u as snapshot } from "./definition-wOvuklwp.js";
1
+ import { i as snapshot } from "./scope-d-L87NeC.js";
2
+ import { n as defineIncrementalValue, t as defineIncrementalCollection } from "./definition-c6XQXzvK.js";
2
3
  //#region core/src/projection/advanced.ts
3
4
  const dependenciesOf = (dependencies) => Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency]));
4
- const sourceChange = (sources) => {
5
- for (const source of Object.values(sources)) if (source && typeof source === "object" && "change" in source && source.change !== void 0) return source.change;
5
+ const resetCollectionChange = Object.freeze({ kind: "reset" });
6
+ const isCollectionSource = (source) => Boolean(source && typeof source === "object" && "ids" in source && typeof source.ids === "function" && "previous" in source && "transitions" in source && typeof source.transitions === "function");
7
+ const collectionChange = (source) => {
8
+ if (!isCollectionSource(source)) return void 0;
9
+ if (source.reset || source.change?.kind === "reset") return resetCollectionChange;
10
+ const impact = source.change;
11
+ if (!impact) return void 0;
12
+ const added = [];
13
+ const updated = [];
14
+ const removed = [];
15
+ for (const transition of source.transitions()) if (transition.kind === "added") added.push({
16
+ key: transition.key,
17
+ kind: transition.kind,
18
+ after: transition.after
19
+ });
20
+ else if (transition.kind === "updated") updated.push(transition);
21
+ else removed.push({
22
+ key: transition.key,
23
+ kind: transition.kind,
24
+ before: transition.before
25
+ });
26
+ const order = impact.orderChanged ? {
27
+ before: Object.freeze([...source.previous.ids()]),
28
+ after: Object.freeze([...source.ids()])
29
+ } : void 0;
30
+ if (!added.length && !updated.length && !removed.length && !order) return void 0;
31
+ return Object.freeze({
32
+ kind: "incremental",
33
+ added: Object.freeze(added),
34
+ updated: Object.freeze(updated),
35
+ removed: Object.freeze(removed),
36
+ ...order ? { order: Object.freeze(order) } : {}
37
+ });
6
38
  };
7
39
  const sourceCause = (sources) => {
8
40
  for (const source of Object.values(sources)) if (source && typeof source === "object" && "cause" in source && source.cause !== void 0) return source.cause;
@@ -27,7 +59,19 @@ const publicSource = (source) => {
27
59
  }
28
60
  return source;
29
61
  };
30
- const publicTuple = (sources) => Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1))).map((key) => publicSource(sources[key]));
62
+ const publicInputs = (sources, initial = false) => {
63
+ const values = [];
64
+ const changes = [];
65
+ for (const key of Object.keys(sources).sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))) {
66
+ const source = sources[key];
67
+ values.push(publicSource(source));
68
+ changes.push(initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source));
69
+ }
70
+ return {
71
+ values,
72
+ changes
73
+ };
74
+ };
31
75
  const normalizeValue = (result) => result && typeof result === "object" && result.kind === "value" ? {
32
76
  value: result.value,
33
77
  state: result.state
@@ -38,11 +82,12 @@ function createIncrementalValue(dependencies, processor) {
38
82
  let current;
39
83
  const build = (sources) => {
40
84
  state = Object.create(null);
85
+ const publicInputsForBuild = publicInputs(sources, true);
41
86
  const result = processor({
42
- sources: publicTuple(sources),
87
+ sources: publicInputsForBuild.values,
88
+ changes: publicInputsForBuild.changes,
43
89
  previous: void 0,
44
90
  reset: true,
45
- change: void 0,
46
91
  cause: sourceCause(sources),
47
92
  state
48
93
  });
@@ -53,11 +98,12 @@ function createIncrementalValue(dependencies, processor) {
53
98
  return {
54
99
  value: current,
55
100
  update: (nextSources) => {
101
+ const publicInputsForUpdate = publicInputs(nextSources);
56
102
  const next = processor({
57
- sources: publicTuple(nextSources),
103
+ sources: publicInputsForUpdate.values,
104
+ changes: publicInputsForUpdate.changes,
58
105
  previous: current,
59
106
  reset: false,
60
- change: sourceChange(nextSources),
61
107
  cause: sourceCause(nextSources),
62
108
  state
63
109
  });
@@ -82,26 +128,30 @@ function createIncrementalCollection(dependencies, processor) {
82
128
  let state = Object.create(null);
83
129
  const build = (input) => {
84
130
  state = Object.create(null);
131
+ const publicInputsForBuild = publicInputs(input.sources, true);
85
132
  if (processor({
86
- sources: publicTuple(input.sources),
133
+ sources: publicInputsForBuild.values,
134
+ changes: publicInputsForBuild.changes,
87
135
  previous: input.previous,
88
136
  next: input.next,
89
137
  reset: true,
90
- change: void 0,
91
138
  cause: sourceCause(input.sources),
92
139
  state,
93
140
  output: input.writer
94
141
  })?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
95
- return { update: (nextInput) => processor({
96
- sources: publicTuple(nextInput.sources),
97
- previous: nextInput.previous,
98
- next: nextInput.next,
99
- reset: false,
100
- change: sourceChange(nextInput.sources),
101
- cause: sourceCause(nextInput.sources),
102
- state,
103
- output: nextInput.writer
104
- }) };
142
+ return { update: (nextInput) => {
143
+ const publicInputsForUpdate = publicInputs(nextInput.sources);
144
+ return processor({
145
+ sources: publicInputsForUpdate.values,
146
+ changes: publicInputsForUpdate.changes,
147
+ previous: nextInput.previous,
148
+ next: nextInput.next,
149
+ reset: false,
150
+ cause: sourceCause(nextInput.sources),
151
+ state,
152
+ output: nextInput.writer
153
+ });
154
+ } };
105
155
  };
106
156
  return defineIncrementalCollection({
107
157
  dependencies: dependencyMap,
@@ -1 +1 @@
1
- {"version":3,"file":"advanced.js","names":[],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type { Projection, ProjectionValues, PublicCollection } from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type { CollectionDraft, CollectionRead, GraphSources } from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<S, T> = {\n readonly sources: S;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly change: unknown;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<S, T> = (\n context: IncrementalValueContext<S, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<S, K extends string, V> = {\n readonly sources: S;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly change: unknown;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<S, K extends string, V> = (\n context: IncrementalCollectionContext<S, K, V>\n) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown>[]>(dependencies: D): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\nconst sourceChange = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'change' in source &&\n (source as { readonly change?: unknown }).change !== undefined\n )\n return (source as { readonly change?: unknown }).change;\n }\n return undefined;\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicTuple = (sources: Record<string, unknown>): readonly unknown[] =>\n Object.keys(sources)\n .sort((left, right) => Number(left.slice(1)) - Number(right.slice(1)))\n .map(key => publicSource(sources[key]));\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<ProjectionValues<D>, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const result = processor({\n sources: publicTuple(sources) as ProjectionValues<D>,\n previous: undefined,\n reset: true,\n change: undefined,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const next = processor({\n sources: publicTuple(nextSources) as ProjectionValues<D>,\n previous: current,\n reset: false,\n change: sourceChange(nextSources),\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown>[],\n K extends string,\n V,\n>(\n dependencies: D,\n processor: IncrementalCollectionProcessor<ProjectionValues<D>, K, V>\n): Projection<PublicCollection<K, V>> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const result = processor({\n sources: publicTuple(input.sources) as ProjectionValues<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n change: undefined,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) =>\n processor({\n sources: publicTuple(nextInput.sources) as ProjectionValues<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n change: sourceChange(nextInput.sources),\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\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>[]> = DependencyMap<D>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"advanced.js","names":[],"sources":["../core/src/projection/advanced.ts"],"sourcesContent":["import type {\n Projection,\n CollectionProjection,\n ProjectionChanges,\n ProjectionValues,\n PublicCollection,\n} from './definition';\nimport { defineIncrementalCollection, defineIncrementalValue } from './definition';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionEntryTransition,\n CollectionRead,\n GraphSources,\n} from './contract';\nimport { snapshot } from '../access/scope';\n\nexport type IncrementalState = Record<string, unknown>;\n\nexport type IncrementalValueContext<D extends readonly Projection<unknown, unknown>[], T> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: T | undefined;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n};\n\nexport type IncrementalValueProcessor<D extends readonly Projection<unknown, unknown>[], T> = (\n context: IncrementalValueContext<D, T>\n) =>\n | T\n | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n | { readonly kind: 'rebuild' };\n\nexport type IncrementalCollectionContext<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = {\n readonly sources: ProjectionValues<D>;\n readonly changes: ProjectionChanges<D>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly reset: boolean;\n readonly cause: unknown;\n readonly state: IncrementalState;\n readonly output: CollectionDraft<K, V>;\n};\n\nexport type IncrementalCollectionProcessor<\n D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n> = (context: IncrementalCollectionContext<D, K, V>) => void | { readonly kind: 'rebuild' };\n\ntype DependencyMap<D extends readonly Projection<unknown, unknown>[]> = {\n readonly [K in keyof D as `d${Extract<K, number>}`]: D[K];\n};\n\nconst dependenciesOf = <D extends readonly Projection<unknown, unknown>[]>(\n dependencies: D\n): GraphSources =>\n Object.fromEntries(\n dependencies.map((dependency, index) => [`d${index}`, dependency])\n ) as unknown as GraphSources;\n\ntype RuntimeCollectionSource = {\n readonly ids: () => readonly string[];\n readonly previous: CollectionRead<string, unknown>;\n readonly reset: boolean;\n readonly change?: { readonly kind: 'reset' | 'incremental'; readonly orderChanged?: boolean };\n readonly transitions: () => readonly CollectionEntryTransition<string, unknown>[];\n};\nconst resetCollectionChange = Object.freeze({ kind: 'reset' as const });\ntype IncrementalCollectionChange = Extract<\n CollectionChange<string, unknown>,\n { readonly kind: 'incremental' }\n>;\n\nconst isCollectionSource = (source: unknown): source is RuntimeCollectionSource =>\n Boolean(\n source &&\n typeof source === 'object' &&\n 'ids' in source &&\n typeof (source as { readonly ids?: unknown }).ids === 'function' &&\n 'previous' in source &&\n 'transitions' in source &&\n typeof (source as { readonly transitions?: unknown }).transitions === 'function'\n );\n\nconst collectionChange = (source: unknown): CollectionChange<string, unknown> | undefined => {\n if (!isCollectionSource(source)) return undefined;\n if (source.reset || source.change?.kind === 'reset') return resetCollectionChange;\n const impact = source.change;\n if (!impact) return undefined;\n const added: IncrementalCollectionChange['added'][number][] = [];\n const updated: IncrementalCollectionChange['updated'][number][] = [];\n const removed: IncrementalCollectionChange['removed'][number][] = [];\n for (const transition of source.transitions()) {\n if (transition.kind === 'added')\n added.push({ key: transition.key, kind: transition.kind, after: transition.after });\n else if (transition.kind === 'updated') updated.push(transition);\n else removed.push({ key: transition.key, kind: transition.kind, before: transition.before });\n }\n const order = impact.orderChanged\n ? {\n before: Object.freeze([...source.previous.ids()]),\n after: Object.freeze([...source.ids()]),\n }\n : undefined;\n if (!added.length && !updated.length && !removed.length && !order) return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze(added),\n updated: Object.freeze(updated),\n removed: Object.freeze(removed),\n ...(order ? { order: Object.freeze(order) } : {}),\n });\n};\n\nconst sourceCause = (sources: Record<string, unknown>): unknown => {\n for (const source of Object.values(sources)) {\n if (\n source &&\n typeof source === 'object' &&\n 'cause' in source &&\n (source as { readonly cause?: unknown }).cause !== undefined\n )\n return (source as { readonly cause?: unknown }).cause;\n }\n return undefined;\n};\n\nconst publicSource = (source: unknown): unknown => {\n if (!source || typeof source !== 'object') return source;\n if ('value' in source) return (source as { readonly value: unknown }).value;\n if ('read' in source) {\n const read = (source as { readonly read: unknown }).read;\n if (\n read &&\n typeof read === 'object' &&\n 'ids' in read &&\n typeof (read as { ids?: unknown }).ids === 'function'\n ) {\n const result = new Map<string, unknown>();\n for (const id of (read as CollectionRead<string, unknown>).ids())\n result.set(id, (read as CollectionRead<string, unknown>).get(id));\n return result;\n }\n return snapshot(read);\n }\n if ('ids' in source && typeof (source as { ids?: unknown }).ids === 'function') {\n const result = new Map<string, unknown>();\n const read = source as CollectionRead<string, unknown>;\n for (const id of read.ids()) result.set(id, read.get(id));\n return result;\n }\n return source;\n};\n\nconst publicInputs = (\n sources: Record<string, unknown>,\n initial = false\n): { readonly values: readonly unknown[]; readonly changes: readonly unknown[] } => {\n const values: unknown[] = [];\n const changes: unknown[] = [];\n for (const key of Object.keys(sources).sort(\n (left, right) => Number(left.slice(1)) - Number(right.slice(1))\n )) {\n const source = sources[key];\n values.push(publicSource(source));\n changes.push(\n initial && isCollectionSource(source) ? resetCollectionChange : collectionChange(source)\n );\n }\n return { values, changes };\n};\n\nconst normalizeValue = <T>(\n result: T | { readonly kind: 'value'; readonly value: T; readonly state?: IncrementalState }\n): { value: T; state?: IncrementalState } =>\n result && typeof result === 'object' && (result as { readonly kind?: unknown }).kind === 'value'\n ? {\n value: (result as { readonly value: T }).value,\n state: (result as { readonly state?: IncrementalState }).state,\n }\n : { value: result as T };\n\nfunction createIncrementalValue<const D extends readonly Projection<unknown, unknown>[], T>(\n dependencies: D,\n processor: IncrementalValueProcessor<D, T>\n): Projection<T> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n let current!: T;\n const build = (sources: Record<string, unknown>) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: undefined,\n reset: true,\n cause: sourceCause(sources),\n state,\n });\n if (result && typeof result === 'object' && 'kind' in result)\n throw new TypeError('Initial incremental processor cannot rebuild.');\n const normalized = normalizeValue(result as T);\n current = normalized.value;\n if (normalized.state) state = normalized.state;\n return {\n value: current,\n update: (nextSources: Record<string, unknown>) => {\n const publicInputsForUpdate = publicInputs(nextSources);\n const next = processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: current,\n reset: false,\n cause: sourceCause(nextSources),\n state,\n });\n if (next && typeof next === 'object' && 'kind' in next) return next;\n const nextValue = normalizeValue(next as T);\n current = nextValue.value;\n if (nextValue.state) state = nextValue.state;\n return { kind: 'changed', value: current } as const;\n },\n };\n };\n return defineIncrementalValue({ dependencies: dependencyMap, build: build as never });\n}\n\nfunction createIncrementalCollection<\n const D extends readonly Projection<unknown, unknown>[],\n K extends string,\n V,\n>(dependencies: D, processor: IncrementalCollectionProcessor<D, K, V>): CollectionProjection<K, V> {\n const dependencyMap = dependenciesOf(dependencies);\n let state: IncrementalState = Object.create(null) as IncrementalState;\n const build = (input: {\n readonly sources: Record<string, unknown>;\n readonly previous: CollectionRead<K, V>;\n readonly next: CollectionRead<K, V>;\n readonly writer: CollectionDraft<K, V>;\n }) => {\n state = Object.create(null) as IncrementalState;\n const publicInputsForBuild = publicInputs(input.sources, true);\n const result = processor({\n sources: publicInputsForBuild.values as ProjectionValues<D>,\n changes: publicInputsForBuild.changes as ProjectionChanges<D>,\n previous: input.previous,\n next: input.next,\n reset: true,\n cause: sourceCause(input.sources),\n state,\n output: input.writer,\n });\n if (result?.kind === 'rebuild')\n throw new TypeError('Initial incremental collection processor cannot rebuild.');\n return {\n update: (nextInput: typeof input) => {\n const publicInputsForUpdate = publicInputs(nextInput.sources);\n return processor({\n sources: publicInputsForUpdate.values as ProjectionValues<D>,\n changes: publicInputsForUpdate.changes as ProjectionChanges<D>,\n previous: nextInput.previous,\n next: nextInput.next,\n reset: false,\n cause: sourceCause(nextInput.sources),\n state,\n output: nextInput.writer,\n });\n },\n };\n };\n return defineIncrementalCollection({ dependencies: dependencyMap, build: build as never });\n}\n\nexport const incremental = Object.assign(createIncrementalValue, {\n collection: createIncrementalCollection,\n});\n\nexport type IncrementalDependencies<D extends readonly Projection<unknown, unknown>[]> =\n DependencyMap<D>;\n\nexport type { CollectionChange } from './contract';\n"],"mappings":"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"}
@@ -456,4 +456,4 @@ type DocumentRuntime<S extends ObjectNode> = DocumentReadable<S> & {
456
456
  };
457
457
  //#endregion
458
458
  export { OptionalNode as $, overlaps as A, DocumentAddress as B, Draft as C, AddressRef as D, snapshot as E, MemberChange as F, DocumentTreeValue as G, DocumentListConfig as H, ValueTransition as I, Infer as J, FieldNode as K, CollectionId as L, resolveAddress as M, Change as N, contains as O, ChangeSet as P, ObjectShape as Q, CollectionNode as R, DocumentImpact as S, replace as T, DocumentNode as U, DocumentAnchor as V, DocumentTreeNode as W, MapNode as X, ListNode as Y, ObjectNode as Z, Unsubscribe as _, Validator as _t, DocumentDisposedError as a, VariantNode as at, MutationIssueCode as b, DocumentReentrancyError as c, list as ct, LocalHistory as d, optional as dt, PathValueOf as et, ObserverError as f, table as ft, TransactionResult as g, ParseIssue as gt, TransactionRejected as h, ParseError as ht, DocumentDiagnostic as i, TreeNode as it, read as j, debugKey as k, DocumentRuntime as l, map as lt, Synchronous as m, variant as mt, CommitSource as n, SchemaPath as nt, DocumentProblem as o, VariantShape as ot, OperationResult as p, tree as pt, ImpactTarget as q, DocumentCommit as r, TableNode as rt, DocumentReadable as s, field as st, CommitListener as t, ReadonlyValue as tt, HistoryState as u, object as ut, Readable as v, parse as vt, Read as w, CollectionImpact as x, MutationIssue as y, CollectionPath as z };
459
- //# sourceMappingURL=contract-BT53Gg94.d.ts.map
459
+ //# sourceMappingURL=contract-CATCCVu5.d.ts.map