doxum 0.1.26 → 0.1.27

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.
@@ -1,3 +1,4 @@
1
+ const require_record = require("./record-ChYUi8PP.cjs");
1
2
  const profile = {
2
3
  projection: (key, amount = 1) => {},
3
4
  recorder: (key, amount = 1) => {},
@@ -58,6 +59,14 @@ const projectionRef = (projection) => {
58
59
  return ref;
59
60
  };
60
61
  const producerOf = (projection) => projectionRef(projection).producer;
62
+ /** Resolves the immutable output description owned by a projection definition. */
63
+ const outputDefinitionOf = (projection) => {
64
+ const ref = projectionRef(projection);
65
+ const producer = ref.producer;
66
+ const output = producer.kind === "source" ? producer.output : producer.outputs[ref.output];
67
+ if (!output) throw new TypeError("Projection output does not exist.");
68
+ return output;
69
+ };
61
70
  const isProjection = (value) => value !== null && typeof value === "object" && projections.has(value);
62
71
  const ownProjections = (projections, owner) => {
63
72
  const producers = new Set(projections.map(producerOf));
@@ -137,6 +146,90 @@ const snapshotCollectionView = (read) => {
137
146
  return collectionView(mapRead(values));
138
147
  };
139
148
  //#endregion
149
+ //#region core/src/projection/dependency.ts
150
+ /** Creates the durable dependency value exposed to pure derive callbacks. */
151
+ const snapshotDependencyValue = (source) => source.kind === "value" ? source.value : snapshotCollectionView(source.read);
152
+ /** Compiles the shared named Projection dependency declaration contract. */
153
+ const compileProjectionDependencies = (dependencies, label) => {
154
+ if (!require_record.isPlainObject(dependencies) || isProjection(dependencies)) throw new TypeError(`${label} dependencies must be a plain object.`);
155
+ const names = [];
156
+ const projections = [];
157
+ for (const key of Reflect.ownKeys(dependencies)) {
158
+ if (typeof key !== "string") throw new TypeError(`${label} dependency names must be strings.`);
159
+ const descriptor = Object.getOwnPropertyDescriptor(dependencies, key);
160
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError(`${label} dependencies must be enumerable data properties.`);
161
+ const projection = descriptor.value;
162
+ projectionRef(projection);
163
+ names.push(key);
164
+ projections.push(projection);
165
+ }
166
+ return Object.freeze({
167
+ names: Object.freeze(names),
168
+ projections: Object.freeze(projections)
169
+ });
170
+ };
171
+ //#endregion
172
+ //#region core/src/projection/collection/change.ts
173
+ const commonOrderChanged = (before, after, added, removed) => {
174
+ const beforeCommon = before.filter((key) => !removed.has(key));
175
+ const afterCommon = after.filter((key) => !added.has(key));
176
+ return beforeCommon.some((key, index) => afterCommon[index] !== key);
177
+ };
178
+ /** Builds the canonical incremental CollectionChange from already-known net transitions. */
179
+ const createCollectionChange = (input) => {
180
+ const addedKeys = new Set(input.added.map((entry) => entry.key));
181
+ const removedKeys = new Set(input.removed.map((entry) => entry.key));
182
+ const orderChanged = input.beforeOrder !== input.afterOrder && commonOrderChanged(input.beforeOrder, input.afterOrder, addedKeys, removedKeys);
183
+ if (!input.added.length && !input.updated.length && !input.removed.length && !orderChanged) return void 0;
184
+ return Object.freeze({
185
+ kind: "incremental",
186
+ added: Object.freeze([...input.added]),
187
+ updated: Object.freeze([...input.updated]),
188
+ removed: Object.freeze([...input.removed]),
189
+ ...orderChanged ? { order: Object.freeze({
190
+ before: Object.freeze([...input.beforeOrder]),
191
+ after: Object.freeze([...input.afterOrder])
192
+ }) } : {}
193
+ });
194
+ };
195
+ /** Exact fallback diff between two published map-like snapshots. */
196
+ const diffCollection = (previous, current, isEqual = Object.is) => {
197
+ const added = [];
198
+ const updated = [];
199
+ const removed = [];
200
+ for (const [key, before] of previous) if (!current.has(key)) removed.push({
201
+ key,
202
+ before
203
+ });
204
+ else {
205
+ const after = current.get(key);
206
+ if (!isEqual(before, after)) updated.push({
207
+ key,
208
+ before,
209
+ after
210
+ });
211
+ }
212
+ for (const [key, after] of current) if (!previous.has(key)) added.push({
213
+ key,
214
+ after
215
+ });
216
+ return createCollectionChange({
217
+ added,
218
+ updated,
219
+ removed,
220
+ beforeOrder: [...previous.keys()],
221
+ afterOrder: [...current.keys()]
222
+ });
223
+ };
224
+ const changedKeys = function* (change) {
225
+ if (change.kind !== "incremental") throw new TypeError("collectionChange.keys requires an incremental CollectionChange.");
226
+ for (const entry of change.added) yield entry.key;
227
+ for (const entry of change.updated) yield entry.key;
228
+ for (const entry of change.removed) yield entry.key;
229
+ };
230
+ const collectionChange = Object.freeze({ keys: changedKeys });
231
+ const collectionHasStructuralChange = (change) => change.kind === "reset" || Boolean(change.added.length || change.removed.length || change.order);
232
+ //#endregion
140
233
  //#region core/src/projection/contract.ts
141
234
  var ProjectionError = class extends Error {
142
235
  cause;
@@ -519,12 +612,36 @@ Object.defineProperty(exports, "assertSynchronous", {
519
612
  return assertSynchronous;
520
613
  }
521
614
  });
615
+ Object.defineProperty(exports, "collectionChange", {
616
+ enumerable: true,
617
+ get: function() {
618
+ return collectionChange;
619
+ }
620
+ });
621
+ Object.defineProperty(exports, "collectionHasStructuralChange", {
622
+ enumerable: true,
623
+ get: function() {
624
+ return collectionHasStructuralChange;
625
+ }
626
+ });
522
627
  Object.defineProperty(exports, "collectionView", {
523
628
  enumerable: true,
524
629
  get: function() {
525
630
  return collectionView;
526
631
  }
527
632
  });
633
+ Object.defineProperty(exports, "compileProjectionDependencies", {
634
+ enumerable: true,
635
+ get: function() {
636
+ return compileProjectionDependencies;
637
+ }
638
+ });
639
+ Object.defineProperty(exports, "createCollectionChange", {
640
+ enumerable: true,
641
+ get: function() {
642
+ return createCollectionChange;
643
+ }
644
+ });
528
645
  Object.defineProperty(exports, "createScheduler", {
529
646
  enumerable: true,
530
647
  get: function() {
@@ -543,6 +660,12 @@ Object.defineProperty(exports, "defineSource", {
543
660
  return defineSource;
544
661
  }
545
662
  });
663
+ Object.defineProperty(exports, "diffCollection", {
664
+ enumerable: true,
665
+ get: function() {
666
+ return diffCollection;
667
+ }
668
+ });
546
669
  Object.defineProperty(exports, "isProjection", {
547
670
  enumerable: true,
548
671
  get: function() {
@@ -555,6 +678,12 @@ Object.defineProperty(exports, "mapRead", {
555
678
  return mapRead;
556
679
  }
557
680
  });
681
+ Object.defineProperty(exports, "outputDefinitionOf", {
682
+ enumerable: true,
683
+ get: function() {
684
+ return outputDefinitionOf;
685
+ }
686
+ });
558
687
  Object.defineProperty(exports, "ownProjections", {
559
688
  enumerable: true,
560
689
  get: function() {
@@ -585,5 +714,11 @@ Object.defineProperty(exports, "snapshotCollectionView", {
585
714
  return snapshotCollectionView;
586
715
  }
587
716
  });
717
+ Object.defineProperty(exports, "snapshotDependencyValue", {
718
+ enumerable: true,
719
+ get: function() {
720
+ return snapshotDependencyValue;
721
+ }
722
+ });
588
723
 
589
- //# sourceMappingURL=scheduler-D4VthaaK.cjs.map
724
+ //# sourceMappingURL=scheduler-k1ZGR1PG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-k1ZGR1PG.cjs","names":["isPlainObject"],"sources":["../core/src/profile.ts","../core/src/projection/definition.ts","../core/src/projection/collection/view.ts","../core/src/projection/dependency.ts","../core/src/projection/collection/change.ts","../core/src/projection/contract.ts","../core/src/projection/graph/scheduler.ts"],"sourcesContent":["const counters = () => ({\n projection: {\n sourceEvents: 0,\n scheduledNodes: 0,\n processedNodes: 0,\n touchedKeys: 0,\n changedKeys: 0,\n publishedNodes: 0,\n flushes: 0,\n },\n copy: { structures: 0, treeNodes: 0, shallowRecordItems: 0 },\n equality: { calls: 0, containers: 0 },\n recorder: {\n facts: 0,\n groups: 0,\n transitions: 0,\n absorbed: 0,\n orderSnapshots: 0,\n orderCaptures: 0,\n orderItems: 0,\n publishedOrderItems: 0,\n treeNodes: 0,\n sealed: 0,\n indexedGroups: 0,\n },\n access: { scopes: 0, proxies: 0, snapshots: 0, addresses: 0, resolutions: 0 },\n address: {\n schemaSteps: 0,\n documentSteps: 0,\n prefixComparisons: 0,\n segmentsCompared: 0,\n listIndexes: 0,\n listItems: 0,\n },\n impact: { affectsChecks: 0, indexes: 0 },\n dependency: { comparisons: 0, segmentsCompared: 0 },\n collectionIndex: { nodes: 0, builds: 0, builtItems: 0 },\n collectionView: { mappedItems: 0, idsScanned: 0, arraysCopied: 0 },\n materialized: { updated: 0, rebuilt: 0, notifications: 0 },\n});\ntype Counters = ReturnType<typeof counters>;\ntype DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K] };\nexport type ProfileSnapshot = DeepReadonly<Counters>;\nlet active: Counters | undefined;\nconst freeze = <T extends object>(value: T): DeepReadonly<T> => {\n Object.values(value).forEach(child => {\n if (child && typeof child === 'object') freeze(child);\n });\n return Object.freeze(value) as DeepReadonly<T>;\n};\nexport const profile = {\n projection: (key: keyof Counters['projection'], amount = 1) => {\n if (active) active.projection[key] += amount;\n },\n recorder: (key: keyof Counters['recorder'], amount = 1) => {\n if (active) active.recorder[key] += amount;\n },\n access: (key: keyof Counters['access']) => {\n if (active) active.access[key]++;\n },\n copy: {\n structure: () => {\n if (active) active.copy.structures++;\n },\n treeNode: () => {\n if (active) active.copy.treeNodes++;\n },\n shallowRecord: (items: number) => {\n if (active) active.copy.shallowRecordItems += items;\n },\n },\n equality: {\n call: () => {\n if (active) active.equality.calls++;\n },\n container: () => {\n if (active) active.equality.containers++;\n },\n },\n address: {\n listIndex: (items: number) => {\n if (active) {\n active.address.listIndexes++;\n active.address.listItems += items;\n }\n },\n schemaStep: () => {\n if (active) active.address.schemaSteps++;\n },\n documentStep: () => {\n if (active) active.address.documentSteps++;\n },\n prefixComparison: () => {\n if (active) active.address.prefixComparisons++;\n },\n segmentCompared: () => {\n if (active) active.address.segmentsCompared++;\n },\n },\n impact: {\n index: () => {\n if (active) active.impact.indexes++;\n },\n affects: () => {\n if (active) active.impact.affectsChecks++;\n },\n },\n dependency: {\n comparison: () => {\n if (active) active.dependency.comparisons++;\n },\n segmentCompared: () => {\n if (active) active.dependency.segmentsCompared++;\n },\n },\n collectionIndex: {\n node: () => {\n if (active) active.collectionIndex.nodes++;\n },\n build: (items: number) => {\n if (active) {\n active.collectionIndex.builds++;\n active.collectionIndex.builtItems += items;\n }\n },\n },\n collectionView: {\n mapped: () => {\n if (active) active.collectionView.mappedItems++;\n },\n idsScanned: (amount = 1) => {\n if (active) active.collectionView.idsScanned += amount;\n },\n arrayCopied: () => {\n if (active) active.collectionView.arraysCopied++;\n },\n },\n materialized: {\n updated: () => {\n if (active) active.materialized.updated++;\n },\n rebuilt: () => {\n if (active) active.materialized.rebuilt++;\n },\n notification: () => {\n if (active) active.materialized.notifications++;\n },\n },\n};\nexport type ProfileSession = { snapshot(): ProfileSnapshot; stop(): ProfileSnapshot };\nexport const startProfile = (): ProfileSession => {\n if (active) throw new Error('A document profile session is already active.');\n const value = counters();\n active = value;\n const snapshot = () => freeze(structuredClone(value));\n return {\n snapshot,\n stop: () => {\n if (active === value) active = undefined;\n return snapshot();\n },\n };\n};\nexport const measureProfile = <T>(run: () => T): { value: T; profile: ProfileSnapshot } => {\n const session = startProfile();\n try {\n return { value: run(), profile: session.stop() };\n } finally {\n session.stop();\n }\n};\n","import type { ReadonlyDocument } from '../runtime/contract';\nimport type { ObjectSchema } from '../schema/model';\nimport type { CollectionSelector, ValueSelector } from '../schema/path';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionRead,\n ExternalCollectionSource,\n ExternalValueSource,\n SourceContext,\n} from './contract';\nimport type { Readable } from '../readable';\n\ndeclare const projectionDefinition: unique symbol;\ndeclare const keyedProjection: unique symbol;\ndeclare const writableInput: unique symbol;\ndeclare const writableCollectionInput: unique symbol;\n\n/** A lazy output reference with no materialized Runtime state. */\nexport type Projection<T> = {\n readonly [projectionDefinition]: T;\n};\n\n/** A projection whose output is a keyed collection with per-key change semantics. */\nexport type KeyedProjection<K extends string, V> = Projection<ReadonlyMap<K, V>> & {\n readonly [keyedProjection]: { readonly key: K; readonly value: V };\n};\n\n/** A writable source projection. */\nexport type Input<T> = Projection<T> & { readonly [writableInput]: true };\n\n/** A writable keyed collection source projection. */\nexport type CollectionInput<K extends string, V> = KeyedProjection<K, V> & {\n readonly [writableCollectionInput]: { readonly key: K; readonly value: V };\n};\n\nexport type CollectionInputDraft<K extends string, V> = {\n get(key: K): V | undefined;\n has(key: K): boolean;\n set(key: K, value: V): void;\n remove(key: K): void;\n};\n\nexport type ProjectionChange<P> =\n P extends KeyedProjection<infer K, infer V> ? CollectionChange<K, V> : undefined;\n\nexport type Equality = (a: unknown, b: unknown) => boolean;\n\nexport type OutputDefinition =\n | {\n readonly kind: 'value';\n readonly equality: Equality;\n readonly path?: readonly string[];\n }\n | {\n readonly kind: 'collection';\n readonly equality: Equality;\n readonly path?: readonly string[];\n };\n\nexport type ValueOutputEvaluation = {\n readonly kind: 'value';\n readonly previous: unknown;\n readonly next: () => unknown;\n readonly output: { set(value: unknown): void };\n};\n\nexport type CollectionOutputEvaluation = {\n readonly kind: 'collection';\n readonly previous: CollectionRead<string, unknown>;\n readonly next: CollectionRead<string, unknown>;\n readonly output: CollectionDraft<string, unknown>;\n};\n\nexport type OutputEvaluation = ValueOutputEvaluation | CollectionOutputEvaluation;\n\nexport type ProcessorEvaluation = {\n readonly reset: boolean;\n readonly cause: unknown;\n readonly sources: readonly SourceContext[];\n readonly outputs: readonly OutputEvaluation[];\n};\n\nexport type ProcessorInstance = {\n evaluate(input: ProcessorEvaluation): void;\n release?(): void;\n};\n\nexport type SourceAdapter =\n | {\n readonly kind: 'value-input';\n readonly initial: unknown;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'collection-input';\n readonly initial: ReadonlyMap<string, unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'readable';\n readonly readable: Readable<unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'external-value';\n readonly source: ExternalValueSource<unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'external-collection';\n readonly source: ExternalCollectionSource<string, unknown>;\n }\n | {\n readonly kind: 'document';\n readonly document: ReadonlyDocument<ObjectSchema<object>>;\n readonly selector: ValueSelector | CollectionSelector;\n };\n\nexport type SourceDefinition = {\n readonly kind: 'source';\n readonly source: SourceAdapter;\n readonly output: OutputDefinition;\n owner?: object;\n materialized?: true;\n};\n\nexport type ProcessorDefinition = {\n readonly kind: 'processor';\n readonly dependencies: readonly Projection<unknown>[];\n readonly outputs: readonly OutputDefinition[];\n readonly create: () => ProcessorInstance;\n readonly name?: string;\n owner?: object;\n materialized?: true;\n};\n\nexport type ProducerDefinition = SourceDefinition | ProcessorDefinition;\n\nexport type ProjectionRef = {\n readonly producer: ProducerDefinition;\n readonly output: number;\n};\n\nconst projections = new WeakMap<object, ProjectionRef>();\n\nconst defineRef = <T>(producer: ProducerDefinition, output: number): Projection<T> => {\n const handle = Object.freeze({}) as Projection<T>;\n projections.set(handle, Object.freeze({ producer, output }));\n return handle;\n};\n\nexport const projectionRef = (projection: Projection<unknown>): ProjectionRef => {\n const ref = projections.get(projection);\n if (!ref) throw new TypeError('Unknown projection definition.');\n return ref;\n};\n\nexport const producerOf = (projection: Projection<unknown>): ProducerDefinition =>\n projectionRef(projection).producer;\n\n/** Resolves the immutable output description owned by a projection definition. */\nexport const outputDefinitionOf = (projection: Projection<unknown>): OutputDefinition => {\n const ref = projectionRef(projection);\n const producer = ref.producer;\n const output = producer.kind === 'source' ? producer.output : producer.outputs[ref.output];\n if (!output) throw new TypeError('Projection output does not exist.');\n return output;\n};\n\nexport const isProjection = (value: unknown): value is Projection<unknown> =>\n value !== null && typeof value === 'object' && projections.has(value);\n\nexport const ownProjections = (\n projections: readonly Projection<unknown>[],\n owner: object\n): void => {\n const producers = new Set(projections.map(producerOf));\n for (const producer of producers) {\n if (producer.owner !== undefined && producer.owner !== owner)\n throw new TypeError('Projection producer already belongs to another scope.');\n if (producer.owner === undefined && producer.materialized)\n throw new TypeError('A materialized root projection cannot become scope-owned.');\n if (producer.kind !== 'processor') continue;\n for (const dependency of producer.dependencies) {\n const dependencyOwner = producerOf(dependency).owner;\n if (dependencyOwner !== undefined && dependencyOwner !== owner)\n throw new TypeError('A scope cannot depend on another scope.');\n }\n }\n for (const producer of producers) producer.owner = owner;\n};\n\nconst freezeOutput = (output: OutputDefinition): OutputDefinition =>\n Object.freeze({\n kind: output.kind,\n equality: output.equality,\n ...(output.path ? { path: Object.freeze([...output.path]) } : {}),\n });\n\nexport const defineProcessor = (definition: {\n readonly dependencies: readonly Projection<unknown>[];\n readonly outputs: readonly OutputDefinition[];\n readonly create: () => ProcessorInstance;\n readonly name?: string;\n}): readonly Projection<unknown>[] => {\n if (!Array.isArray(definition.dependencies))\n throw new TypeError('Projection dependencies must be an array.');\n definition.dependencies.forEach(projectionRef);\n if (!definition.outputs.length) throw new TypeError('Projection processor requires an output.');\n const producer: ProcessorDefinition = {\n kind: 'processor',\n dependencies: Object.freeze([...definition.dependencies]),\n outputs: Object.freeze(definition.outputs.map(freezeOutput)),\n create: definition.create,\n ...(definition.name ? { name: definition.name } : {}),\n };\n return Object.freeze(producer.outputs.map((_, output) => defineRef<unknown>(producer, output)));\n};\n\nexport const defineSource = <T>(source: SourceAdapter, output: OutputDefinition): Projection<T> => {\n const producer: SourceDefinition = {\n kind: 'source',\n source,\n output: freezeOutput(output),\n };\n return defineRef<T>(producer, 0);\n};\n","import type { CollectionRead } from '../contract';\n\nexport const mapRead = <K extends string, V>(value: ReadonlyMap<K, V>): CollectionRead<K, V> => ({\n get: key => value.get(key),\n has: key => value.has(key),\n ids: () => Object.freeze([...value.keys()]),\n});\n\n/** Immutable map-like view over a CollectionRead. */\nexport const collectionView = <K extends string, V>(\n read: CollectionRead<K, V>\n): ReadonlyMap<K, V> => {\n const ids = read.ids();\n const entries = function* (): IterableIterator<[K, V]> {\n for (const key of ids) yield [key, read.get(key) as V];\n };\n const values = function* (): IterableIterator<V> {\n for (const key of ids) yield read.get(key) as V;\n };\n const view: ReadonlyMap<K, V> = {\n get: key => read.get(key),\n has: key => read.has(key),\n get size() {\n return ids.length;\n },\n keys: () => ids[Symbol.iterator](),\n values,\n entries,\n forEach: (callback, thisArg) => {\n for (const key of ids) callback.call(thisArg, read.get(key) as V, key, view);\n },\n [Symbol.iterator]: entries,\n };\n return Object.freeze(view);\n};\n\n/** Eager durable view used when a processor result may retain its dependency value. */\nexport const snapshotCollectionView = <K extends string, V>(\n read: CollectionRead<K, V>\n): ReadonlyMap<K, V> => {\n const ids = read.ids();\n const values = new Map<K, V>();\n for (const key of ids) values.set(key, read.get(key) as V);\n return collectionView(mapRead(values));\n};\n","import { isPlainObject } from '../value/record';\nimport { snapshotCollectionView } from './collection/view';\nimport type { SourceContext } from './contract';\nimport { isProjection, projectionRef, type Projection } from './definition';\n\nexport type CompiledProjectionDependencies = {\n readonly names: readonly string[];\n readonly projections: readonly Projection<unknown>[];\n};\n\n/** Creates the durable dependency value exposed to pure derive callbacks. */\nexport const snapshotDependencyValue = (source: SourceContext): unknown =>\n source.kind === 'value' ? source.value : snapshotCollectionView(source.read);\n\n/** Compiles the shared named Projection dependency declaration contract. */\nexport const compileProjectionDependencies = (\n dependencies: unknown,\n label: string\n): CompiledProjectionDependencies => {\n if (!isPlainObject(dependencies) || isProjection(dependencies))\n throw new TypeError(`${label} dependencies must be a plain object.`);\n const names: string[] = [];\n const projections: Projection<unknown>[] = [];\n for (const key of Reflect.ownKeys(dependencies)) {\n if (typeof key !== 'string') throw new TypeError(`${label} dependency names must be strings.`);\n const descriptor = Object.getOwnPropertyDescriptor(dependencies, key);\n if (!descriptor?.enumerable || !('value' in descriptor))\n throw new TypeError(`${label} dependencies must be enumerable data properties.`);\n const projection = descriptor.value as Projection<unknown>;\n projectionRef(projection);\n names.push(key);\n projections.push(projection);\n }\n return Object.freeze({\n names: Object.freeze(names),\n projections: Object.freeze(projections),\n });\n};\n","import type { CollectionChange } from '../contract';\n\ntype Added<K extends string, V> = { readonly key: K; readonly after: V };\ntype Updated<K extends string, V> = {\n readonly key: K;\n readonly before: V;\n readonly after: V;\n};\ntype Removed<K extends string, V> = { readonly key: K; readonly before: V };\n\nconst commonOrderChanged = <K extends string>(\n before: readonly K[],\n after: readonly K[],\n added: ReadonlySet<K>,\n removed: ReadonlySet<K>\n): boolean => {\n const beforeCommon = before.filter(key => !removed.has(key));\n const afterCommon = after.filter(key => !added.has(key));\n return beforeCommon.some((key, index) => afterCommon[index] !== key);\n};\n\n/** Builds the canonical incremental CollectionChange from already-known net transitions. */\nexport const createCollectionChange = <K extends string, V>(input: {\n readonly added: readonly Added<K, V>[];\n readonly updated: readonly Updated<K, V>[];\n readonly removed: readonly Removed<K, V>[];\n readonly beforeOrder: readonly K[];\n readonly afterOrder: readonly K[];\n}): CollectionChange<K, V> | undefined => {\n const addedKeys = new Set(input.added.map(entry => entry.key));\n const removedKeys = new Set(input.removed.map(entry => entry.key));\n const orderChanged =\n input.beforeOrder !== input.afterOrder &&\n commonOrderChanged(input.beforeOrder, input.afterOrder, addedKeys, removedKeys);\n if (!input.added.length && !input.updated.length && !input.removed.length && !orderChanged)\n return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze([...input.added]),\n updated: Object.freeze([...input.updated]),\n removed: Object.freeze([...input.removed]),\n ...(orderChanged\n ? {\n order: Object.freeze({\n before: Object.freeze([...input.beforeOrder]),\n after: Object.freeze([...input.afterOrder]),\n }),\n }\n : {}),\n });\n};\n\n/** Exact fallback diff between two published map-like snapshots. */\nexport const diffCollection = <K extends string, V>(\n previous: ReadonlyMap<K, V>,\n current: ReadonlyMap<K, V>,\n isEqual: (previous: V, next: V) => boolean = Object.is\n): CollectionChange<K, V> | undefined => {\n const added: Added<K, V>[] = [];\n const updated: Updated<K, V>[] = [];\n const removed: Removed<K, V>[] = [];\n for (const [key, before] of previous) {\n if (!current.has(key)) removed.push({ key, before });\n else {\n const after = current.get(key) as V;\n if (!isEqual(before, after)) updated.push({ key, before, after });\n }\n }\n for (const [key, after] of current) if (!previous.has(key)) added.push({ key, after });\n return createCollectionChange({\n added,\n updated,\n removed,\n beforeOrder: [...previous.keys()],\n afterOrder: [...current.keys()],\n });\n};\n\nconst changedKeys = function* <K extends string, V>(\n change: Extract<CollectionChange<K, V>, { readonly kind: 'incremental' }>\n): IterableIterator<K> {\n if ((change as CollectionChange<K, V>).kind !== 'incremental')\n throw new TypeError('collectionChange.keys requires an incremental CollectionChange.');\n for (const entry of change.added) yield entry.key;\n for (const entry of change.updated) yield entry.key;\n for (const entry of change.removed) yield entry.key;\n};\n\nexport const collectionChange: {\n readonly keys: <K extends string, V>(\n change: Extract<CollectionChange<K, V>, { readonly kind: 'incremental' }>\n ) => Iterable<K>;\n} = Object.freeze({ keys: changedKeys });\n\nexport const collectionHasStructuralChange = <K extends string, V>(\n change: CollectionChange<K, V>\n): boolean =>\n change.kind === 'reset' || Boolean(change.added.length || change.removed.length || change.order);\n","import type { CollectionImpact } from '../impact';\nimport type { Unsubscribe } from '../runtime/contract';\n\n/** Scheduler-owned metadata for one Runtime batch. */\nexport type BatchContext = {\n readonly id: number;\n readonly cause?: unknown;\n};\n\n/** The one processor-facing collection transition protocol. */\nexport type CollectionChange<K extends string, V> =\n | { readonly kind: 'reset' }\n | {\n readonly kind: 'incremental';\n readonly added: readonly { readonly key: K; readonly after: V }[];\n readonly updated: readonly {\n readonly key: K;\n readonly before: V;\n readonly after: V;\n }[];\n readonly removed: readonly { readonly key: K; readonly before: V }[];\n readonly order?: {\n readonly before: readonly K[];\n readonly after: readonly K[];\n };\n };\n\nexport type ValueContext<T> = {\n readonly kind: 'value';\n readonly value: T;\n readonly revision: number;\n readonly reset: boolean;\n readonly cause?: unknown;\n};\n\nexport type CollectionRead<K extends string, V> = {\n get(key: K): V | undefined;\n has(key: K): boolean;\n ids(): readonly K[];\n};\n\nexport type ExternalCollectionRead<K extends string, V> = {\n readonly get: (key: K) => V | undefined;\n readonly has: (key: K) => boolean;\n readonly ids: () => readonly K[];\n};\n\nexport type CollectionContext<K extends string, V> = {\n readonly kind: 'collection';\n readonly read: CollectionRead<K, V>;\n readonly change: CollectionChange<K, V> | undefined;\n readonly revision: number;\n readonly reset: boolean;\n readonly cause?: unknown;\n};\n\nexport type SourceContext = ValueContext<unknown> | CollectionContext<string, unknown>;\n\nexport type ExternalValueSource<T> = {\n readonly kind: 'value';\n current(): T;\n revision(): number;\n subscribe(listener: (event: ExternalValueEvent<T>) => void): Unsubscribe;\n};\n\nexport type ExternalCollectionSource<K extends string, V> = {\n readonly kind: 'collection';\n current(): ExternalCollectionRead<K, V>;\n revision(): number;\n subscribe(listener: (event: ExternalCollectionEvent<K, V>) => void): Unsubscribe;\n};\n\nexport type ExternalValueEvent<T> = {\n readonly value: T;\n readonly revision: number;\n readonly reset?: boolean;\n readonly cause?: unknown;\n};\n\nexport type ExternalCollectionEvent<K extends string, V> = {\n /** Stable read from the source before this event or external batch. */\n readonly previous: ExternalCollectionRead<K, V>;\n readonly revision: number;\n /** Optional document-style hint; the adapter resolves the canonical change. */\n readonly impact?: CollectionImpact<K>;\n readonly cause?: unknown;\n};\n\nexport type CollectionDraft<K extends string, V> = {\n set(key: K, value: V): void;\n remove(key: K): void;\n order(ids: readonly K[]): void;\n};\n\nexport class ProjectionError extends Error {\n readonly cause: unknown;\n\n constructor(\n readonly phase: 'processor' | 'listener' | 'source' | 'blocked',\n cause: unknown\n ) {\n super(`Projection ${phase} failed.`, { cause });\n this.name = 'ProjectionError';\n this.cause = cause;\n }\n}\n\nexport class ProjectionDisposedError extends Error {\n constructor() {\n super('Projection has been disposed.');\n this.name = 'ProjectionDisposedError';\n }\n}\n","import { profile } from '../../profile';\nimport type { ObserverError, Unsubscribe } from '../../runtime/contract';\nimport type { BatchContext, SourceContext } from '../contract';\nimport { ProjectionDisposedError, ProjectionError } from '../contract';\n\ntype BatchOptions = { readonly cause?: unknown };\n\ntype ProducerBase = {\n readonly name: string;\n readonly outputs: readonly OutputRecord[];\n fault: ProjectionError | undefined;\n disposed: boolean;\n clear(): void;\n release(): void;\n};\n\nexport type OutputRecord = {\n readonly kind: 'value' | 'collection';\n readonly owner: ProducerRecord;\n context(active: () => boolean): SourceContext;\n current(): unknown;\n revision(): number;\n reset(): boolean;\n subscribe(listener: () => void): Unsubscribe;\n emit(call: (listener: () => void) => void): void;\n hasConsumers(): boolean;\n forEachConsumer(run: (consumer: ProcessorRecord) => void): void;\n attachConsumer(consumer: ProcessorRecord): void;\n detachConsumer(consumer: ProcessorRecord): void;\n clear(): void;\n release(): void;\n};\n\nexport type SourceBoundaryRecord = ProducerBase & {\n readonly kind: 'source';\n readonly outputs: readonly [OutputRecord];\n pendingCause(): unknown;\n recovering(): boolean;\n prepare(cause: unknown): { readonly changed: boolean; readonly force: boolean };\n publish(): void;\n};\n\nexport type ProcessorRecord = ProducerBase & {\n readonly kind: 'processor';\n readonly dependencies: readonly OutputRecord[];\n readonly order: number;\n evaluate(reset: boolean, cause: unknown, recreate?: boolean): readonly OutputRecord[];\n publish(): void;\n};\n\nexport type ProducerRecord = SourceBoundaryRecord | ProcessorRecord;\n\nexport const createScheduler = (onError: (error: ProjectionError) => void) => {\n let disposed = false;\n let depth = 0;\n let batchSequence = 0;\n let activeBatch: BatchContext | undefined;\n let phase: 'idle' | 'compute' | 'notify' = 'idle';\n let sequence = 0;\n const sources = new Set<SourceBoundaryRecord>();\n const processors = new Set<ProcessorRecord>();\n const pendingSources = new Set<SourceBoundaryRecord>();\n const heap: ProcessorRecord[] = [];\n const queued = new Set<ProcessorRecord>();\n const completed = new Set<ProcessorRecord>();\n const emissions = new Set<OutputRecord>();\n const errors: ProjectionError[] = [];\n let reportingFailures: unknown[] = [];\n const guards = new Set<(locked: boolean) => void>();\n\n const assertActive = () => {\n if (disposed) throw new ProjectionDisposedError();\n };\n const assertIdle = () => {\n assertActive();\n if (phase !== 'idle')\n throw new Error('Projection cannot be re-entered during processing or notification.');\n };\n const lock = (value: boolean) => guards.forEach(guard => guard(value));\n\n const enqueue = (processor: ProcessorRecord) => {\n if (processor.disposed || queued.has(processor)) return;\n queued.add(processor);\n profile.projection('scheduledNodes');\n let index = heap.length;\n heap.push(processor);\n while (index > 0) {\n const parent = (index - 1) >> 1;\n if (heap[parent].order < processor.order) break;\n heap[index] = heap[parent];\n index = parent;\n }\n heap[index] = processor;\n };\n\n const pop = (): ProcessorRecord => {\n const first = heap[0];\n const last = heap.pop()!;\n if (heap.length) {\n let index = 0;\n while (index * 2 + 1 < heap.length) {\n let child = index * 2 + 1;\n if (child + 1 < heap.length && heap[child + 1].order < heap[child].order) child++;\n if (last.order < heap[child].order) break;\n heap[index] = heap[child];\n index = child;\n }\n heap[index] = last;\n }\n return first;\n };\n\n const errorFor = (\n producer: ProducerRecord,\n cause: unknown,\n kind: ProjectionError['phase'] = producer.kind === 'source' ? 'source' : 'processor'\n ) => new ProjectionError(kind, cause);\n\n const capture = (source: SourceBoundaryRecord) => {\n if (disposed) return;\n if (phase !== 'idle') {\n source.fault = errorFor(\n source,\n new Error('Source changed while projection was running.'),\n 'source'\n );\n errors.push(source.fault);\n throw source.fault;\n }\n pendingSources.add(source);\n profile.projection('sourceEvents');\n if (source.fault) errors.push(source.fault);\n };\n\n const settleCause = (): unknown => {\n if (activeBatch?.cause !== undefined) return activeBatch.cause;\n for (const source of pendingSources) {\n const cause = source.pendingCause();\n if (cause !== undefined) return cause;\n }\n return undefined;\n };\n\n const settle = () => {\n if (disposed || depth || phase !== 'idle') return;\n phase = 'compute';\n lock(true);\n const cause = settleCause();\n try {\n for (const source of pendingSources) {\n if (source.disposed) continue;\n const wasFaulted = source.fault !== undefined;\n let changed = false;\n let force = false;\n if (!source.fault || source.recovering()) {\n try {\n const prepared = source.prepare(cause);\n changed = prepared.changed;\n force = prepared.force;\n source.fault = undefined;\n } catch (failure) {\n source.fault = errorFor(source, failure, 'source');\n errors.push(source.fault);\n }\n }\n const recovered = wasFaulted && !source.fault;\n if (changed) source.publish();\n if (source.fault || changed || force || recovered) {\n const output = source.outputs[0];\n emissions.add(output);\n output.forEachConsumer(enqueue);\n }\n }\n\n while (heap.length) {\n const processor = pop();\n if (processor.disposed) continue;\n const wasFaulted = processor.fault !== undefined;\n profile.projection('processedNodes');\n let changedOutputs: readonly OutputRecord[] = Object.freeze([]);\n const blocked = processor.dependencies.find(\n output => output.owner.fault || output.owner.disposed\n );\n if (blocked) {\n processor.fault = errorFor(\n processor,\n blocked.owner.fault ?? new ProjectionDisposedError(),\n 'blocked'\n );\n } else {\n const reset = wasFaulted || processor.dependencies.some(output => output.reset());\n try {\n changedOutputs = processor.evaluate(reset, cause, wasFaulted);\n const dependencyFailure = processor.dependencies.find(output => output.owner.fault)\n ?.owner.fault;\n if (dependencyFailure) throw dependencyFailure;\n processor.fault = undefined;\n } catch (failure) {\n const error = errorFor(processor, failure);\n processor.fault = error;\n if (!reset) {\n try {\n changedOutputs = processor.evaluate(true, cause, true);\n const dependencyFailure = processor.dependencies.find(output => output.owner.fault)\n ?.owner.fault;\n if (dependencyFailure) throw dependencyFailure;\n processor.fault = undefined;\n errors.push(error);\n } catch (rebuildFailure) {\n processor.fault = errorFor(processor, rebuildFailure);\n errors.push(processor.fault);\n }\n } else errors.push(error);\n }\n }\n completed.add(processor);\n const recovered = wasFaulted && !processor.fault;\n if (processor.fault) {\n processor.outputs.forEach(output => {\n emissions.add(output);\n output.forEachConsumer(enqueue);\n });\n } else {\n if (changedOutputs.length) {\n processor.publish();\n changedOutputs.forEach(output => emissions.add(output));\n }\n const propagated = recovered ? processor.outputs : changedOutputs;\n propagated.forEach(output => output.forEachConsumer(enqueue));\n }\n if (processor.fault || changedOutputs.length) {\n profile.projection('publishedNodes');\n }\n }\n } finally {\n lock(false);\n phase = 'idle';\n }\n };\n\n const flush = (): readonly ObserverError[] => {\n if (disposed || depth) return [];\n if (pendingSources.size || completed.size) profile.projection('flushes');\n phase = 'notify';\n lock(true);\n const reportFailures: unknown[] = [];\n try {\n emissions.forEach(output =>\n output.emit(listener => {\n try {\n listener();\n } catch (cause) {\n errors.push(errorFor(output.owner, cause, 'listener'));\n }\n })\n );\n for (const error of errors.slice()) {\n try {\n onError(error);\n } catch (cause) {\n reportFailures.push(cause);\n }\n }\n return Object.freeze([\n ...errors.map(error =>\n Object.freeze({\n phase: error.phase === 'listener' ? ('listener' as const) : ('processor' as const),\n error,\n })\n ),\n ...reportFailures.map(error => Object.freeze({ phase: 'listener' as const, error })),\n ]);\n } finally {\n pendingSources.forEach(source => source.clear());\n completed.forEach(processor => processor.clear());\n pendingSources.clear();\n queued.clear();\n completed.clear();\n emissions.clear();\n errors.length = 0;\n reportingFailures = reportFailures;\n lock(false);\n phase = 'idle';\n }\n };\n\n const run = () => {\n settle();\n const result = flush();\n const failures = reportingFailures;\n reportingFailures = [];\n if (failures.length) throw new AggregateError(failures, 'Projection error reporter failed.');\n return result;\n };\n\n const batch = <T>(callback: () => T, options?: BatchOptions): T => {\n assertIdle();\n const outer = depth === 0;\n if (outer)\n activeBatch = Object.freeze({\n id: ++batchSequence,\n ...(options?.cause === undefined ? {} : { cause: options.cause }),\n });\n depth++;\n let failed = false;\n try {\n const value = callback();\n assertSynchronous(value);\n return value;\n } catch (error) {\n failed = true;\n throw error;\n } finally {\n depth--;\n if (!depth) {\n try {\n if (failed) {\n try {\n run();\n } catch {\n /* The original application error retains priority. */\n }\n } else run();\n } finally {\n activeBatch = undefined;\n }\n }\n }\n };\n\n const releaseProducer = (producer: ProducerRecord) => {\n assertIdle();\n if (producer.outputs.some(output => output.hasConsumers()))\n throw new Error('Projection producer is still used by another processor.');\n producer.disposed = true;\n if (producer.kind === 'processor') {\n producer.dependencies.forEach(output => output.detachConsumer(producer));\n processors.delete(producer);\n queued.delete(producer);\n completed.delete(producer);\n } else {\n sources.delete(producer);\n pendingSources.delete(producer);\n }\n const failures: unknown[] = [];\n try {\n producer.release();\n } catch (error) {\n failures.push(error);\n }\n try {\n producer.clear();\n } catch (error) {\n failures.push(error);\n }\n producer.outputs.forEach(output => emissions.delete(output));\n if (failures.length) throw failures[0];\n };\n\n return {\n assertActive,\n assertIdle,\n capture,\n settle,\n flush,\n run,\n registerGuard(guard: (locked: boolean) => void): Unsubscribe {\n assertActive();\n guards.add(guard);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n guards.delete(guard);\n };\n },\n get active() {\n return !disposed;\n },\n addSource(source: SourceBoundaryRecord) {\n assertIdle();\n sources.add(source);\n },\n addProcessor(processor: ProcessorRecord) {\n assertIdle();\n processors.add(processor);\n processor.dependencies.forEach(output => output.attachConsumer(processor));\n },\n releaseProducer,\n order: () => sequence++,\n initialize<T>(callback: () => T): T {\n assertIdle();\n phase = 'compute';\n lock(true);\n try {\n return callback();\n } finally {\n lock(false);\n phase = 'idle';\n }\n },\n batch,\n batchContext: () => activeBatch,\n dispose() {\n if (disposed) return;\n assertIdle();\n disposed = true;\n const failures: unknown[] = [];\n processors.forEach(processor => {\n processor.disposed = true;\n try {\n processor.release();\n } catch (error) {\n failures.push(error);\n }\n });\n sources.forEach(source => {\n source.disposed = true;\n try {\n source.release();\n } catch (error) {\n failures.push(error);\n }\n });\n processors.clear();\n sources.clear();\n pendingSources.clear();\n heap.length = 0;\n queued.clear();\n completed.clear();\n emissions.clear();\n guards.clear();\n errors.length = 0;\n reportingFailures = [];\n if (failures.length) throw new AggregateError(failures, 'Projection cleanup failed.');\n },\n };\n};\n\nexport type Scheduler = ReturnType<typeof createScheduler>;\n\nexport const assertSynchronous = (value: unknown): void => {\n if (\n value != null &&\n (typeof value === 'object' || typeof value === 'function') &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n throw new TypeError('Projection callbacks must be synchronous.');\n};\n\nexport const assertScope = (active: () => boolean) => {\n if (!active()) throw new Error('Projection reader or writer is no longer active.');\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { n as isPlainObject } from "./record-B2yRhYsc.js";
1
2
  const profile = {
2
3
  projection: (key, amount = 1) => {},
3
4
  recorder: (key, amount = 1) => {},
@@ -58,6 +59,14 @@ const projectionRef = (projection) => {
58
59
  return ref;
59
60
  };
60
61
  const producerOf = (projection) => projectionRef(projection).producer;
62
+ /** Resolves the immutable output description owned by a projection definition. */
63
+ const outputDefinitionOf = (projection) => {
64
+ const ref = projectionRef(projection);
65
+ const producer = ref.producer;
66
+ const output = producer.kind === "source" ? producer.output : producer.outputs[ref.output];
67
+ if (!output) throw new TypeError("Projection output does not exist.");
68
+ return output;
69
+ };
61
70
  const isProjection = (value) => value !== null && typeof value === "object" && projections.has(value);
62
71
  const ownProjections = (projections, owner) => {
63
72
  const producers = new Set(projections.map(producerOf));
@@ -137,6 +146,90 @@ const snapshotCollectionView = (read) => {
137
146
  return collectionView(mapRead(values));
138
147
  };
139
148
  //#endregion
149
+ //#region core/src/projection/dependency.ts
150
+ /** Creates the durable dependency value exposed to pure derive callbacks. */
151
+ const snapshotDependencyValue = (source) => source.kind === "value" ? source.value : snapshotCollectionView(source.read);
152
+ /** Compiles the shared named Projection dependency declaration contract. */
153
+ const compileProjectionDependencies = (dependencies, label) => {
154
+ if (!isPlainObject(dependencies) || isProjection(dependencies)) throw new TypeError(`${label} dependencies must be a plain object.`);
155
+ const names = [];
156
+ const projections = [];
157
+ for (const key of Reflect.ownKeys(dependencies)) {
158
+ if (typeof key !== "string") throw new TypeError(`${label} dependency names must be strings.`);
159
+ const descriptor = Object.getOwnPropertyDescriptor(dependencies, key);
160
+ if (!descriptor?.enumerable || !("value" in descriptor)) throw new TypeError(`${label} dependencies must be enumerable data properties.`);
161
+ const projection = descriptor.value;
162
+ projectionRef(projection);
163
+ names.push(key);
164
+ projections.push(projection);
165
+ }
166
+ return Object.freeze({
167
+ names: Object.freeze(names),
168
+ projections: Object.freeze(projections)
169
+ });
170
+ };
171
+ //#endregion
172
+ //#region core/src/projection/collection/change.ts
173
+ const commonOrderChanged = (before, after, added, removed) => {
174
+ const beforeCommon = before.filter((key) => !removed.has(key));
175
+ const afterCommon = after.filter((key) => !added.has(key));
176
+ return beforeCommon.some((key, index) => afterCommon[index] !== key);
177
+ };
178
+ /** Builds the canonical incremental CollectionChange from already-known net transitions. */
179
+ const createCollectionChange = (input) => {
180
+ const addedKeys = new Set(input.added.map((entry) => entry.key));
181
+ const removedKeys = new Set(input.removed.map((entry) => entry.key));
182
+ const orderChanged = input.beforeOrder !== input.afterOrder && commonOrderChanged(input.beforeOrder, input.afterOrder, addedKeys, removedKeys);
183
+ if (!input.added.length && !input.updated.length && !input.removed.length && !orderChanged) return void 0;
184
+ return Object.freeze({
185
+ kind: "incremental",
186
+ added: Object.freeze([...input.added]),
187
+ updated: Object.freeze([...input.updated]),
188
+ removed: Object.freeze([...input.removed]),
189
+ ...orderChanged ? { order: Object.freeze({
190
+ before: Object.freeze([...input.beforeOrder]),
191
+ after: Object.freeze([...input.afterOrder])
192
+ }) } : {}
193
+ });
194
+ };
195
+ /** Exact fallback diff between two published map-like snapshots. */
196
+ const diffCollection = (previous, current, isEqual = Object.is) => {
197
+ const added = [];
198
+ const updated = [];
199
+ const removed = [];
200
+ for (const [key, before] of previous) if (!current.has(key)) removed.push({
201
+ key,
202
+ before
203
+ });
204
+ else {
205
+ const after = current.get(key);
206
+ if (!isEqual(before, after)) updated.push({
207
+ key,
208
+ before,
209
+ after
210
+ });
211
+ }
212
+ for (const [key, after] of current) if (!previous.has(key)) added.push({
213
+ key,
214
+ after
215
+ });
216
+ return createCollectionChange({
217
+ added,
218
+ updated,
219
+ removed,
220
+ beforeOrder: [...previous.keys()],
221
+ afterOrder: [...current.keys()]
222
+ });
223
+ };
224
+ const changedKeys = function* (change) {
225
+ if (change.kind !== "incremental") throw new TypeError("collectionChange.keys requires an incremental CollectionChange.");
226
+ for (const entry of change.added) yield entry.key;
227
+ for (const entry of change.updated) yield entry.key;
228
+ for (const entry of change.removed) yield entry.key;
229
+ };
230
+ const collectionChange = Object.freeze({ keys: changedKeys });
231
+ const collectionHasStructuralChange = (change) => change.kind === "reset" || Boolean(change.added.length || change.removed.length || change.order);
232
+ //#endregion
140
233
  //#region core/src/projection/contract.ts
141
234
  var ProjectionError = class extends Error {
142
235
  cause;
@@ -495,6 +588,6 @@ const assertScope = (active) => {
495
588
  if (!active()) throw new Error("Projection reader or writer is no longer active.");
496
589
  };
497
590
  //#endregion
498
- export { ProjectionError as a, snapshotCollectionView as c, isProjection as d, ownProjections as f, profile as h, ProjectionDisposedError as i, defineProcessor as l, projectionRef as m, assertSynchronous as n, collectionView as o, producerOf as p, createScheduler as r, mapRead as s, assertScope as t, defineSource as u };
591
+ export { profile as S, isProjection as _, ProjectionError as a, producerOf as b, createCollectionChange as c, snapshotDependencyValue as d, collectionView as f, defineSource as g, defineProcessor as h, ProjectionDisposedError as i, diffCollection as l, snapshotCollectionView as m, assertSynchronous as n, collectionChange as o, mapRead as p, createScheduler as r, collectionHasStructuralChange as s, assertScope as t, compileProjectionDependencies as u, outputDefinitionOf as v, projectionRef as x, ownProjections as y };
499
592
 
500
- //# sourceMappingURL=scheduler--137L3j-.js.map
593
+ //# sourceMappingURL=scheduler-vzf3OcjT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-vzf3OcjT.js","names":[],"sources":["../core/src/profile.ts","../core/src/projection/definition.ts","../core/src/projection/collection/view.ts","../core/src/projection/dependency.ts","../core/src/projection/collection/change.ts","../core/src/projection/contract.ts","../core/src/projection/graph/scheduler.ts"],"sourcesContent":["const counters = () => ({\n projection: {\n sourceEvents: 0,\n scheduledNodes: 0,\n processedNodes: 0,\n touchedKeys: 0,\n changedKeys: 0,\n publishedNodes: 0,\n flushes: 0,\n },\n copy: { structures: 0, treeNodes: 0, shallowRecordItems: 0 },\n equality: { calls: 0, containers: 0 },\n recorder: {\n facts: 0,\n groups: 0,\n transitions: 0,\n absorbed: 0,\n orderSnapshots: 0,\n orderCaptures: 0,\n orderItems: 0,\n publishedOrderItems: 0,\n treeNodes: 0,\n sealed: 0,\n indexedGroups: 0,\n },\n access: { scopes: 0, proxies: 0, snapshots: 0, addresses: 0, resolutions: 0 },\n address: {\n schemaSteps: 0,\n documentSteps: 0,\n prefixComparisons: 0,\n segmentsCompared: 0,\n listIndexes: 0,\n listItems: 0,\n },\n impact: { affectsChecks: 0, indexes: 0 },\n dependency: { comparisons: 0, segmentsCompared: 0 },\n collectionIndex: { nodes: 0, builds: 0, builtItems: 0 },\n collectionView: { mappedItems: 0, idsScanned: 0, arraysCopied: 0 },\n materialized: { updated: 0, rebuilt: 0, notifications: 0 },\n});\ntype Counters = ReturnType<typeof counters>;\ntype DeepReadonly<T> = { readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K] };\nexport type ProfileSnapshot = DeepReadonly<Counters>;\nlet active: Counters | undefined;\nconst freeze = <T extends object>(value: T): DeepReadonly<T> => {\n Object.values(value).forEach(child => {\n if (child && typeof child === 'object') freeze(child);\n });\n return Object.freeze(value) as DeepReadonly<T>;\n};\nexport const profile = {\n projection: (key: keyof Counters['projection'], amount = 1) => {\n if (active) active.projection[key] += amount;\n },\n recorder: (key: keyof Counters['recorder'], amount = 1) => {\n if (active) active.recorder[key] += amount;\n },\n access: (key: keyof Counters['access']) => {\n if (active) active.access[key]++;\n },\n copy: {\n structure: () => {\n if (active) active.copy.structures++;\n },\n treeNode: () => {\n if (active) active.copy.treeNodes++;\n },\n shallowRecord: (items: number) => {\n if (active) active.copy.shallowRecordItems += items;\n },\n },\n equality: {\n call: () => {\n if (active) active.equality.calls++;\n },\n container: () => {\n if (active) active.equality.containers++;\n },\n },\n address: {\n listIndex: (items: number) => {\n if (active) {\n active.address.listIndexes++;\n active.address.listItems += items;\n }\n },\n schemaStep: () => {\n if (active) active.address.schemaSteps++;\n },\n documentStep: () => {\n if (active) active.address.documentSteps++;\n },\n prefixComparison: () => {\n if (active) active.address.prefixComparisons++;\n },\n segmentCompared: () => {\n if (active) active.address.segmentsCompared++;\n },\n },\n impact: {\n index: () => {\n if (active) active.impact.indexes++;\n },\n affects: () => {\n if (active) active.impact.affectsChecks++;\n },\n },\n dependency: {\n comparison: () => {\n if (active) active.dependency.comparisons++;\n },\n segmentCompared: () => {\n if (active) active.dependency.segmentsCompared++;\n },\n },\n collectionIndex: {\n node: () => {\n if (active) active.collectionIndex.nodes++;\n },\n build: (items: number) => {\n if (active) {\n active.collectionIndex.builds++;\n active.collectionIndex.builtItems += items;\n }\n },\n },\n collectionView: {\n mapped: () => {\n if (active) active.collectionView.mappedItems++;\n },\n idsScanned: (amount = 1) => {\n if (active) active.collectionView.idsScanned += amount;\n },\n arrayCopied: () => {\n if (active) active.collectionView.arraysCopied++;\n },\n },\n materialized: {\n updated: () => {\n if (active) active.materialized.updated++;\n },\n rebuilt: () => {\n if (active) active.materialized.rebuilt++;\n },\n notification: () => {\n if (active) active.materialized.notifications++;\n },\n },\n};\nexport type ProfileSession = { snapshot(): ProfileSnapshot; stop(): ProfileSnapshot };\nexport const startProfile = (): ProfileSession => {\n if (active) throw new Error('A document profile session is already active.');\n const value = counters();\n active = value;\n const snapshot = () => freeze(structuredClone(value));\n return {\n snapshot,\n stop: () => {\n if (active === value) active = undefined;\n return snapshot();\n },\n };\n};\nexport const measureProfile = <T>(run: () => T): { value: T; profile: ProfileSnapshot } => {\n const session = startProfile();\n try {\n return { value: run(), profile: session.stop() };\n } finally {\n session.stop();\n }\n};\n","import type { ReadonlyDocument } from '../runtime/contract';\nimport type { ObjectSchema } from '../schema/model';\nimport type { CollectionSelector, ValueSelector } from '../schema/path';\nimport type {\n CollectionChange,\n CollectionDraft,\n CollectionRead,\n ExternalCollectionSource,\n ExternalValueSource,\n SourceContext,\n} from './contract';\nimport type { Readable } from '../readable';\n\ndeclare const projectionDefinition: unique symbol;\ndeclare const keyedProjection: unique symbol;\ndeclare const writableInput: unique symbol;\ndeclare const writableCollectionInput: unique symbol;\n\n/** A lazy output reference with no materialized Runtime state. */\nexport type Projection<T> = {\n readonly [projectionDefinition]: T;\n};\n\n/** A projection whose output is a keyed collection with per-key change semantics. */\nexport type KeyedProjection<K extends string, V> = Projection<ReadonlyMap<K, V>> & {\n readonly [keyedProjection]: { readonly key: K; readonly value: V };\n};\n\n/** A writable source projection. */\nexport type Input<T> = Projection<T> & { readonly [writableInput]: true };\n\n/** A writable keyed collection source projection. */\nexport type CollectionInput<K extends string, V> = KeyedProjection<K, V> & {\n readonly [writableCollectionInput]: { readonly key: K; readonly value: V };\n};\n\nexport type CollectionInputDraft<K extends string, V> = {\n get(key: K): V | undefined;\n has(key: K): boolean;\n set(key: K, value: V): void;\n remove(key: K): void;\n};\n\nexport type ProjectionChange<P> =\n P extends KeyedProjection<infer K, infer V> ? CollectionChange<K, V> : undefined;\n\nexport type Equality = (a: unknown, b: unknown) => boolean;\n\nexport type OutputDefinition =\n | {\n readonly kind: 'value';\n readonly equality: Equality;\n readonly path?: readonly string[];\n }\n | {\n readonly kind: 'collection';\n readonly equality: Equality;\n readonly path?: readonly string[];\n };\n\nexport type ValueOutputEvaluation = {\n readonly kind: 'value';\n readonly previous: unknown;\n readonly next: () => unknown;\n readonly output: { set(value: unknown): void };\n};\n\nexport type CollectionOutputEvaluation = {\n readonly kind: 'collection';\n readonly previous: CollectionRead<string, unknown>;\n readonly next: CollectionRead<string, unknown>;\n readonly output: CollectionDraft<string, unknown>;\n};\n\nexport type OutputEvaluation = ValueOutputEvaluation | CollectionOutputEvaluation;\n\nexport type ProcessorEvaluation = {\n readonly reset: boolean;\n readonly cause: unknown;\n readonly sources: readonly SourceContext[];\n readonly outputs: readonly OutputEvaluation[];\n};\n\nexport type ProcessorInstance = {\n evaluate(input: ProcessorEvaluation): void;\n release?(): void;\n};\n\nexport type SourceAdapter =\n | {\n readonly kind: 'value-input';\n readonly initial: unknown;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'collection-input';\n readonly initial: ReadonlyMap<string, unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'readable';\n readonly readable: Readable<unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'external-value';\n readonly source: ExternalValueSource<unknown>;\n readonly equality: Equality;\n }\n | {\n readonly kind: 'external-collection';\n readonly source: ExternalCollectionSource<string, unknown>;\n }\n | {\n readonly kind: 'document';\n readonly document: ReadonlyDocument<ObjectSchema<object>>;\n readonly selector: ValueSelector | CollectionSelector;\n };\n\nexport type SourceDefinition = {\n readonly kind: 'source';\n readonly source: SourceAdapter;\n readonly output: OutputDefinition;\n owner?: object;\n materialized?: true;\n};\n\nexport type ProcessorDefinition = {\n readonly kind: 'processor';\n readonly dependencies: readonly Projection<unknown>[];\n readonly outputs: readonly OutputDefinition[];\n readonly create: () => ProcessorInstance;\n readonly name?: string;\n owner?: object;\n materialized?: true;\n};\n\nexport type ProducerDefinition = SourceDefinition | ProcessorDefinition;\n\nexport type ProjectionRef = {\n readonly producer: ProducerDefinition;\n readonly output: number;\n};\n\nconst projections = new WeakMap<object, ProjectionRef>();\n\nconst defineRef = <T>(producer: ProducerDefinition, output: number): Projection<T> => {\n const handle = Object.freeze({}) as Projection<T>;\n projections.set(handle, Object.freeze({ producer, output }));\n return handle;\n};\n\nexport const projectionRef = (projection: Projection<unknown>): ProjectionRef => {\n const ref = projections.get(projection);\n if (!ref) throw new TypeError('Unknown projection definition.');\n return ref;\n};\n\nexport const producerOf = (projection: Projection<unknown>): ProducerDefinition =>\n projectionRef(projection).producer;\n\n/** Resolves the immutable output description owned by a projection definition. */\nexport const outputDefinitionOf = (projection: Projection<unknown>): OutputDefinition => {\n const ref = projectionRef(projection);\n const producer = ref.producer;\n const output = producer.kind === 'source' ? producer.output : producer.outputs[ref.output];\n if (!output) throw new TypeError('Projection output does not exist.');\n return output;\n};\n\nexport const isProjection = (value: unknown): value is Projection<unknown> =>\n value !== null && typeof value === 'object' && projections.has(value);\n\nexport const ownProjections = (\n projections: readonly Projection<unknown>[],\n owner: object\n): void => {\n const producers = new Set(projections.map(producerOf));\n for (const producer of producers) {\n if (producer.owner !== undefined && producer.owner !== owner)\n throw new TypeError('Projection producer already belongs to another scope.');\n if (producer.owner === undefined && producer.materialized)\n throw new TypeError('A materialized root projection cannot become scope-owned.');\n if (producer.kind !== 'processor') continue;\n for (const dependency of producer.dependencies) {\n const dependencyOwner = producerOf(dependency).owner;\n if (dependencyOwner !== undefined && dependencyOwner !== owner)\n throw new TypeError('A scope cannot depend on another scope.');\n }\n }\n for (const producer of producers) producer.owner = owner;\n};\n\nconst freezeOutput = (output: OutputDefinition): OutputDefinition =>\n Object.freeze({\n kind: output.kind,\n equality: output.equality,\n ...(output.path ? { path: Object.freeze([...output.path]) } : {}),\n });\n\nexport const defineProcessor = (definition: {\n readonly dependencies: readonly Projection<unknown>[];\n readonly outputs: readonly OutputDefinition[];\n readonly create: () => ProcessorInstance;\n readonly name?: string;\n}): readonly Projection<unknown>[] => {\n if (!Array.isArray(definition.dependencies))\n throw new TypeError('Projection dependencies must be an array.');\n definition.dependencies.forEach(projectionRef);\n if (!definition.outputs.length) throw new TypeError('Projection processor requires an output.');\n const producer: ProcessorDefinition = {\n kind: 'processor',\n dependencies: Object.freeze([...definition.dependencies]),\n outputs: Object.freeze(definition.outputs.map(freezeOutput)),\n create: definition.create,\n ...(definition.name ? { name: definition.name } : {}),\n };\n return Object.freeze(producer.outputs.map((_, output) => defineRef<unknown>(producer, output)));\n};\n\nexport const defineSource = <T>(source: SourceAdapter, output: OutputDefinition): Projection<T> => {\n const producer: SourceDefinition = {\n kind: 'source',\n source,\n output: freezeOutput(output),\n };\n return defineRef<T>(producer, 0);\n};\n","import type { CollectionRead } from '../contract';\n\nexport const mapRead = <K extends string, V>(value: ReadonlyMap<K, V>): CollectionRead<K, V> => ({\n get: key => value.get(key),\n has: key => value.has(key),\n ids: () => Object.freeze([...value.keys()]),\n});\n\n/** Immutable map-like view over a CollectionRead. */\nexport const collectionView = <K extends string, V>(\n read: CollectionRead<K, V>\n): ReadonlyMap<K, V> => {\n const ids = read.ids();\n const entries = function* (): IterableIterator<[K, V]> {\n for (const key of ids) yield [key, read.get(key) as V];\n };\n const values = function* (): IterableIterator<V> {\n for (const key of ids) yield read.get(key) as V;\n };\n const view: ReadonlyMap<K, V> = {\n get: key => read.get(key),\n has: key => read.has(key),\n get size() {\n return ids.length;\n },\n keys: () => ids[Symbol.iterator](),\n values,\n entries,\n forEach: (callback, thisArg) => {\n for (const key of ids) callback.call(thisArg, read.get(key) as V, key, view);\n },\n [Symbol.iterator]: entries,\n };\n return Object.freeze(view);\n};\n\n/** Eager durable view used when a processor result may retain its dependency value. */\nexport const snapshotCollectionView = <K extends string, V>(\n read: CollectionRead<K, V>\n): ReadonlyMap<K, V> => {\n const ids = read.ids();\n const values = new Map<K, V>();\n for (const key of ids) values.set(key, read.get(key) as V);\n return collectionView(mapRead(values));\n};\n","import { isPlainObject } from '../value/record';\nimport { snapshotCollectionView } from './collection/view';\nimport type { SourceContext } from './contract';\nimport { isProjection, projectionRef, type Projection } from './definition';\n\nexport type CompiledProjectionDependencies = {\n readonly names: readonly string[];\n readonly projections: readonly Projection<unknown>[];\n};\n\n/** Creates the durable dependency value exposed to pure derive callbacks. */\nexport const snapshotDependencyValue = (source: SourceContext): unknown =>\n source.kind === 'value' ? source.value : snapshotCollectionView(source.read);\n\n/** Compiles the shared named Projection dependency declaration contract. */\nexport const compileProjectionDependencies = (\n dependencies: unknown,\n label: string\n): CompiledProjectionDependencies => {\n if (!isPlainObject(dependencies) || isProjection(dependencies))\n throw new TypeError(`${label} dependencies must be a plain object.`);\n const names: string[] = [];\n const projections: Projection<unknown>[] = [];\n for (const key of Reflect.ownKeys(dependencies)) {\n if (typeof key !== 'string') throw new TypeError(`${label} dependency names must be strings.`);\n const descriptor = Object.getOwnPropertyDescriptor(dependencies, key);\n if (!descriptor?.enumerable || !('value' in descriptor))\n throw new TypeError(`${label} dependencies must be enumerable data properties.`);\n const projection = descriptor.value as Projection<unknown>;\n projectionRef(projection);\n names.push(key);\n projections.push(projection);\n }\n return Object.freeze({\n names: Object.freeze(names),\n projections: Object.freeze(projections),\n });\n};\n","import type { CollectionChange } from '../contract';\n\ntype Added<K extends string, V> = { readonly key: K; readonly after: V };\ntype Updated<K extends string, V> = {\n readonly key: K;\n readonly before: V;\n readonly after: V;\n};\ntype Removed<K extends string, V> = { readonly key: K; readonly before: V };\n\nconst commonOrderChanged = <K extends string>(\n before: readonly K[],\n after: readonly K[],\n added: ReadonlySet<K>,\n removed: ReadonlySet<K>\n): boolean => {\n const beforeCommon = before.filter(key => !removed.has(key));\n const afterCommon = after.filter(key => !added.has(key));\n return beforeCommon.some((key, index) => afterCommon[index] !== key);\n};\n\n/** Builds the canonical incremental CollectionChange from already-known net transitions. */\nexport const createCollectionChange = <K extends string, V>(input: {\n readonly added: readonly Added<K, V>[];\n readonly updated: readonly Updated<K, V>[];\n readonly removed: readonly Removed<K, V>[];\n readonly beforeOrder: readonly K[];\n readonly afterOrder: readonly K[];\n}): CollectionChange<K, V> | undefined => {\n const addedKeys = new Set(input.added.map(entry => entry.key));\n const removedKeys = new Set(input.removed.map(entry => entry.key));\n const orderChanged =\n input.beforeOrder !== input.afterOrder &&\n commonOrderChanged(input.beforeOrder, input.afterOrder, addedKeys, removedKeys);\n if (!input.added.length && !input.updated.length && !input.removed.length && !orderChanged)\n return undefined;\n return Object.freeze({\n kind: 'incremental' as const,\n added: Object.freeze([...input.added]),\n updated: Object.freeze([...input.updated]),\n removed: Object.freeze([...input.removed]),\n ...(orderChanged\n ? {\n order: Object.freeze({\n before: Object.freeze([...input.beforeOrder]),\n after: Object.freeze([...input.afterOrder]),\n }),\n }\n : {}),\n });\n};\n\n/** Exact fallback diff between two published map-like snapshots. */\nexport const diffCollection = <K extends string, V>(\n previous: ReadonlyMap<K, V>,\n current: ReadonlyMap<K, V>,\n isEqual: (previous: V, next: V) => boolean = Object.is\n): CollectionChange<K, V> | undefined => {\n const added: Added<K, V>[] = [];\n const updated: Updated<K, V>[] = [];\n const removed: Removed<K, V>[] = [];\n for (const [key, before] of previous) {\n if (!current.has(key)) removed.push({ key, before });\n else {\n const after = current.get(key) as V;\n if (!isEqual(before, after)) updated.push({ key, before, after });\n }\n }\n for (const [key, after] of current) if (!previous.has(key)) added.push({ key, after });\n return createCollectionChange({\n added,\n updated,\n removed,\n beforeOrder: [...previous.keys()],\n afterOrder: [...current.keys()],\n });\n};\n\nconst changedKeys = function* <K extends string, V>(\n change: Extract<CollectionChange<K, V>, { readonly kind: 'incremental' }>\n): IterableIterator<K> {\n if ((change as CollectionChange<K, V>).kind !== 'incremental')\n throw new TypeError('collectionChange.keys requires an incremental CollectionChange.');\n for (const entry of change.added) yield entry.key;\n for (const entry of change.updated) yield entry.key;\n for (const entry of change.removed) yield entry.key;\n};\n\nexport const collectionChange: {\n readonly keys: <K extends string, V>(\n change: Extract<CollectionChange<K, V>, { readonly kind: 'incremental' }>\n ) => Iterable<K>;\n} = Object.freeze({ keys: changedKeys });\n\nexport const collectionHasStructuralChange = <K extends string, V>(\n change: CollectionChange<K, V>\n): boolean =>\n change.kind === 'reset' || Boolean(change.added.length || change.removed.length || change.order);\n","import type { CollectionImpact } from '../impact';\nimport type { Unsubscribe } from '../runtime/contract';\n\n/** Scheduler-owned metadata for one Runtime batch. */\nexport type BatchContext = {\n readonly id: number;\n readonly cause?: unknown;\n};\n\n/** The one processor-facing collection transition protocol. */\nexport type CollectionChange<K extends string, V> =\n | { readonly kind: 'reset' }\n | {\n readonly kind: 'incremental';\n readonly added: readonly { readonly key: K; readonly after: V }[];\n readonly updated: readonly {\n readonly key: K;\n readonly before: V;\n readonly after: V;\n }[];\n readonly removed: readonly { readonly key: K; readonly before: V }[];\n readonly order?: {\n readonly before: readonly K[];\n readonly after: readonly K[];\n };\n };\n\nexport type ValueContext<T> = {\n readonly kind: 'value';\n readonly value: T;\n readonly revision: number;\n readonly reset: boolean;\n readonly cause?: unknown;\n};\n\nexport type CollectionRead<K extends string, V> = {\n get(key: K): V | undefined;\n has(key: K): boolean;\n ids(): readonly K[];\n};\n\nexport type ExternalCollectionRead<K extends string, V> = {\n readonly get: (key: K) => V | undefined;\n readonly has: (key: K) => boolean;\n readonly ids: () => readonly K[];\n};\n\nexport type CollectionContext<K extends string, V> = {\n readonly kind: 'collection';\n readonly read: CollectionRead<K, V>;\n readonly change: CollectionChange<K, V> | undefined;\n readonly revision: number;\n readonly reset: boolean;\n readonly cause?: unknown;\n};\n\nexport type SourceContext = ValueContext<unknown> | CollectionContext<string, unknown>;\n\nexport type ExternalValueSource<T> = {\n readonly kind: 'value';\n current(): T;\n revision(): number;\n subscribe(listener: (event: ExternalValueEvent<T>) => void): Unsubscribe;\n};\n\nexport type ExternalCollectionSource<K extends string, V> = {\n readonly kind: 'collection';\n current(): ExternalCollectionRead<K, V>;\n revision(): number;\n subscribe(listener: (event: ExternalCollectionEvent<K, V>) => void): Unsubscribe;\n};\n\nexport type ExternalValueEvent<T> = {\n readonly value: T;\n readonly revision: number;\n readonly reset?: boolean;\n readonly cause?: unknown;\n};\n\nexport type ExternalCollectionEvent<K extends string, V> = {\n /** Stable read from the source before this event or external batch. */\n readonly previous: ExternalCollectionRead<K, V>;\n readonly revision: number;\n /** Optional document-style hint; the adapter resolves the canonical change. */\n readonly impact?: CollectionImpact<K>;\n readonly cause?: unknown;\n};\n\nexport type CollectionDraft<K extends string, V> = {\n set(key: K, value: V): void;\n remove(key: K): void;\n order(ids: readonly K[]): void;\n};\n\nexport class ProjectionError extends Error {\n readonly cause: unknown;\n\n constructor(\n readonly phase: 'processor' | 'listener' | 'source' | 'blocked',\n cause: unknown\n ) {\n super(`Projection ${phase} failed.`, { cause });\n this.name = 'ProjectionError';\n this.cause = cause;\n }\n}\n\nexport class ProjectionDisposedError extends Error {\n constructor() {\n super('Projection has been disposed.');\n this.name = 'ProjectionDisposedError';\n }\n}\n","import { profile } from '../../profile';\nimport type { ObserverError, Unsubscribe } from '../../runtime/contract';\nimport type { BatchContext, SourceContext } from '../contract';\nimport { ProjectionDisposedError, ProjectionError } from '../contract';\n\ntype BatchOptions = { readonly cause?: unknown };\n\ntype ProducerBase = {\n readonly name: string;\n readonly outputs: readonly OutputRecord[];\n fault: ProjectionError | undefined;\n disposed: boolean;\n clear(): void;\n release(): void;\n};\n\nexport type OutputRecord = {\n readonly kind: 'value' | 'collection';\n readonly owner: ProducerRecord;\n context(active: () => boolean): SourceContext;\n current(): unknown;\n revision(): number;\n reset(): boolean;\n subscribe(listener: () => void): Unsubscribe;\n emit(call: (listener: () => void) => void): void;\n hasConsumers(): boolean;\n forEachConsumer(run: (consumer: ProcessorRecord) => void): void;\n attachConsumer(consumer: ProcessorRecord): void;\n detachConsumer(consumer: ProcessorRecord): void;\n clear(): void;\n release(): void;\n};\n\nexport type SourceBoundaryRecord = ProducerBase & {\n readonly kind: 'source';\n readonly outputs: readonly [OutputRecord];\n pendingCause(): unknown;\n recovering(): boolean;\n prepare(cause: unknown): { readonly changed: boolean; readonly force: boolean };\n publish(): void;\n};\n\nexport type ProcessorRecord = ProducerBase & {\n readonly kind: 'processor';\n readonly dependencies: readonly OutputRecord[];\n readonly order: number;\n evaluate(reset: boolean, cause: unknown, recreate?: boolean): readonly OutputRecord[];\n publish(): void;\n};\n\nexport type ProducerRecord = SourceBoundaryRecord | ProcessorRecord;\n\nexport const createScheduler = (onError: (error: ProjectionError) => void) => {\n let disposed = false;\n let depth = 0;\n let batchSequence = 0;\n let activeBatch: BatchContext | undefined;\n let phase: 'idle' | 'compute' | 'notify' = 'idle';\n let sequence = 0;\n const sources = new Set<SourceBoundaryRecord>();\n const processors = new Set<ProcessorRecord>();\n const pendingSources = new Set<SourceBoundaryRecord>();\n const heap: ProcessorRecord[] = [];\n const queued = new Set<ProcessorRecord>();\n const completed = new Set<ProcessorRecord>();\n const emissions = new Set<OutputRecord>();\n const errors: ProjectionError[] = [];\n let reportingFailures: unknown[] = [];\n const guards = new Set<(locked: boolean) => void>();\n\n const assertActive = () => {\n if (disposed) throw new ProjectionDisposedError();\n };\n const assertIdle = () => {\n assertActive();\n if (phase !== 'idle')\n throw new Error('Projection cannot be re-entered during processing or notification.');\n };\n const lock = (value: boolean) => guards.forEach(guard => guard(value));\n\n const enqueue = (processor: ProcessorRecord) => {\n if (processor.disposed || queued.has(processor)) return;\n queued.add(processor);\n profile.projection('scheduledNodes');\n let index = heap.length;\n heap.push(processor);\n while (index > 0) {\n const parent = (index - 1) >> 1;\n if (heap[parent].order < processor.order) break;\n heap[index] = heap[parent];\n index = parent;\n }\n heap[index] = processor;\n };\n\n const pop = (): ProcessorRecord => {\n const first = heap[0];\n const last = heap.pop()!;\n if (heap.length) {\n let index = 0;\n while (index * 2 + 1 < heap.length) {\n let child = index * 2 + 1;\n if (child + 1 < heap.length && heap[child + 1].order < heap[child].order) child++;\n if (last.order < heap[child].order) break;\n heap[index] = heap[child];\n index = child;\n }\n heap[index] = last;\n }\n return first;\n };\n\n const errorFor = (\n producer: ProducerRecord,\n cause: unknown,\n kind: ProjectionError['phase'] = producer.kind === 'source' ? 'source' : 'processor'\n ) => new ProjectionError(kind, cause);\n\n const capture = (source: SourceBoundaryRecord) => {\n if (disposed) return;\n if (phase !== 'idle') {\n source.fault = errorFor(\n source,\n new Error('Source changed while projection was running.'),\n 'source'\n );\n errors.push(source.fault);\n throw source.fault;\n }\n pendingSources.add(source);\n profile.projection('sourceEvents');\n if (source.fault) errors.push(source.fault);\n };\n\n const settleCause = (): unknown => {\n if (activeBatch?.cause !== undefined) return activeBatch.cause;\n for (const source of pendingSources) {\n const cause = source.pendingCause();\n if (cause !== undefined) return cause;\n }\n return undefined;\n };\n\n const settle = () => {\n if (disposed || depth || phase !== 'idle') return;\n phase = 'compute';\n lock(true);\n const cause = settleCause();\n try {\n for (const source of pendingSources) {\n if (source.disposed) continue;\n const wasFaulted = source.fault !== undefined;\n let changed = false;\n let force = false;\n if (!source.fault || source.recovering()) {\n try {\n const prepared = source.prepare(cause);\n changed = prepared.changed;\n force = prepared.force;\n source.fault = undefined;\n } catch (failure) {\n source.fault = errorFor(source, failure, 'source');\n errors.push(source.fault);\n }\n }\n const recovered = wasFaulted && !source.fault;\n if (changed) source.publish();\n if (source.fault || changed || force || recovered) {\n const output = source.outputs[0];\n emissions.add(output);\n output.forEachConsumer(enqueue);\n }\n }\n\n while (heap.length) {\n const processor = pop();\n if (processor.disposed) continue;\n const wasFaulted = processor.fault !== undefined;\n profile.projection('processedNodes');\n let changedOutputs: readonly OutputRecord[] = Object.freeze([]);\n const blocked = processor.dependencies.find(\n output => output.owner.fault || output.owner.disposed\n );\n if (blocked) {\n processor.fault = errorFor(\n processor,\n blocked.owner.fault ?? new ProjectionDisposedError(),\n 'blocked'\n );\n } else {\n const reset = wasFaulted || processor.dependencies.some(output => output.reset());\n try {\n changedOutputs = processor.evaluate(reset, cause, wasFaulted);\n const dependencyFailure = processor.dependencies.find(output => output.owner.fault)\n ?.owner.fault;\n if (dependencyFailure) throw dependencyFailure;\n processor.fault = undefined;\n } catch (failure) {\n const error = errorFor(processor, failure);\n processor.fault = error;\n if (!reset) {\n try {\n changedOutputs = processor.evaluate(true, cause, true);\n const dependencyFailure = processor.dependencies.find(output => output.owner.fault)\n ?.owner.fault;\n if (dependencyFailure) throw dependencyFailure;\n processor.fault = undefined;\n errors.push(error);\n } catch (rebuildFailure) {\n processor.fault = errorFor(processor, rebuildFailure);\n errors.push(processor.fault);\n }\n } else errors.push(error);\n }\n }\n completed.add(processor);\n const recovered = wasFaulted && !processor.fault;\n if (processor.fault) {\n processor.outputs.forEach(output => {\n emissions.add(output);\n output.forEachConsumer(enqueue);\n });\n } else {\n if (changedOutputs.length) {\n processor.publish();\n changedOutputs.forEach(output => emissions.add(output));\n }\n const propagated = recovered ? processor.outputs : changedOutputs;\n propagated.forEach(output => output.forEachConsumer(enqueue));\n }\n if (processor.fault || changedOutputs.length) {\n profile.projection('publishedNodes');\n }\n }\n } finally {\n lock(false);\n phase = 'idle';\n }\n };\n\n const flush = (): readonly ObserverError[] => {\n if (disposed || depth) return [];\n if (pendingSources.size || completed.size) profile.projection('flushes');\n phase = 'notify';\n lock(true);\n const reportFailures: unknown[] = [];\n try {\n emissions.forEach(output =>\n output.emit(listener => {\n try {\n listener();\n } catch (cause) {\n errors.push(errorFor(output.owner, cause, 'listener'));\n }\n })\n );\n for (const error of errors.slice()) {\n try {\n onError(error);\n } catch (cause) {\n reportFailures.push(cause);\n }\n }\n return Object.freeze([\n ...errors.map(error =>\n Object.freeze({\n phase: error.phase === 'listener' ? ('listener' as const) : ('processor' as const),\n error,\n })\n ),\n ...reportFailures.map(error => Object.freeze({ phase: 'listener' as const, error })),\n ]);\n } finally {\n pendingSources.forEach(source => source.clear());\n completed.forEach(processor => processor.clear());\n pendingSources.clear();\n queued.clear();\n completed.clear();\n emissions.clear();\n errors.length = 0;\n reportingFailures = reportFailures;\n lock(false);\n phase = 'idle';\n }\n };\n\n const run = () => {\n settle();\n const result = flush();\n const failures = reportingFailures;\n reportingFailures = [];\n if (failures.length) throw new AggregateError(failures, 'Projection error reporter failed.');\n return result;\n };\n\n const batch = <T>(callback: () => T, options?: BatchOptions): T => {\n assertIdle();\n const outer = depth === 0;\n if (outer)\n activeBatch = Object.freeze({\n id: ++batchSequence,\n ...(options?.cause === undefined ? {} : { cause: options.cause }),\n });\n depth++;\n let failed = false;\n try {\n const value = callback();\n assertSynchronous(value);\n return value;\n } catch (error) {\n failed = true;\n throw error;\n } finally {\n depth--;\n if (!depth) {\n try {\n if (failed) {\n try {\n run();\n } catch {\n /* The original application error retains priority. */\n }\n } else run();\n } finally {\n activeBatch = undefined;\n }\n }\n }\n };\n\n const releaseProducer = (producer: ProducerRecord) => {\n assertIdle();\n if (producer.outputs.some(output => output.hasConsumers()))\n throw new Error('Projection producer is still used by another processor.');\n producer.disposed = true;\n if (producer.kind === 'processor') {\n producer.dependencies.forEach(output => output.detachConsumer(producer));\n processors.delete(producer);\n queued.delete(producer);\n completed.delete(producer);\n } else {\n sources.delete(producer);\n pendingSources.delete(producer);\n }\n const failures: unknown[] = [];\n try {\n producer.release();\n } catch (error) {\n failures.push(error);\n }\n try {\n producer.clear();\n } catch (error) {\n failures.push(error);\n }\n producer.outputs.forEach(output => emissions.delete(output));\n if (failures.length) throw failures[0];\n };\n\n return {\n assertActive,\n assertIdle,\n capture,\n settle,\n flush,\n run,\n registerGuard(guard: (locked: boolean) => void): Unsubscribe {\n assertActive();\n guards.add(guard);\n let registered = true;\n return () => {\n if (!registered) return;\n registered = false;\n guards.delete(guard);\n };\n },\n get active() {\n return !disposed;\n },\n addSource(source: SourceBoundaryRecord) {\n assertIdle();\n sources.add(source);\n },\n addProcessor(processor: ProcessorRecord) {\n assertIdle();\n processors.add(processor);\n processor.dependencies.forEach(output => output.attachConsumer(processor));\n },\n releaseProducer,\n order: () => sequence++,\n initialize<T>(callback: () => T): T {\n assertIdle();\n phase = 'compute';\n lock(true);\n try {\n return callback();\n } finally {\n lock(false);\n phase = 'idle';\n }\n },\n batch,\n batchContext: () => activeBatch,\n dispose() {\n if (disposed) return;\n assertIdle();\n disposed = true;\n const failures: unknown[] = [];\n processors.forEach(processor => {\n processor.disposed = true;\n try {\n processor.release();\n } catch (error) {\n failures.push(error);\n }\n });\n sources.forEach(source => {\n source.disposed = true;\n try {\n source.release();\n } catch (error) {\n failures.push(error);\n }\n });\n processors.clear();\n sources.clear();\n pendingSources.clear();\n heap.length = 0;\n queued.clear();\n completed.clear();\n emissions.clear();\n guards.clear();\n errors.length = 0;\n reportingFailures = [];\n if (failures.length) throw new AggregateError(failures, 'Projection cleanup failed.');\n },\n };\n};\n\nexport type Scheduler = ReturnType<typeof createScheduler>;\n\nexport const assertSynchronous = (value: unknown): void => {\n if (\n value != null &&\n (typeof value === 'object' || typeof value === 'function') &&\n 'then' in value &&\n typeof value.then === 'function'\n )\n throw new TypeError('Projection callbacks must be synchronous.');\n};\n\nexport const assertScope = (active: () => boolean) => {\n if (!active()) throw new Error('Projection reader or writer is no longer active.');\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doxum",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "private": false,
5
5
  "license": "MIT",
6
6
  "description": "Doxum is a typed runtime for complex mutable documents.",
@@ -47,9 +47,11 @@ Before runtime changes read [invariants](references/invariants.en.md) or
47
47
  `KeyedProjection<K,V>` is the single public keyed projection handle. Collection
48
48
  `observe`, `derive.keyed`, `incremental.collection`, group collection leaves and
49
49
  `CollectionInput<K,V>` all use that same keyed capability.
50
- Use named-object `derive` for pure aggregate values. Use `derive.keyed` when one keyed
51
- driver owns the output key domain/order: per-entry equality suppresses unchanged
52
- selected values. Its dependency form uses a named object: plain Projection members
50
+ Use named-object `derive` for pure aggregate values. The `derive.keyed` family owns
51
+ keyed derivation: ordinary `derive.keyed` preserves driver membership/order;
52
+ `keys`/`values` expose standard ordered read shapes; `subset`/`filter`/`compact` own
53
+ membership-changing derivation without application-side collection patch loops.
54
+ Per-entry equality suppresses unchanged generated values. Its dependency form uses a named object: plain Projection members
53
55
  invalidate the driver key set, while `{ source, key }` members let the Runtime own
54
56
  per-output-key source bindings and reverse lookup. Selectors receive
55
57
  `(entry, key)` or `(entry, key, dependencies)`. The producer graph remains explicit and static;
@@ -60,7 +62,9 @@ Before runtime changes read [invariants](references/invariants.en.md) or
60
62
  definitions with the root declaration APIs, then own a projection or static output tree
61
63
  before that definition is first materialized as a root.
62
64
  Use advanced `incremental` only for retained state or cross-key coordination that
63
- cannot be expressed by `derive.keyed`. React selector tracking remains a consumer
65
+ cannot be expressed by the `derive.keyed` family. `collectionChange.keys` is the
66
+ transport-level iterable for incremental added/updated/removed keys; callers handle
67
+ reset and order semantics themselves. React selector tracking remains a consumer
64
68
  concern through `ProjectionProvider` and `useProjection(projection, selector)`.
65
69
  - Advanced incremental definitions always declare `process`; `state()` is present only
66
70
  when retained state is actually needed. `incremental.group` declares its static