doxum 0.1.15 → 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.
package/README.md CHANGED
@@ -254,6 +254,12 @@ const doubled = incremental.collection([tasks], ({ sources, output }) => {
254
254
  });
255
255
  ```
256
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
+
257
263
  In React, `useProjection(projection)` reads a value and
258
264
  `useProjection(projection, selector, equality?)` tracks keyed reads such as
259
265
  `tasks => tasks.get(taskId)`. Unrelated key changes do not execute that selector;
package/dist/advanced.cjs CHANGED
@@ -3,8 +3,39 @@ const require_scope = require("./scope-Ezs-Y3TY.cjs");
3
3
  const require_definition = require("./definition-Z6TagMup.cjs");
4
4
  //#region core/src/projection/advanced.ts
5
5
  const dependenciesOf = (dependencies) => Object.fromEntries(dependencies.map((dependency, index) => [`d${index}`, dependency]));
6
- const sourceChange = (sources) => {
7
- 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
+ });
8
39
  };
9
40
  const sourceCause = (sources) => {
10
41
  for (const source of Object.values(sources)) if (source && typeof source === "object" && "cause" in source && source.cause !== void 0) return source.cause;
@@ -29,7 +60,19 @@ const publicSource = (source) => {
29
60
  }
30
61
  return source;
31
62
  };
32
- 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
+ };
33
76
  const normalizeValue = (result) => result && typeof result === "object" && result.kind === "value" ? {
34
77
  value: result.value,
35
78
  state: result.state
@@ -40,11 +83,12 @@ function createIncrementalValue(dependencies, processor) {
40
83
  let current;
41
84
  const build = (sources) => {
42
85
  state = Object.create(null);
86
+ const publicInputsForBuild = publicInputs(sources, true);
43
87
  const result = processor({
44
- sources: publicTuple(sources),
88
+ sources: publicInputsForBuild.values,
89
+ changes: publicInputsForBuild.changes,
45
90
  previous: void 0,
46
91
  reset: true,
47
- change: void 0,
48
92
  cause: sourceCause(sources),
49
93
  state
50
94
  });
@@ -55,11 +99,12 @@ function createIncrementalValue(dependencies, processor) {
55
99
  return {
56
100
  value: current,
57
101
  update: (nextSources) => {
102
+ const publicInputsForUpdate = publicInputs(nextSources);
58
103
  const next = processor({
59
- sources: publicTuple(nextSources),
104
+ sources: publicInputsForUpdate.values,
105
+ changes: publicInputsForUpdate.changes,
60
106
  previous: current,
61
107
  reset: false,
62
- change: sourceChange(nextSources),
63
108
  cause: sourceCause(nextSources),
64
109
  state
65
110
  });
@@ -84,26 +129,30 @@ function createIncrementalCollection(dependencies, processor) {
84
129
  let state = Object.create(null);
85
130
  const build = (input) => {
86
131
  state = Object.create(null);
132
+ const publicInputsForBuild = publicInputs(input.sources, true);
87
133
  if (processor({
88
- sources: publicTuple(input.sources),
134
+ sources: publicInputsForBuild.values,
135
+ changes: publicInputsForBuild.changes,
89
136
  previous: input.previous,
90
137
  next: input.next,
91
138
  reset: true,
92
- change: void 0,
93
139
  cause: sourceCause(input.sources),
94
140
  state,
95
141
  output: input.writer
96
142
  })?.kind === "rebuild") throw new TypeError("Initial incremental collection processor cannot rebuild.");
97
- return { update: (nextInput) => processor({
98
- sources: publicTuple(nextInput.sources),
99
- previous: nextInput.previous,
100
- next: nextInput.next,
101
- reset: false,
102
- change: sourceChange(nextInput.sources),
103
- cause: sourceCause(nextInput.sources),
104
- state,
105
- output: nextInput.writer
106
- }) };
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
+ } };
107
156
  };
108
157
  return require_definition.defineIncrementalCollection({
109
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":";;;;AA4DA,MAAM,kBACJ,iBAEA,OAAO,YACL,aAAa,KAAK,YAAY,UAAU,CAAC,IAAI,SAAS,WAAW,CAAC,CACnE;AASH,MAAM,wBAAwB,OAAO,OAAO,EAAE,MAAM,SAAkB,CAAC;AAMvE,MAAM,sBAAsB,WAC1B,QACE,UACA,OAAO,WAAW,YAClB,SAAS,UACT,OAAQ,OAAsC,QAAQ,cACtD,cAAc,UACd,iBAAiB,UACjB,OAAQ,OAA8C,gBAAgB,WACvE;AAEH,MAAM,oBAAoB,WAAmE;AAC3F,KAAI,CAAC,mBAAmB,OAAO,CAAE,QAAO,KAAA;AACxC,KAAI,OAAO,SAAS,OAAO,QAAQ,SAAS,QAAS,QAAO;CAC5D,MAAM,SAAS,OAAO;AACtB,KAAI,CAAC,OAAQ,QAAO,KAAA;CACpB,MAAM,QAAwD,EAAE;CAChE,MAAM,UAA4D,EAAE;CACpE,MAAM,UAA4D,EAAE;AACpE,MAAK,MAAM,cAAc,OAAO,aAAa,CAC3C,KAAI,WAAW,SAAS,QACtB,OAAM,KAAK;EAAE,KAAK,WAAW;EAAK,MAAM,WAAW;EAAM,OAAO,WAAW;EAAO,CAAC;UAC5E,WAAW,SAAS,UAAW,SAAQ,KAAK,WAAW;KAC3D,SAAQ,KAAK;EAAE,KAAK,WAAW;EAAK,MAAM,WAAW;EAAM,QAAQ,WAAW;EAAQ,CAAC;CAE9F,MAAM,QAAQ,OAAO,eACjB;EACE,QAAQ,OAAO,OAAO,CAAC,GAAG,OAAO,SAAS,KAAK,CAAC,CAAC;EACjD,OAAO,OAAO,OAAO,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC;EACxC,GACD,KAAA;AACJ,KAAI,CAAC,MAAM,UAAU,CAAC,QAAQ,UAAU,CAAC,QAAQ,UAAU,CAAC,MAAO,QAAO,KAAA;AAC1E,QAAO,OAAO,OAAO;EACnB,MAAM;EACN,OAAO,OAAO,OAAO,MAAM;EAC3B,SAAS,OAAO,OAAO,QAAQ;EAC/B,SAAS,OAAO,OAAO,QAAQ;EAC/B,GAAI,QAAQ,EAAE,OAAO,OAAO,OAAO,MAAM,EAAE,GAAG,EAAE;EACjD,CAAC;;AAGJ,MAAM,eAAe,YAA8C;AACjE,MAAK,MAAM,UAAU,OAAO,OAAO,QAAQ,CACzC,KACE,UACA,OAAO,WAAW,YAClB,WAAW,UACV,OAAwC,UAAU,KAAA,EAEnD,QAAQ,OAAwC;;AAKtD,MAAM,gBAAgB,WAA6B;AACjD,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,KAAI,WAAW,OAAQ,QAAQ,OAAuC;AACtE,KAAI,UAAU,QAAQ;EACpB,MAAM,OAAQ,OAAsC;AACpD,MACE,QACA,OAAO,SAAS,YAChB,SAAS,QACT,OAAQ,KAA2B,QAAQ,YAC3C;GACA,MAAM,yBAAS,IAAI,KAAsB;AACzC,QAAK,MAAM,MAAO,KAAyC,KAAK,CAC9D,QAAO,IAAI,IAAK,KAAyC,IAAI,GAAG,CAAC;AACnE,UAAO;;AAET,SAAOA,cAAAA,SAAS,KAAK;;AAEvB,KAAI,SAAS,UAAU,OAAQ,OAA6B,QAAQ,YAAY;EAC9E,MAAM,yBAAS,IAAI,KAAsB;EACzC,MAAM,OAAO;AACb,OAAK,MAAM,MAAM,KAAK,KAAK,CAAE,QAAO,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC;AACzD,SAAO;;AAET,QAAO;;AAGT,MAAM,gBACJ,SACA,UAAU,UACwE;CAClF,MAAM,SAAoB,EAAE;CAC5B,MAAM,UAAqB,EAAE;AAC7B,MAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,CAAC,MACpC,MAAM,UAAU,OAAO,KAAK,MAAM,EAAE,CAAC,GAAG,OAAO,MAAM,MAAM,EAAE,CAAC,CAChE,EAAE;EACD,MAAM,SAAS,QAAQ;AACvB,SAAO,KAAK,aAAa,OAAO,CAAC;AACjC,UAAQ,KACN,WAAW,mBAAmB,OAAO,GAAG,wBAAwB,iBAAiB,OAAO,CACzF;;AAEH,QAAO;EAAE;EAAQ;EAAS;;AAG5B,MAAM,kBACJ,WAEA,UAAU,OAAO,WAAW,YAAa,OAAuC,SAAS,UACrF;CACE,OAAQ,OAAiC;CACzC,OAAQ,OAAiD;CAC1D,GACD,EAAE,OAAO,QAAa;AAE5B,SAAS,uBACP,cACA,WACe;CACf,MAAM,gBAAgB,eAAe,aAAa;CAClD,IAAI,QAA0B,OAAO,OAAO,KAAK;CACjD,IAAI;CACJ,MAAM,SAAS,YAAqC;AAClD,UAAQ,OAAO,OAAO,KAAK;EAC3B,MAAM,uBAAuB,aAAa,SAAS,KAAK;EACxD,MAAM,SAAS,UAAU;GACvB,SAAS,qBAAqB;GAC9B,SAAS,qBAAqB;GAC9B,UAAU,KAAA;GACV,OAAO;GACP,OAAO,YAAY,QAAQ;GAC3B;GACD,CAAC;AACF,MAAI,UAAU,OAAO,WAAW,YAAY,UAAU,OACpD,OAAM,IAAI,UAAU,gDAAgD;EACtE,MAAM,aAAa,eAAe,OAAY;AAC9C,YAAU,WAAW;AACrB,MAAI,WAAW,MAAO,SAAQ,WAAW;AACzC,SAAO;GACL,OAAO;GACP,SAAS,gBAAyC;IAChD,MAAM,wBAAwB,aAAa,YAAY;IACvD,MAAM,OAAO,UAAU;KACrB,SAAS,sBAAsB;KAC/B,SAAS,sBAAsB;KAC/B,UAAU;KACV,OAAO;KACP,OAAO,YAAY,YAAY;KAC/B;KACD,CAAC;AACF,QAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,KAAM,QAAO;IAC/D,MAAM,YAAY,eAAe,KAAU;AAC3C,cAAU,UAAU;AACpB,QAAI,UAAU,MAAO,SAAQ,UAAU;AACvC,WAAO;KAAE,MAAM;KAAW,OAAO;KAAS;;GAE7C;;AAEH,QAAOC,mBAAAA,uBAAuB;EAAE,cAAc;EAAsB;EAAgB,CAAC;;AAGvF,SAAS,4BAIP,cAAiB,WAAgF;CACjG,MAAM,gBAAgB,eAAe,aAAa;CAClD,IAAI,QAA0B,OAAO,OAAO,KAAK;CACjD,MAAM,SAAS,UAKT;AACJ,UAAQ,OAAO,OAAO,KAAK;EAC3B,MAAM,uBAAuB,aAAa,MAAM,SAAS,KAAK;AAW9D,MAVe,UAAU;GACvB,SAAS,qBAAqB;GAC9B,SAAS,qBAAqB;GAC9B,UAAU,MAAM;GAChB,MAAM,MAAM;GACZ,OAAO;GACP,OAAO,YAAY,MAAM,QAAQ;GACjC;GACA,QAAQ,MAAM;GACf,CACS,EAAE,SAAS,UACnB,OAAM,IAAI,UAAU,2DAA2D;AACjF,SAAO,EACL,SAAS,cAA4B;GACnC,MAAM,wBAAwB,aAAa,UAAU,QAAQ;AAC7D,UAAO,UAAU;IACf,SAAS,sBAAsB;IAC/B,SAAS,sBAAsB;IAC/B,UAAU,UAAU;IACpB,MAAM,UAAU;IAChB,OAAO;IACP,OAAO,YAAY,UAAU,QAAQ;IACrC;IACA,QAAQ,UAAU;IACnB,CAAC;KAEL;;AAEH,QAAOC,mBAAAA,4BAA4B;EAAE,cAAc;EAAsB;EAAgB,CAAC;;AAG5F,MAAa,cAAc,OAAO,OAAO,wBAAwB,EAC/D,YAAY,6BACb,CAAC"}
@@ -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-B6J0SSNa.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
@@ -2,8 +2,39 @@ import { i as snapshot } from "./scope-d-L87NeC.js";
2
2
  import { n as defineIncrementalValue, t as defineIncrementalCollection } from "./definition-c6XQXzvK.js";
3
3
  //#region core/src/projection/advanced.ts
4
4
  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;
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
+ });
7
38
  };
8
39
  const sourceCause = (sources) => {
9
40
  for (const source of Object.values(sources)) if (source && typeof source === "object" && "cause" in source && source.cause !== void 0) return source.cause;
@@ -28,7 +59,19 @@ const publicSource = (source) => {
28
59
  }
29
60
  return source;
30
61
  };
31
- 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
+ };
32
75
  const normalizeValue = (result) => result && typeof result === "object" && result.kind === "value" ? {
33
76
  value: result.value,
34
77
  state: result.state
@@ -39,11 +82,12 @@ function createIncrementalValue(dependencies, processor) {
39
82
  let current;
40
83
  const build = (sources) => {
41
84
  state = Object.create(null);
85
+ const publicInputsForBuild = publicInputs(sources, true);
42
86
  const result = processor({
43
- sources: publicTuple(sources),
87
+ sources: publicInputsForBuild.values,
88
+ changes: publicInputsForBuild.changes,
44
89
  previous: void 0,
45
90
  reset: true,
46
- change: void 0,
47
91
  cause: sourceCause(sources),
48
92
  state
49
93
  });
@@ -54,11 +98,12 @@ function createIncrementalValue(dependencies, processor) {
54
98
  return {
55
99
  value: current,
56
100
  update: (nextSources) => {
101
+ const publicInputsForUpdate = publicInputs(nextSources);
57
102
  const next = processor({
58
- sources: publicTuple(nextSources),
103
+ sources: publicInputsForUpdate.values,
104
+ changes: publicInputsForUpdate.changes,
59
105
  previous: current,
60
106
  reset: false,
61
- change: sourceChange(nextSources),
62
107
  cause: sourceCause(nextSources),
63
108
  state
64
109
  });
@@ -83,26 +128,30 @@ function createIncrementalCollection(dependencies, processor) {
83
128
  let state = Object.create(null);
84
129
  const build = (input) => {
85
130
  state = Object.create(null);
131
+ const publicInputsForBuild = publicInputs(input.sources, true);
86
132
  if (processor({
87
- sources: publicTuple(input.sources),
133
+ sources: publicInputsForBuild.values,
134
+ changes: publicInputsForBuild.changes,
88
135
  previous: input.previous,
89
136
  next: input.next,
90
137
  reset: true,
91
- change: void 0,
92
138
  cause: sourceCause(input.sources),
93
139
  state,
94
140
  output: input.writer
95
141
  })?.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
- }) };
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
+ } };
106
155
  };
107
156
  return defineIncrementalCollection({
108
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":";;;AA0CA,MAAM,kBAA4D,iBAChE,OAAO,YACL,aAAa,KAAK,YAAY,UAAU,CAAC,IAAI,SAAS,WAAW,CAAC,CACnE;AAEH,MAAM,gBAAgB,YAA8C;AAClE,MAAK,MAAM,UAAU,OAAO,OAAO,QAAQ,CACzC,KACE,UACA,OAAO,WAAW,YAClB,YAAY,UACX,OAAyC,WAAW,KAAA,EAErD,QAAQ,OAAyC;;AAKvD,MAAM,eAAe,YAA8C;AACjE,MAAK,MAAM,UAAU,OAAO,OAAO,QAAQ,CACzC,KACE,UACA,OAAO,WAAW,YAClB,WAAW,UACV,OAAwC,UAAU,KAAA,EAEnD,QAAQ,OAAwC;;AAKtD,MAAM,gBAAgB,WAA6B;AACjD,KAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,KAAI,WAAW,OAAQ,QAAQ,OAAuC;AACtE,KAAI,UAAU,QAAQ;EACpB,MAAM,OAAQ,OAAsC;AACpD,MACE,QACA,OAAO,SAAS,YAChB,SAAS,QACT,OAAQ,KAA2B,QAAQ,YAC3C;GACA,MAAM,yBAAS,IAAI,KAAsB;AACzC,QAAK,MAAM,MAAO,KAAyC,KAAK,CAC9D,QAAO,IAAI,IAAK,KAAyC,IAAI,GAAG,CAAC;AACnE,UAAO;;AAET,SAAO,SAAS,KAAK;;AAEvB,KAAI,SAAS,UAAU,OAAQ,OAA6B,QAAQ,YAAY;EAC9E,MAAM,yBAAS,IAAI,KAAsB;EACzC,MAAM,OAAO;AACb,OAAK,MAAM,MAAM,KAAK,KAAK,CAAE,QAAO,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC;AACzD,SAAO;;AAET,QAAO;;AAGT,MAAM,eAAe,YACnB,OAAO,KAAK,QAAQ,CACjB,MAAM,MAAM,UAAU,OAAO,KAAK,MAAM,EAAE,CAAC,GAAG,OAAO,MAAM,MAAM,EAAE,CAAC,CAAC,CACrE,KAAI,QAAO,aAAa,QAAQ,KAAK,CAAC;AAE3C,MAAM,kBACJ,WAEA,UAAU,OAAO,WAAW,YAAa,OAAuC,SAAS,UACrF;CACE,OAAQ,OAAiC;CACzC,OAAQ,OAAiD;CAC1D,GACD,EAAE,OAAO,QAAa;AAE5B,SAAS,uBACP,cACA,WACe;CACf,MAAM,gBAAgB,eAAe,aAAa;CAClD,IAAI,QAA0B,OAAO,OAAO,KAAK;CACjD,IAAI;CACJ,MAAM,SAAS,YAAqC;AAClD,UAAQ,OAAO,OAAO,KAAK;EAC3B,MAAM,SAAS,UAAU;GACvB,SAAS,YAAY,QAAQ;GAC7B,UAAU,KAAA;GACV,OAAO;GACP,QAAQ,KAAA;GACR,OAAO,YAAY,QAAQ;GAC3B;GACD,CAAC;AACF,MAAI,UAAU,OAAO,WAAW,YAAY,UAAU,OACpD,OAAM,IAAI,UAAU,gDAAgD;EACtE,MAAM,aAAa,eAAe,OAAY;AAC9C,YAAU,WAAW;AACrB,MAAI,WAAW,MAAO,SAAQ,WAAW;AACzC,SAAO;GACL,OAAO;GACP,SAAS,gBAAyC;IAChD,MAAM,OAAO,UAAU;KACrB,SAAS,YAAY,YAAY;KACjC,UAAU;KACV,OAAO;KACP,QAAQ,aAAa,YAAY;KACjC,OAAO,YAAY,YAAY;KAC/B;KACD,CAAC;AACF,QAAI,QAAQ,OAAO,SAAS,YAAY,UAAU,KAAM,QAAO;IAC/D,MAAM,YAAY,eAAe,KAAU;AAC3C,cAAU,UAAU;AACpB,QAAI,UAAU,MAAO,SAAQ,UAAU;AACvC,WAAO;KAAE,MAAM;KAAW,OAAO;KAAS;;GAE7C;;AAEH,QAAO,uBAAuB;EAAE,cAAc;EAAsB;EAAgB,CAAC;;AAGvF,SAAS,4BAKP,cACA,WACoC;CACpC,MAAM,gBAAgB,eAAe,aAAa;CAClD,IAAI,QAA0B,OAAO,OAAO,KAAK;CACjD,MAAM,SAAS,UAKT;AACJ,UAAQ,OAAO,OAAO,KAAK;AAW3B,MAVe,UAAU;GACvB,SAAS,YAAY,MAAM,QAAQ;GACnC,UAAU,MAAM;GAChB,MAAM,MAAM;GACZ,OAAO;GACP,QAAQ,KAAA;GACR,OAAO,YAAY,MAAM,QAAQ;GACjC;GACA,QAAQ,MAAM;GACf,CACS,EAAE,SAAS,UACnB,OAAM,IAAI,UAAU,2DAA2D;AACjF,SAAO,EACL,SAAS,cACP,UAAU;GACR,SAAS,YAAY,UAAU,QAAQ;GACvC,UAAU,UAAU;GACpB,MAAM,UAAU;GAChB,OAAO;GACP,QAAQ,aAAa,UAAU,QAAQ;GACvC,OAAO,YAAY,UAAU,QAAQ;GACrC;GACA,QAAQ,UAAU;GACnB,CAAC,EACL;;AAEH,QAAO,4BAA4B;EAAE,cAAc;EAAsB;EAAgB,CAAC;;AAG5F,MAAa,cAAc,OAAO,OAAO,wBAAwB,EAC/D,YAAY,6BACb,CAAC"}
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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"}
@@ -6,6 +6,40 @@ type Cause = unknown;
6
6
  type BatchOptions = {
7
7
  readonly cause?: Cause;
8
8
  };
9
+ type CollectionEntryTransition<K extends string, V> = {
10
+ readonly key: K;
11
+ readonly kind: 'added';
12
+ readonly before: undefined;
13
+ readonly after: V;
14
+ } | {
15
+ readonly key: K;
16
+ readonly kind: 'updated';
17
+ readonly before: V;
18
+ readonly after: V;
19
+ } | {
20
+ readonly key: K;
21
+ readonly kind: 'removed';
22
+ readonly before: V;
23
+ readonly after: undefined;
24
+ };
25
+ type CollectionChange<K extends string, V> = {
26
+ readonly kind: 'reset';
27
+ } | {
28
+ readonly kind: 'incremental';
29
+ readonly added: readonly Omit<Extract<CollectionEntryTransition<K, V>, {
30
+ readonly kind: 'added';
31
+ }>, 'before'>[];
32
+ readonly updated: readonly Extract<CollectionEntryTransition<K, V>, {
33
+ readonly kind: 'updated';
34
+ }>[];
35
+ readonly removed: readonly Omit<Extract<CollectionEntryTransition<K, V>, {
36
+ readonly kind: 'removed';
37
+ }>, 'after'>[];
38
+ readonly order?: {
39
+ readonly before: readonly K[];
40
+ readonly after: readonly K[];
41
+ };
42
+ };
9
43
  type CollectionRead<K extends string, V> = {
10
44
  get(key: K): V | undefined;
11
45
  has(key: K): boolean;
@@ -69,18 +103,21 @@ declare class ProjectionDisposedError extends Error {
69
103
  //#endregion
70
104
  //#region core/src/projection/definition.d.ts
71
105
  declare const projectionDefinition: unique symbol;
106
+ declare const projectionChanges: unique symbol;
72
107
  declare const writableInput: unique symbol;
73
108
  /** A lazy, reusable projection definition. Its value is materialized per runtime. */
74
- type Projection<T> = {
109
+ type Projection<T, C = undefined> = {
75
110
  readonly [projectionDefinition]: T;
111
+ readonly [projectionChanges]: C;
76
112
  };
77
113
  /** A runtime-local writable projection definition. */
78
114
  type Input<T> = Projection<T> & {
79
115
  readonly [writableInput]: true;
80
116
  };
81
- type ProjectionValues<D extends readonly Projection<unknown>[]> = { readonly [K in keyof D]: D[K] extends Projection<infer T> ? T : never };
117
+ type ProjectionValues<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D]: D[K] extends Projection<infer T, unknown> ? T : never };
118
+ type ProjectionChanges<D extends readonly Projection<unknown, unknown>[]> = { readonly [K in keyof D]: D[K] extends Projection<unknown, infer C> ? [C] extends [undefined] ? undefined : C | undefined : undefined };
82
119
  type PublicCollection<K extends string, V> = ReadonlyMap<K, V>;
83
- type ObservedCollection<P extends CollectionPath> = PublicCollection<CollectionId<P>, ReadonlyValue<Infer<CollectionNode<P>>>>;
120
+ type CollectionProjection<K extends string, V> = Projection<PublicCollection<K, V>, CollectionChange<K, V>>;
84
121
  declare const input: <T>(initial: T, equality?: (previous: T, next: T) => boolean) => Input<T>;
85
122
  /**
86
123
  * Establishes a reactive boundary from a document, readable, or external
@@ -89,11 +126,11 @@ declare const input: <T>(initial: T, equality?: (previous: T, next: T) => boolea
89
126
  */
90
127
  declare function observe<S extends ObjectNode>(document: DocumentReadable<S>): Projection<Infer<S>>;
91
128
  declare function observe<T, D>(source: ExternalValueSource<T, D>): Projection<T>;
92
- declare function observe<K extends string, V, D>(source: ExternalCollectionSource<K, V, D>): Projection<PublicCollection<K, V>>;
129
+ declare function observe<K extends string, V, D>(source: ExternalCollectionSource<K, V, D>): CollectionProjection<K, V>;
93
130
  declare function observe<T>(readable: Readable<T>): Projection<T>;
94
- declare function observe<S extends ObjectNode, P extends CollectionPath>(document: DocumentReadable<S>, selector: (path: SchemaPath<S['shape']>) => P): Projection<ObservedCollection<P>>;
131
+ declare function observe<S extends ObjectNode, P extends CollectionPath>(document: DocumentReadable<S>, selector: (path: SchemaPath<S['shape']>) => P): CollectionProjection<CollectionId<P>, ReadonlyValue<Infer<CollectionNode<P>>>>;
95
132
  declare function observe<S extends ObjectNode, P>(document: DocumentReadable<S>, selector: (path: SchemaPath<S['shape']>) => P): Projection<PathValueOf<P>>;
96
- declare function derive<const D extends readonly Projection<unknown>[], T>(dependencies: D, compute: (...values: ProjectionValues<D>) => Synchronous<T>, equality?: (previous: T, next: T) => boolean): Projection<T>;
133
+ declare function derive<const D extends readonly Projection<unknown, unknown>[], T>(dependencies: D, compute: (...values: ProjectionValues<D>) => Synchronous<T>, equality?: (previous: T, next: T) => boolean): Projection<T>;
97
134
  //#endregion
98
- export { ProjectionError as _, derive as a, BatchOptions as c, ExternalCollectionEvent as d, ExternalCollectionRead as f, ProjectionDisposedError as g, ExternalValueSource as h, PublicCollection as i, CollectionDraft as l, ExternalValueEvent as m, Projection as n, input as o, ExternalCollectionSource as p, ProjectionValues as r, observe as s, Input as t, CollectionRead as u };
99
- //# sourceMappingURL=definition-DN6yW2vi.d.cts.map
135
+ export { ExternalValueEvent as _, ProjectionValues as a, ProjectionError as b, input as c, CollectionChange as d, CollectionDraft as f, ExternalCollectionSource as g, ExternalCollectionRead as h, ProjectionChanges as i, observe as l, ExternalCollectionEvent as m, Input as n, PublicCollection as o, CollectionRead as p, Projection as r, derive as s, CollectionProjection as t, BatchOptions as u, ExternalValueSource as v, ProjectionDisposedError as y };
136
+ //# sourceMappingURL=definition-C__VJqA4.d.cts.map