doxum 0.1.34 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +19 -0
  2. package/dist/advanced.cjs +1 -3
  3. package/dist/advanced.d.cts +1 -2
  4. package/dist/advanced.d.ts +1 -2
  5. package/dist/advanced.js +1 -3
  6. package/dist/contract-CNR6BS75.d.cts +1 -2
  7. package/dist/contract-COgxO5sv.d.ts +1 -2
  8. package/dist/dependency-Cbf3C8eJ.d.cts +1 -2
  9. package/dist/dependency-DzxXGYe1.d.ts +1 -2
  10. package/dist/driver-B7RR-VfX.js +0 -2
  11. package/dist/driver-CN3dGxQI.cjs +0 -2
  12. package/dist/index.cjs +56 -21
  13. package/dist/index.d.cts +12 -7
  14. package/dist/index.d.ts +12 -7
  15. package/dist/index.js +56 -21
  16. package/dist/local-sync.cjs +0 -2
  17. package/dist/local-sync.d.cts +1 -2
  18. package/dist/local-sync.d.ts +1 -2
  19. package/dist/local-sync.js +0 -2
  20. package/dist/react.cjs +0 -2
  21. package/dist/react.d.cts +1 -2
  22. package/dist/react.d.ts +1 -2
  23. package/dist/react.js +0 -2
  24. package/dist/record-B2yRhYsc.js +0 -2
  25. package/dist/record-ChYUi8PP.cjs +0 -2
  26. package/dist/{transform-RghG_Qxs.js → transform-3mj0eStL.js} +7 -3
  27. package/dist/{transform-Bt1Mwgrj.cjs → transform-D45KWMzj.cjs} +8 -4
  28. package/package.json +8 -3
  29. package/skills/doxum-runtime/SKILL.md +2 -2
  30. package/skills/doxum-runtime/references/projections.md +27 -0
  31. package/skills/doxum-runtime/references/public-api.md +19 -14
  32. package/skills/doxum-runtime/references/recipes.md +23 -0
  33. package/dist/advanced.cjs.map +0 -1
  34. package/dist/advanced.js.map +0 -1
  35. package/dist/driver-B7RR-VfX.js.map +0 -1
  36. package/dist/driver-CN3dGxQI.cjs.map +0 -1
  37. package/dist/index.cjs.map +0 -1
  38. package/dist/index.js.map +0 -1
  39. package/dist/local-sync.cjs.map +0 -1
  40. package/dist/local-sync.js.map +0 -1
  41. package/dist/react.cjs.map +0 -1
  42. package/dist/react.js.map +0 -1
  43. package/dist/record-B2yRhYsc.js.map +0 -1
  44. package/dist/record-ChYUi8PP.cjs.map +0 -1
  45. package/dist/transform-Bt1Mwgrj.cjs.map +0 -1
  46. package/dist/transform-RghG_Qxs.js.map +0 -1
package/README.md CHANGED
@@ -432,6 +432,18 @@ const lines = derive.keyed.flatMap(orders, order =>
432
432
 
433
433
  Each parent returns ordered `[globalKey, value]` tuples, including zero entries. `flatMap` reuses named/dynamic keyed dependencies and only recomputes invalidated parents. Formal output order follows parent order then child order; parent-only reordering runs no selectors. Duplicate final output keys are errors, and present `undefined` is valid. Same-batch transfers preserve a global key's membership identity. Structural changes can rebuild full order; this is not a claim that every operation costs only the changed entries.
434
434
 
435
+ ### Compute a keyed result from named inputs
436
+
437
+ ```ts
438
+ const errors = derive.keyed.fromEntries(
439
+ { form: formState, rules: validationRules },
440
+ ({ form, rules }) => validateForm(form, rules).map(error => [error.id, error]),
441
+ (before, after) => before.message === after.message && before.field === after.field
442
+ );
443
+ ```
444
+
445
+ `fromEntries` uses the same named dependencies as `derive`, including the single-source form `{ form }`. The synchronous callback returns the complete ordered `[key, value]` array: `[]` is empty, missing keys are removed, and `[key, undefined]` is present. Duplicate keys are errors. Per-entry equality preserves equivalent value references while membership/order changes remain observable. It computes and scans the full result, then publishes exact changes; use `flatMap` for per-parent incremental computation or `derive.keyed.get` as an input for precise active-entry dependencies. See [Projection API](docs/projections.md#keyed-results-from-named-dependencies).
446
+
435
447
  ### Runtime-local keyed state
436
448
 
437
449
  Use `input.collection` for selection, expanded state, local overrides and other
@@ -654,6 +666,13 @@ round trips and repeated tree edits to expose costs hidden by commit-only benchm
654
666
  Builds produce root `dist` ESM/CJS/declarations for `doxum`,
655
667
  `doxum/local-sync`, `doxum/react` and `doxum/advanced`. Source ownership is described in
656
668
  [architecture](docs/architecture.md) and [AGENTS.md](AGENTS.md).
669
+ Release builds keep JavaScript readable and omit source maps. Use `pnpm run build:debug`
670
+ to generate a separate `.debug/dist` build with embedded-source maps for source-level
671
+ debugging; it does not replace `dist` and is excluded from publication. Published
672
+ packages include both module formats, their declarations and the runtime skill.
673
+ `pnpm run check:package` inspects the actual npm file list, checks required artifacts
674
+ and reports packed/unpacked sizes. It runs as part of `build`, including releases,
675
+ and rejects accidental debug artifacts or dangling source-map references.
657
676
  The runtime shares one transaction lifecycle; complete mutation operations are
658
677
  organized by domain under `core/src/mutation/operations`, with access, first-touch
659
678
  recording and publication retaining their own responsibilities.
package/dist/advanced.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_transform = require("./transform-Bt1Mwgrj.cjs");
2
+ const require_transform = require("./transform-D45KWMzj.cjs");
3
3
  const require_record = require("./record-ChYUi8PP.cjs");
4
4
  //#region core/src/projection/advanced.ts
5
5
  const resetCollectionChange = Object.freeze({ kind: "reset" });
@@ -244,5 +244,3 @@ const incremental = Object.assign(createIncrementalValue, {
244
244
  //#endregion
245
245
  exports.collectionChange = require_transform.collectionChange;
246
246
  exports.incremental = incremental;
247
-
248
- //# sourceMappingURL=advanced.cjs.map
@@ -118,5 +118,4 @@ declare const incremental: typeof createIncrementalValue & {
118
118
  group: typeof createIncrementalGroup;
119
119
  };
120
120
  //#endregion
121
- export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionDefinition, IncrementalGroupContext, IncrementalGroupOutput, IncrementalGroupResult, IncrementalKeyedContext, IncrementalKeyedDefinition, IncrementalValueContext, IncrementalValueDefinition, collectionChange, incremental };
122
- //# sourceMappingURL=advanced.d.cts.map
121
+ export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionDefinition, IncrementalGroupContext, IncrementalGroupOutput, IncrementalGroupResult, IncrementalKeyedContext, IncrementalKeyedDefinition, IncrementalValueContext, IncrementalValueDefinition, collectionChange, incremental };
@@ -118,5 +118,4 @@ declare const incremental: typeof createIncrementalValue & {
118
118
  group: typeof createIncrementalGroup;
119
119
  };
120
120
  //#endregion
121
- export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionDefinition, IncrementalGroupContext, IncrementalGroupOutput, IncrementalGroupResult, IncrementalKeyedContext, IncrementalKeyedDefinition, IncrementalValueContext, IncrementalValueDefinition, collectionChange, incremental };
122
- //# sourceMappingURL=advanced.d.ts.map
121
+ export { type CollectionChange, IncrementalCollectionContext, IncrementalCollectionDefinition, IncrementalGroupContext, IncrementalGroupOutput, IncrementalGroupResult, IncrementalKeyedContext, IncrementalKeyedDefinition, IncrementalValueContext, IncrementalValueDefinition, collectionChange, incremental };
package/dist/advanced.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as defineProcessor, S as compileProjectionDependencies, _ as assertSynchronous, r as collectionChange, t as createKeyedTransform, w as collectionView } from "./transform-RghG_Qxs.js";
1
+ import { D as defineProcessor, S as compileProjectionDependencies, _ as assertSynchronous, r as collectionChange, t as createKeyedTransform, w as collectionView } from "./transform-3mj0eStL.js";
2
2
  import { n as isPlainObject } from "./record-B2yRhYsc.js";
3
3
  //#region core/src/projection/advanced.ts
4
4
  const resetCollectionChange = Object.freeze({ kind: "reset" });
@@ -242,5 +242,3 @@ const incremental = Object.assign(createIncrementalValue, {
242
242
  });
243
243
  //#endregion
244
244
  export { collectionChange, incremental };
245
-
246
- //# sourceMappingURL=advanced.js.map
@@ -617,5 +617,4 @@ type DocumentRuntime<S extends ObjectSchema<object>> = ReadonlyDocument<S> & {
617
617
  dispose(): void;
618
618
  };
619
619
  //#endregion
620
- export { table as $, ParseError as A, DocumentListConfig as B, Read as C, ChangeSet as D, Change as E, CollectionPath as F, ReadonlyValue as G, DocumentTreeValue as H, PathValueOf as I, field as J, Schema as K, SchemaPath as L, parse as M, CollectionEntry as N, MemberChange as O, CollectionId as P, optional as Q, DocumentAddress as R, Draft as S, snapshot as T, Infer as U, DocumentTreeNode as V, ObjectSchema as W, map as X, list as Y, object as Z, Unsubscribe as _, DocumentProblem as a, CollectionImpact as b, HistoryState as c, OperationResult as d, tree as et, ReadonlyDocument as f, Readable as g, TransactionResult as h, DocumentDisposedError as i, ParseIssue as j, ValueTransition as k, LocalHistory as l, TransactionRejected as m, DocumentCommit as n, DocumentReentrancyError as o, Synchronous as p, Validator as q, DocumentDiagnostic as r, DocumentRuntime as s, CommitSource as t, variant as tt, ObserverError as u, MutationIssue as v, replace as w, DocumentImpact as x, MutationIssueCode as y, DocumentAnchor as z };
621
- //# sourceMappingURL=contract-CNR6BS75.d.cts.map
620
+ export { table as $, ParseError as A, DocumentListConfig as B, Read as C, ChangeSet as D, Change as E, CollectionPath as F, ReadonlyValue as G, DocumentTreeValue as H, PathValueOf as I, field as J, Schema as K, SchemaPath as L, parse as M, CollectionEntry as N, MemberChange as O, CollectionId as P, optional as Q, DocumentAddress as R, Draft as S, snapshot as T, Infer as U, DocumentTreeNode as V, ObjectSchema as W, map as X, list as Y, object as Z, Unsubscribe as _, DocumentProblem as a, CollectionImpact as b, HistoryState as c, OperationResult as d, tree as et, ReadonlyDocument as f, Readable as g, TransactionResult as h, DocumentDisposedError as i, ParseIssue as j, ValueTransition as k, LocalHistory as l, TransactionRejected as m, DocumentCommit as n, DocumentReentrancyError as o, Synchronous as p, Validator as q, DocumentDiagnostic as r, DocumentRuntime as s, CommitSource as t, variant as tt, ObserverError as u, MutationIssue as v, replace as w, DocumentImpact as x, MutationIssueCode as y, DocumentAnchor as z };
@@ -617,5 +617,4 @@ type DocumentRuntime<S extends ObjectSchema<object>> = ReadonlyDocument<S> & {
617
617
  dispose(): void;
618
618
  };
619
619
  //#endregion
620
- export { table as $, ParseError as A, DocumentListConfig as B, Read as C, ChangeSet as D, Change as E, CollectionPath as F, ReadonlyValue as G, DocumentTreeValue as H, PathValueOf as I, field as J, Schema as K, SchemaPath as L, parse as M, CollectionEntry as N, MemberChange as O, CollectionId as P, optional as Q, DocumentAddress as R, Draft as S, snapshot as T, Infer as U, DocumentTreeNode as V, ObjectSchema as W, map as X, list as Y, object as Z, Unsubscribe as _, DocumentProblem as a, CollectionImpact as b, HistoryState as c, OperationResult as d, tree as et, ReadonlyDocument as f, Readable as g, TransactionResult as h, DocumentDisposedError as i, ParseIssue as j, ValueTransition as k, LocalHistory as l, TransactionRejected as m, DocumentCommit as n, DocumentReentrancyError as o, Synchronous as p, Validator as q, DocumentDiagnostic as r, DocumentRuntime as s, CommitSource as t, variant as tt, ObserverError as u, MutationIssue as v, replace as w, DocumentImpact as x, MutationIssueCode as y, DocumentAnchor as z };
621
- //# sourceMappingURL=contract-COgxO5sv.d.ts.map
620
+ export { table as $, ParseError as A, DocumentListConfig as B, Read as C, ChangeSet as D, Change as E, CollectionPath as F, ReadonlyValue as G, DocumentTreeValue as H, PathValueOf as I, field as J, Schema as K, SchemaPath as L, parse as M, CollectionEntry as N, MemberChange as O, CollectionId as P, optional as Q, DocumentAddress as R, Draft as S, snapshot as T, Infer as U, DocumentTreeNode as V, ObjectSchema as W, map as X, list as Y, object as Z, Unsubscribe as _, DocumentProblem as a, CollectionImpact as b, HistoryState as c, OperationResult as d, tree as et, ReadonlyDocument as f, Readable as g, TransactionResult as h, DocumentDisposedError as i, ParseIssue as j, ValueTransition as k, LocalHistory as l, TransactionRejected as m, DocumentCommit as n, DocumentReentrancyError as o, Synchronous as p, Validator as q, DocumentDiagnostic as r, DocumentRuntime as s, CommitSource as t, variant as tt, ObserverError as u, MutationIssue as v, replace as w, DocumentImpact as x, MutationIssueCode as y, DocumentAnchor as z };
@@ -143,5 +143,4 @@ type KeyedDependencyValues<D extends object> = { readonly [P in keyof D]: D[P] e
143
143
  readonly source: KeyedProjection<infer _K extends string, infer V>;
144
144
  } ? V | undefined : D[P] extends Projection<infer T> ? T : never };
145
145
  //#endregion
146
- export { ProjectionDisposedError as _, Input as a, ProjectionChange as c, CollectionRead as d, ExternalCollectionEvent as f, ExternalValueSource as g, ExternalValueEvent as h, CollectionInputDraft as i, CollectionChange as l, ExternalCollectionSource as m, KeyedDependencyValues as n, KeyedProjection as o, ExternalCollectionRead as p, CollectionInput as r, Projection as s, KeyedDependencies as t, CollectionDraft as u, ProjectionError as v };
147
- //# sourceMappingURL=dependency-Cbf3C8eJ.d.cts.map
146
+ export { ProjectionDisposedError as _, Input as a, ProjectionChange as c, CollectionRead as d, ExternalCollectionEvent as f, ExternalValueSource as g, ExternalValueEvent as h, CollectionInputDraft as i, CollectionChange as l, ExternalCollectionSource as m, KeyedDependencyValues as n, KeyedProjection as o, ExternalCollectionRead as p, CollectionInput as r, Projection as s, KeyedDependencies as t, CollectionDraft as u, ProjectionError as v };
@@ -143,5 +143,4 @@ type KeyedDependencyValues<D extends object> = { readonly [P in keyof D]: D[P] e
143
143
  readonly source: KeyedProjection<infer _K extends string, infer V>;
144
144
  } ? V | undefined : D[P] extends Projection<infer T> ? T : never };
145
145
  //#endregion
146
- export { ProjectionDisposedError as _, Input as a, ProjectionChange as c, CollectionRead as d, ExternalCollectionEvent as f, ExternalValueSource as g, ExternalValueEvent as h, CollectionInputDraft as i, CollectionChange as l, ExternalCollectionSource as m, KeyedDependencyValues as n, KeyedProjection as o, ExternalCollectionRead as p, CollectionInput as r, Projection as s, KeyedDependencies as t, CollectionDraft as u, ProjectionError as v };
147
- //# sourceMappingURL=dependency-DzxXGYe1.d.ts.map
146
+ export { ProjectionDisposedError as _, Input as a, ProjectionChange as c, CollectionRead as d, ExternalCollectionEvent as f, ExternalValueSource as g, ExternalValueEvent as h, CollectionInputDraft as i, CollectionChange as l, ExternalCollectionSource as m, KeyedDependencyValues as n, KeyedProjection as o, ExternalCollectionRead as p, CollectionInput as r, Projection as s, KeyedDependencies as t, CollectionDraft as u, ProjectionError as v };
@@ -400,5 +400,3 @@ const installRuntimeWriteDriver = (runtime, driver) => {
400
400
  };
401
401
  //#endregion
402
402
  export { changeCount as a, AddressIndex as c, invalidValue as d, children as f, validate as g, parent as h, contextOf as i, MutationRejected as l, is as m, installRuntimeWriteDriver as n, decodeChanges as o, contains as p, bindContext as r, sealChanges as s, assertRuntimeWritable as t, fail as u };
403
-
404
- //# sourceMappingURL=driver-B7RR-VfX.js.map
@@ -495,5 +495,3 @@ Object.defineProperty(exports, "validate", {
495
495
  return validate;
496
496
  }
497
497
  });
498
-
499
- //# sourceMappingURL=driver-CN3dGxQI.cjs.map
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_transform = require("./transform-Bt1Mwgrj.cjs");
2
+ const require_transform = require("./transform-D45KWMzj.cjs");
3
3
  const require_record = require("./record-ChYUi8PP.cjs");
4
4
  const require_driver = require("./driver-CN3dGxQI.cjs");
5
5
  //#region core/src/schema/model.ts
@@ -2775,6 +2775,12 @@ const isExternalSource = (source) => {
2775
2775
  return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
2776
2776
  };
2777
2777
  //#endregion
2778
+ //#region core/src/projection/keyed/entries.ts
2779
+ /** Shared entry boundary; membership and duplicate policy belong to each operation. */
2780
+ function assertKeyedEntry(entry, name) {
2781
+ if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string") throw new TypeError(`${name} entries must be [string key, value] tuples.`);
2782
+ }
2783
+ //#endregion
2778
2784
  //#region core/src/projection/keyed/flat-map.ts
2779
2785
  function createKeyedFlatMap(source, dependenciesOrSelect, selectOrEquality, maybeEquality) {
2780
2786
  const name = "derive.keyed.flatMap";
@@ -2821,7 +2827,7 @@ function createKeyedFlatMap(source, dependenciesOrSelect, selectOrEquality, mayb
2821
2827
  if (!Array.isArray(entries)) throw new TypeError(`${name} selector must return an array of entries.`);
2822
2828
  const keys = [];
2823
2829
  for (const entry of entries) {
2824
- if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string") throw new TypeError(`${name} entries must be [string key, value] tuples.`);
2830
+ assertKeyedEntry(entry, name);
2825
2831
  const [key, child] = entry;
2826
2832
  const owner = ownerByOutput.get(key);
2827
2833
  if (proposals.has(key) || owner !== void 0 && !replaced.has(owner)) throw new TypeError(`${name} duplicate key ${JSON.stringify(key)}.`);
@@ -2908,6 +2914,25 @@ const assertCollectionSources = (sources, expected) => {
2908
2914
  if (sources.length !== expected) throw new Error("derive.keyed.merge resolved an invalid dependency count.");
2909
2915
  for (const source of sources) if (source.kind !== "collection") throw new Error("derive.keyed.merge requires collection inputs.");
2910
2916
  };
2917
+ /** Complete ordered result reconciliation, without retaining a second member/value cache. */
2918
+ const stageKeyedSnapshot = (values, output, keyOf, valueOf, name) => {
2919
+ const seen = /* @__PURE__ */ new Set();
2920
+ const order = new Array(values.length);
2921
+ const previous = output.previous.ids();
2922
+ require_transform.profile.collectionView.idsScanned(values.length + previous.length);
2923
+ for (let index = 0; index < values.length; index++) {
2924
+ const value = values[index];
2925
+ const key = keyOf(value);
2926
+ require_transform.assertSynchronous(key);
2927
+ if (typeof key !== "string") throw new TypeError(`${name} key selector must return a string.`);
2928
+ if (seen.has(key)) throw new TypeError(`${name} duplicate key ${JSON.stringify(key)}.`);
2929
+ seen.add(key);
2930
+ order[index] = key;
2931
+ output.output.set(key, valueOf(value));
2932
+ }
2933
+ for (const key of previous) if (!seen.has(key)) output.output.remove(key);
2934
+ output.output.order(order);
2935
+ };
2911
2936
  function createKeyedFrom(source, keyOf, equality) {
2912
2937
  if (typeof keyOf !== "function") throw new TypeError("derive.keyed.from requires a key selector.");
2913
2938
  const outputEquality = assertEquality(equality, "derive.keyed.from");
@@ -2937,25 +2962,38 @@ function createKeyedFrom(source, keyOf, equality) {
2937
2962
  values = scalar.value;
2938
2963
  }
2939
2964
  if (!values) throw new Error("derive.keyed.from has no source values.");
2940
- const seen = /* @__PURE__ */ new Set();
2941
- const order = new Array(values.length);
2942
- for (let index = 0; index < values.length; index++) {
2943
- const value = values[index];
2944
- const key = keyOf(value);
2945
- require_transform.assertSynchronous(key);
2946
- if (typeof key !== "string") throw new TypeError("derive.keyed.from key selector must return a string.");
2947
- if (seen.has(key)) throw new TypeError(`derive.keyed.from duplicate key ${JSON.stringify(key)}.`);
2948
- seen.add(key);
2949
- order[index] = key;
2950
- output.output.set(key, value);
2951
- }
2952
- for (const previousKey of output.previous.ids()) if (!seen.has(previousKey)) output.output.remove(previousKey);
2953
- output.output.order(order);
2965
+ stageKeyedSnapshot(values, output, keyOf, (value) => value, "derive.keyed.from");
2954
2966
  } }),
2955
2967
  name: "derive.keyed.from"
2956
2968
  });
2957
2969
  return projection;
2958
2970
  }
2971
+ function createKeyedFromEntries(dependencies, compute, equality) {
2972
+ const name = "derive.keyed.fromEntries";
2973
+ const compiled = require_transform.compileProjectionDependencies(dependencies, name);
2974
+ if (typeof compute !== "function") throw new TypeError(`${name} requires a compute callback.`);
2975
+ const outputEquality = assertEquality(equality, name);
2976
+ const [projection] = require_transform.defineProcessor({
2977
+ dependencies: compiled.projections,
2978
+ outputs: [{
2979
+ kind: "collection",
2980
+ equality: outputEquality
2981
+ }],
2982
+ name,
2983
+ create: () => ({ evaluate: (evaluation) => {
2984
+ const output = evaluation.outputs[0];
2985
+ if (output.kind !== "collection") throw new Error(`${name} requires a collection output.`);
2986
+ const entries = compute(require_transform.snapshotProjectionValues(compiled.names, evaluation.sources));
2987
+ require_transform.assertSynchronous(entries);
2988
+ if (!Array.isArray(entries)) throw new TypeError(`${name} compute must return an array of entries.`);
2989
+ stageKeyedSnapshot(entries, output, (entry) => {
2990
+ assertKeyedEntry(entry, name);
2991
+ return entry[0];
2992
+ }, (entry) => entry[1], name);
2993
+ } })
2994
+ });
2995
+ return projection;
2996
+ }
2959
2997
  function createKeyedMerge(sources, options) {
2960
2998
  if (!Array.isArray(sources)) throw new TypeError("derive.keyed.merge sources must be an array of keyed projections.");
2961
2999
  const capturedSources = require_transform.snapshotArray(sources);
@@ -3584,6 +3622,7 @@ const keyedDerive = Object.assign(createKeyedDerive, {
3584
3622
  entries: createKeyedEntries,
3585
3623
  get: createKeyedGet,
3586
3624
  from: createKeyedFrom,
3625
+ fromEntries: createKeyedFromEntries,
3587
3626
  merge: createKeyedMerge,
3588
3627
  groupBy: createKeyedGroupBy,
3589
3628
  flatMap: createKeyedFlatMap,
@@ -3607,9 +3646,7 @@ function createValueDerive(dependencies, compute, equality = Object.is) {
3607
3646
  create: () => ({ evaluate: (evaluation) => {
3608
3647
  const output = evaluation.outputs[0];
3609
3648
  if (output.kind !== "value") throw new Error("derive requires a value output.");
3610
- const values = Object.create(null);
3611
- for (let index = 0; index < names.length; index++) values[names[index]] = require_transform.snapshotDependencyValue(evaluation.sources[index]);
3612
- const next = compute(Object.freeze(values));
3649
+ const next = compute(require_transform.snapshotProjectionValues(names, evaluation.sources));
3613
3650
  require_transform.assertSynchronous(next);
3614
3651
  output.output.set(next);
3615
3652
  } })
@@ -6430,5 +6467,3 @@ exports.snapshot = snapshot;
6430
6467
  exports.table = table;
6431
6468
  exports.tree = tree;
6432
6469
  exports.variant = variant;
6433
-
6434
- //# sourceMappingURL=index.cjs.map
package/dist/index.d.cts CHANGED
@@ -29,10 +29,18 @@ declare function observe<T>(readable: Readable<T>): Projection<T>;
29
29
  declare function observe<S extends ObjectSchema<object>, P extends CollectionPath>(document: ReadonlyDocument<S>, selector: (path: SchemaPath<S>) => P): KeyedProjection<CollectionId<P>, ReadonlyValue<CollectionEntry<P>>>;
30
30
  declare function observe<S extends ObjectSchema<object>, P>(document: ReadonlyDocument<S>, selector: (path: SchemaPath<S>) => P): Projection<PathValueOf<P>>;
31
31
  //#endregion
32
+ //#region core/src/projection/dependency.d.ts
33
+ type ProjectionDependencies = Readonly<Record<string, Projection<unknown>>> & Partial<Record<keyof Projection<unknown>, never>>;
34
+ type ProjectionValues<D extends ProjectionDependencies> = { readonly [K in keyof D]: D[K] extends Projection<infer T> ? T : never };
35
+ //#endregion
36
+ //#region core/src/projection/keyed/entries.d.ts
37
+ type KeyedEntries<K extends string, V> = readonly (readonly [K, V])[];
38
+ //#endregion
32
39
  //#region core/src/projection/keyed/composition.d.ts
33
40
  type Equality$2<T> = (previous: T, next: T) => boolean;
34
41
  declare function createKeyedFrom<K extends string, V>(source: Projection<readonly V[]>, keyOf: (value: NoInfer<V>) => Synchronous<K>, equality?: Equality$2<V>): KeyedProjection<K, V>;
35
42
  declare function createKeyedFrom<K extends string, V>(source: readonly V[], keyOf: (value: NoInfer<V>) => Synchronous<K>, equality?: Equality$2<V>): KeyedProjection<K, V>;
43
+ declare function createKeyedFromEntries<const D extends ProjectionDependencies, K extends string, V>(dependencies: D, compute: (values: ProjectionValues<D>) => Synchronous<KeyedEntries<K, V>>, equality?: Equality$2<NoInfer<V>>): KeyedProjection<K, V>;
36
44
  declare function createKeyedMerge<K extends string, V>(sources: readonly KeyedProjection<K, V>[], options: {
37
45
  readonly conflict: 'error' | 'first' | 'last';
38
46
  readonly equality?: Equality$2<V>;
@@ -47,14 +55,11 @@ declare function createKeyedMerge<K extends string, V>(sources: readonly KeyedPr
47
55
  }): KeyedProjection<K, V>;
48
56
  //#endregion
49
57
  //#region core/src/projection/keyed/flat-map.d.ts
50
- type Entries<K extends string, V> = readonly (readonly [K, V])[];
51
58
  type Equality$1<V> = (previous: V, next: V) => boolean;
52
- declare function createKeyedFlatMap<K extends string, V, O extends string, T>(source: KeyedProjection<K, V>, select: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<Entries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
53
- declare function createKeyedFlatMap<K extends string, V, const D extends object, O extends string, T>(source: KeyedProjection<K, V>, dependencies: D & KeyedDependencies<NoInfer<K>, NoInfer<V>, D>, select: (value: NoInfer<V>, key: NoInfer<K>, dependencies: KeyedDependencyValues<D>) => Synchronous<Entries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
59
+ declare function createKeyedFlatMap<K extends string, V, O extends string, T>(source: KeyedProjection<K, V>, select: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<KeyedEntries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
60
+ declare function createKeyedFlatMap<K extends string, V, const D extends object, O extends string, T>(source: KeyedProjection<K, V>, dependencies: D & KeyedDependencies<NoInfer<K>, NoInfer<V>, D>, select: (value: NoInfer<V>, key: NoInfer<K>, dependencies: KeyedDependencyValues<D>) => Synchronous<KeyedEntries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
54
61
  //#endregion
55
62
  //#region core/src/projection/derive.d.ts
56
- type ProjectionDependencies = Readonly<Record<string, Projection<unknown>>>;
57
- type ProjectionValues<D extends ProjectionDependencies> = { readonly [K in keyof D]: D[K] extends Projection<infer T> ? T : never };
58
63
  type Equality<T> = (previous: T, next: T) => boolean;
59
64
  declare function createValueDerive<const D extends ProjectionDependencies, T>(dependencies: D, compute: (values: ProjectionValues<D>) => Synchronous<T>, equality?: Equality<T>): Projection<T>;
60
65
  declare const derive: typeof createValueDerive & {
@@ -67,6 +72,7 @@ declare const derive: typeof createValueDerive & {
67
72
  entries: <K extends string, V>(source: KeyedProjection<K, V>) => Projection<readonly (readonly [K, V])[]>;
68
73
  get: <K extends string, V>(source: KeyedProjection<K, V>, key: Projection<NoInfer<K> | undefined>, equality?: (previous: V | undefined, next: V | undefined) => boolean) => Projection<V | undefined>;
69
74
  from: typeof createKeyedFrom;
75
+ fromEntries: typeof createKeyedFromEntries;
70
76
  merge: typeof createKeyedMerge;
71
77
  groupBy: {
72
78
  <K extends string, V, G extends string>(source: KeyedProjection<K, V>, selector: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<G | readonly G[]>): KeyedProjection<G, readonly K[]>;
@@ -127,5 +133,4 @@ declare const createProjectionRuntime: (options?: {
127
133
  readonly onError?: (error: ProjectionError) => void;
128
134
  }) => ProjectionRuntime;
129
135
  //#endregion
130
- export { type Change, type ChangeSet, type CollectionImpact, type CollectionInput, type CollectionInputDraft, type CommitSource, type DocumentAddress, type DocumentAnchor, type DocumentCommit, type DocumentDiagnostic, DocumentDisposedError, type DocumentImpact, type DocumentListConfig, type DocumentProblem, DocumentReentrancyError, type DocumentRuntime, type DocumentSelector, type DocumentTreeNode, type DocumentTreeValue, type Draft, type ExternalCollectionEvent, type ExternalCollectionRead, type ExternalCollectionSource, type ExternalValueEvent, type ExternalValueSource, type HistoryState, type Infer, type Input, type KeyedProjection, type LocalHistory, type MemberChange, type MutationIssue, type MutationIssueCode, type ObjectSchema, type ObserverError, type OperationResult, ParseError, type ParseIssue, type PathValueOf, type Projection, ProjectionDisposedError, ProjectionError, type ProjectionItems, type ProjectionRuntime, type ProjectionScope, type Read, type Readable, type ReadonlyDocument, type ReadonlyValue, type Schema, type SchemaPath, TransactionRejected, type TransactionResult, type Unsubscribe, type Validator, type ValueTransition, createDocument, createProjectionRuntime, derive, field, input, list, map, object, observe, optional, parse, read, replace, select, snapshot, table, tree, variant };
131
- //# sourceMappingURL=index.d.cts.map
136
+ export { type Change, type ChangeSet, type CollectionImpact, type CollectionInput, type CollectionInputDraft, type CommitSource, type DocumentAddress, type DocumentAnchor, type DocumentCommit, type DocumentDiagnostic, DocumentDisposedError, type DocumentImpact, type DocumentListConfig, type DocumentProblem, DocumentReentrancyError, type DocumentRuntime, type DocumentSelector, type DocumentTreeNode, type DocumentTreeValue, type Draft, type ExternalCollectionEvent, type ExternalCollectionRead, type ExternalCollectionSource, type ExternalValueEvent, type ExternalValueSource, type HistoryState, type Infer, type Input, type KeyedProjection, type LocalHistory, type MemberChange, type MutationIssue, type MutationIssueCode, type ObjectSchema, type ObserverError, type OperationResult, ParseError, type ParseIssue, type PathValueOf, type Projection, ProjectionDisposedError, ProjectionError, type ProjectionItems, type ProjectionRuntime, type ProjectionScope, type Read, type Readable, type ReadonlyDocument, type ReadonlyValue, type Schema, type SchemaPath, TransactionRejected, type TransactionResult, type Unsubscribe, type Validator, type ValueTransition, createDocument, createProjectionRuntime, derive, field, input, list, map, object, observe, optional, parse, read, replace, select, snapshot, table, tree, variant };
package/dist/index.d.ts CHANGED
@@ -29,10 +29,18 @@ declare function observe<T>(readable: Readable<T>): Projection<T>;
29
29
  declare function observe<S extends ObjectSchema<object>, P extends CollectionPath>(document: ReadonlyDocument<S>, selector: (path: SchemaPath<S>) => P): KeyedProjection<CollectionId<P>, ReadonlyValue<CollectionEntry<P>>>;
30
30
  declare function observe<S extends ObjectSchema<object>, P>(document: ReadonlyDocument<S>, selector: (path: SchemaPath<S>) => P): Projection<PathValueOf<P>>;
31
31
  //#endregion
32
+ //#region core/src/projection/dependency.d.ts
33
+ type ProjectionDependencies = Readonly<Record<string, Projection<unknown>>> & Partial<Record<keyof Projection<unknown>, never>>;
34
+ type ProjectionValues<D extends ProjectionDependencies> = { readonly [K in keyof D]: D[K] extends Projection<infer T> ? T : never };
35
+ //#endregion
36
+ //#region core/src/projection/keyed/entries.d.ts
37
+ type KeyedEntries<K extends string, V> = readonly (readonly [K, V])[];
38
+ //#endregion
32
39
  //#region core/src/projection/keyed/composition.d.ts
33
40
  type Equality$2<T> = (previous: T, next: T) => boolean;
34
41
  declare function createKeyedFrom<K extends string, V>(source: Projection<readonly V[]>, keyOf: (value: NoInfer<V>) => Synchronous<K>, equality?: Equality$2<V>): KeyedProjection<K, V>;
35
42
  declare function createKeyedFrom<K extends string, V>(source: readonly V[], keyOf: (value: NoInfer<V>) => Synchronous<K>, equality?: Equality$2<V>): KeyedProjection<K, V>;
43
+ declare function createKeyedFromEntries<const D extends ProjectionDependencies, K extends string, V>(dependencies: D, compute: (values: ProjectionValues<D>) => Synchronous<KeyedEntries<K, V>>, equality?: Equality$2<NoInfer<V>>): KeyedProjection<K, V>;
36
44
  declare function createKeyedMerge<K extends string, V>(sources: readonly KeyedProjection<K, V>[], options: {
37
45
  readonly conflict: 'error' | 'first' | 'last';
38
46
  readonly equality?: Equality$2<V>;
@@ -47,14 +55,11 @@ declare function createKeyedMerge<K extends string, V>(sources: readonly KeyedPr
47
55
  }): KeyedProjection<K, V>;
48
56
  //#endregion
49
57
  //#region core/src/projection/keyed/flat-map.d.ts
50
- type Entries<K extends string, V> = readonly (readonly [K, V])[];
51
58
  type Equality$1<V> = (previous: V, next: V) => boolean;
52
- declare function createKeyedFlatMap<K extends string, V, O extends string, T>(source: KeyedProjection<K, V>, select: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<Entries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
53
- declare function createKeyedFlatMap<K extends string, V, const D extends object, O extends string, T>(source: KeyedProjection<K, V>, dependencies: D & KeyedDependencies<NoInfer<K>, NoInfer<V>, D>, select: (value: NoInfer<V>, key: NoInfer<K>, dependencies: KeyedDependencyValues<D>) => Synchronous<Entries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
59
+ declare function createKeyedFlatMap<K extends string, V, O extends string, T>(source: KeyedProjection<K, V>, select: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<KeyedEntries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
60
+ declare function createKeyedFlatMap<K extends string, V, const D extends object, O extends string, T>(source: KeyedProjection<K, V>, dependencies: D & KeyedDependencies<NoInfer<K>, NoInfer<V>, D>, select: (value: NoInfer<V>, key: NoInfer<K>, dependencies: KeyedDependencyValues<D>) => Synchronous<KeyedEntries<O, T>>, equality?: Equality$1<T>): KeyedProjection<O, T>;
54
61
  //#endregion
55
62
  //#region core/src/projection/derive.d.ts
56
- type ProjectionDependencies = Readonly<Record<string, Projection<unknown>>>;
57
- type ProjectionValues<D extends ProjectionDependencies> = { readonly [K in keyof D]: D[K] extends Projection<infer T> ? T : never };
58
63
  type Equality<T> = (previous: T, next: T) => boolean;
59
64
  declare function createValueDerive<const D extends ProjectionDependencies, T>(dependencies: D, compute: (values: ProjectionValues<D>) => Synchronous<T>, equality?: Equality<T>): Projection<T>;
60
65
  declare const derive: typeof createValueDerive & {
@@ -67,6 +72,7 @@ declare const derive: typeof createValueDerive & {
67
72
  entries: <K extends string, V>(source: KeyedProjection<K, V>) => Projection<readonly (readonly [K, V])[]>;
68
73
  get: <K extends string, V>(source: KeyedProjection<K, V>, key: Projection<NoInfer<K> | undefined>, equality?: (previous: V | undefined, next: V | undefined) => boolean) => Projection<V | undefined>;
69
74
  from: typeof createKeyedFrom;
75
+ fromEntries: typeof createKeyedFromEntries;
70
76
  merge: typeof createKeyedMerge;
71
77
  groupBy: {
72
78
  <K extends string, V, G extends string>(source: KeyedProjection<K, V>, selector: (value: NoInfer<V>, key: NoInfer<K>) => Synchronous<G | readonly G[]>): KeyedProjection<G, readonly K[]>;
@@ -127,5 +133,4 @@ declare const createProjectionRuntime: (options?: {
127
133
  readonly onError?: (error: ProjectionError) => void;
128
134
  }) => ProjectionRuntime;
129
135
  //#endregion
130
- export { type Change, type ChangeSet, type CollectionImpact, type CollectionInput, type CollectionInputDraft, type CommitSource, type DocumentAddress, type DocumentAnchor, type DocumentCommit, type DocumentDiagnostic, DocumentDisposedError, type DocumentImpact, type DocumentListConfig, type DocumentProblem, DocumentReentrancyError, type DocumentRuntime, type DocumentSelector, type DocumentTreeNode, type DocumentTreeValue, type Draft, type ExternalCollectionEvent, type ExternalCollectionRead, type ExternalCollectionSource, type ExternalValueEvent, type ExternalValueSource, type HistoryState, type Infer, type Input, type KeyedProjection, type LocalHistory, type MemberChange, type MutationIssue, type MutationIssueCode, type ObjectSchema, type ObserverError, type OperationResult, ParseError, type ParseIssue, type PathValueOf, type Projection, ProjectionDisposedError, ProjectionError, type ProjectionItems, type ProjectionRuntime, type ProjectionScope, type Read, type Readable, type ReadonlyDocument, type ReadonlyValue, type Schema, type SchemaPath, TransactionRejected, type TransactionResult, type Unsubscribe, type Validator, type ValueTransition, createDocument, createProjectionRuntime, derive, field, input, list, map, object, observe, optional, parse, read, replace, select, snapshot, table, tree, variant };
131
- //# sourceMappingURL=index.d.ts.map
136
+ export { type Change, type ChangeSet, type CollectionImpact, type CollectionInput, type CollectionInputDraft, type CommitSource, type DocumentAddress, type DocumentAnchor, type DocumentCommit, type DocumentDiagnostic, DocumentDisposedError, type DocumentImpact, type DocumentListConfig, type DocumentProblem, DocumentReentrancyError, type DocumentRuntime, type DocumentSelector, type DocumentTreeNode, type DocumentTreeValue, type Draft, type ExternalCollectionEvent, type ExternalCollectionRead, type ExternalCollectionSource, type ExternalValueEvent, type ExternalValueSource, type HistoryState, type Infer, type Input, type KeyedProjection, type LocalHistory, type MemberChange, type MutationIssue, type MutationIssueCode, type ObjectSchema, type ObserverError, type OperationResult, ParseError, type ParseIssue, type PathValueOf, type Projection, ProjectionDisposedError, ProjectionError, type ProjectionItems, type ProjectionRuntime, type ProjectionScope, type Read, type Readable, type ReadonlyDocument, type ReadonlyValue, type Schema, type SchemaPath, TransactionRejected, type TransactionResult, type Unsubscribe, type Validator, type ValueTransition, createDocument, createProjectionRuntime, derive, field, input, list, map, object, observe, optional, parse, read, replace, select, snapshot, table, tree, variant };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as ownProjections, C as snapshotDependencyValue, D as defineProcessor, E as snapshotCollectionView, M as projectionRef, N as profile, O as defineSource, S as compileProjectionDependencies, T as mapRead, _ as assertSynchronous, a as collectionChangeTouchesKey, b as ProjectionError, c as assertKeyedProjection, d as outputKind, f as createKeyRelation, g as assertScope, h as snapshotArray, i as collectionChangeIntersects, j as producerOf, k as isProjection, l as compileKeyedDependencies, m as sameArray, n as keyedAbsent, o as collectionHasStructuralChange, p as iterableMatchesArray, s as createCollectionChange, t as createKeyedTransform, u as createKeyedDependencyRuntime, v as createScheduler, w as collectionView, x as collectKeyedInvalidation, y as ProjectionDisposedError } from "./transform-RghG_Qxs.js";
1
+ import { A as ownProjections, C as snapshotProjectionValues, D as defineProcessor, E as snapshotCollectionView, M as projectionRef, N as profile, O as defineSource, S as compileProjectionDependencies, T as mapRead, _ as assertSynchronous, a as collectionChangeTouchesKey, b as ProjectionError, c as assertKeyedProjection, d as outputKind, f as createKeyRelation, g as assertScope, h as snapshotArray, i as collectionChangeIntersects, j as producerOf, k as isProjection, l as compileKeyedDependencies, m as sameArray, n as keyedAbsent, o as collectionHasStructuralChange, p as iterableMatchesArray, s as createCollectionChange, t as createKeyedTransform, u as createKeyedDependencyRuntime, v as createScheduler, w as collectionView, x as collectKeyedInvalidation, y as ProjectionDisposedError } from "./transform-3mj0eStL.js";
2
2
  import { n as isPlainObject, r as isRecord, t as installOwn } from "./record-B2yRhYsc.js";
3
3
  import { c as AddressIndex, d as invalidValue, f as children, g as validate, h as parent, i as contextOf, l as MutationRejected, m as is, o as decodeChanges, p as contains$1, r as bindContext, s as sealChanges, t as assertRuntimeWritable, u as fail } from "./driver-B7RR-VfX.js";
4
4
  //#region core/src/schema/model.ts
@@ -2774,6 +2774,12 @@ const isExternalSource = (source) => {
2774
2774
  return (candidate.kind === "value" || candidate.kind === "collection") && typeof candidate.current === "function" && typeof candidate.revision === "function" && typeof candidate.subscribe === "function";
2775
2775
  };
2776
2776
  //#endregion
2777
+ //#region core/src/projection/keyed/entries.ts
2778
+ /** Shared entry boundary; membership and duplicate policy belong to each operation. */
2779
+ function assertKeyedEntry(entry, name) {
2780
+ if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string") throw new TypeError(`${name} entries must be [string key, value] tuples.`);
2781
+ }
2782
+ //#endregion
2777
2783
  //#region core/src/projection/keyed/flat-map.ts
2778
2784
  function createKeyedFlatMap(source, dependenciesOrSelect, selectOrEquality, maybeEquality) {
2779
2785
  const name = "derive.keyed.flatMap";
@@ -2820,7 +2826,7 @@ function createKeyedFlatMap(source, dependenciesOrSelect, selectOrEquality, mayb
2820
2826
  if (!Array.isArray(entries)) throw new TypeError(`${name} selector must return an array of entries.`);
2821
2827
  const keys = [];
2822
2828
  for (const entry of entries) {
2823
- if (!Array.isArray(entry) || entry.length !== 2 || typeof entry[0] !== "string") throw new TypeError(`${name} entries must be [string key, value] tuples.`);
2829
+ assertKeyedEntry(entry, name);
2824
2830
  const [key, child] = entry;
2825
2831
  const owner = ownerByOutput.get(key);
2826
2832
  if (proposals.has(key) || owner !== void 0 && !replaced.has(owner)) throw new TypeError(`${name} duplicate key ${JSON.stringify(key)}.`);
@@ -2907,6 +2913,25 @@ const assertCollectionSources = (sources, expected) => {
2907
2913
  if (sources.length !== expected) throw new Error("derive.keyed.merge resolved an invalid dependency count.");
2908
2914
  for (const source of sources) if (source.kind !== "collection") throw new Error("derive.keyed.merge requires collection inputs.");
2909
2915
  };
2916
+ /** Complete ordered result reconciliation, without retaining a second member/value cache. */
2917
+ const stageKeyedSnapshot = (values, output, keyOf, valueOf, name) => {
2918
+ const seen = /* @__PURE__ */ new Set();
2919
+ const order = new Array(values.length);
2920
+ const previous = output.previous.ids();
2921
+ profile.collectionView.idsScanned(values.length + previous.length);
2922
+ for (let index = 0; index < values.length; index++) {
2923
+ const value = values[index];
2924
+ const key = keyOf(value);
2925
+ assertSynchronous(key);
2926
+ if (typeof key !== "string") throw new TypeError(`${name} key selector must return a string.`);
2927
+ if (seen.has(key)) throw new TypeError(`${name} duplicate key ${JSON.stringify(key)}.`);
2928
+ seen.add(key);
2929
+ order[index] = key;
2930
+ output.output.set(key, valueOf(value));
2931
+ }
2932
+ for (const key of previous) if (!seen.has(key)) output.output.remove(key);
2933
+ output.output.order(order);
2934
+ };
2910
2935
  function createKeyedFrom(source, keyOf, equality) {
2911
2936
  if (typeof keyOf !== "function") throw new TypeError("derive.keyed.from requires a key selector.");
2912
2937
  const outputEquality = assertEquality(equality, "derive.keyed.from");
@@ -2936,25 +2961,38 @@ function createKeyedFrom(source, keyOf, equality) {
2936
2961
  values = scalar.value;
2937
2962
  }
2938
2963
  if (!values) throw new Error("derive.keyed.from has no source values.");
2939
- const seen = /* @__PURE__ */ new Set();
2940
- const order = new Array(values.length);
2941
- for (let index = 0; index < values.length; index++) {
2942
- const value = values[index];
2943
- const key = keyOf(value);
2944
- assertSynchronous(key);
2945
- if (typeof key !== "string") throw new TypeError("derive.keyed.from key selector must return a string.");
2946
- if (seen.has(key)) throw new TypeError(`derive.keyed.from duplicate key ${JSON.stringify(key)}.`);
2947
- seen.add(key);
2948
- order[index] = key;
2949
- output.output.set(key, value);
2950
- }
2951
- for (const previousKey of output.previous.ids()) if (!seen.has(previousKey)) output.output.remove(previousKey);
2952
- output.output.order(order);
2964
+ stageKeyedSnapshot(values, output, keyOf, (value) => value, "derive.keyed.from");
2953
2965
  } }),
2954
2966
  name: "derive.keyed.from"
2955
2967
  });
2956
2968
  return projection;
2957
2969
  }
2970
+ function createKeyedFromEntries(dependencies, compute, equality) {
2971
+ const name = "derive.keyed.fromEntries";
2972
+ const compiled = compileProjectionDependencies(dependencies, name);
2973
+ if (typeof compute !== "function") throw new TypeError(`${name} requires a compute callback.`);
2974
+ const outputEquality = assertEquality(equality, name);
2975
+ const [projection] = defineProcessor({
2976
+ dependencies: compiled.projections,
2977
+ outputs: [{
2978
+ kind: "collection",
2979
+ equality: outputEquality
2980
+ }],
2981
+ name,
2982
+ create: () => ({ evaluate: (evaluation) => {
2983
+ const output = evaluation.outputs[0];
2984
+ if (output.kind !== "collection") throw new Error(`${name} requires a collection output.`);
2985
+ const entries = compute(snapshotProjectionValues(compiled.names, evaluation.sources));
2986
+ assertSynchronous(entries);
2987
+ if (!Array.isArray(entries)) throw new TypeError(`${name} compute must return an array of entries.`);
2988
+ stageKeyedSnapshot(entries, output, (entry) => {
2989
+ assertKeyedEntry(entry, name);
2990
+ return entry[0];
2991
+ }, (entry) => entry[1], name);
2992
+ } })
2993
+ });
2994
+ return projection;
2995
+ }
2958
2996
  function createKeyedMerge(sources, options) {
2959
2997
  if (!Array.isArray(sources)) throw new TypeError("derive.keyed.merge sources must be an array of keyed projections.");
2960
2998
  const capturedSources = snapshotArray(sources);
@@ -3583,6 +3621,7 @@ const keyedDerive = Object.assign(createKeyedDerive, {
3583
3621
  entries: createKeyedEntries,
3584
3622
  get: createKeyedGet,
3585
3623
  from: createKeyedFrom,
3624
+ fromEntries: createKeyedFromEntries,
3586
3625
  merge: createKeyedMerge,
3587
3626
  groupBy: createKeyedGroupBy,
3588
3627
  flatMap: createKeyedFlatMap,
@@ -3606,9 +3645,7 @@ function createValueDerive(dependencies, compute, equality = Object.is) {
3606
3645
  create: () => ({ evaluate: (evaluation) => {
3607
3646
  const output = evaluation.outputs[0];
3608
3647
  if (output.kind !== "value") throw new Error("derive requires a value output.");
3609
- const values = Object.create(null);
3610
- for (let index = 0; index < names.length; index++) values[names[index]] = snapshotDependencyValue(evaluation.sources[index]);
3611
- const next = compute(Object.freeze(values));
3648
+ const next = compute(snapshotProjectionValues(names, evaluation.sources));
3612
3649
  assertSynchronous(next);
3613
3650
  output.output.set(next);
3614
3651
  } })
@@ -6406,5 +6443,3 @@ const createProjectionRuntime = (options) => {
6406
6443
  };
6407
6444
  //#endregion
6408
6445
  export { DocumentDisposedError, DocumentReentrancyError, ParseError, ProjectionDisposedError, ProjectionError, TransactionRejected, createDocument, createProjectionRuntime, derive, field, input, list, map, object, observe, optional, parse, read, replace, select, snapshot, table, tree, variant };
6409
-
6410
- //# sourceMappingURL=index.js.map
@@ -514,5 +514,3 @@ const attachLocalSync = async (input) => {
514
514
  exports.LocalSyncError = LocalSyncError;
515
515
  exports.attachLocalSync = attachLocalSync;
516
516
  exports.defaultJsonChangeLimits = defaultJsonChangeLimits;
517
-
518
- //# sourceMappingURL=local-sync.cjs.map
@@ -58,5 +58,4 @@ type AttachLocalSyncOptions<TSchema extends ObjectSchema<object>> = {
58
58
  //#region core/src/local-sync/session.d.ts
59
59
  declare const attachLocalSync: <TSchema extends ObjectSchema<object>>(input: AttachLocalSyncOptions<TSchema>) => Promise<LocalSync>;
60
60
  //#endregion
61
- export { type AttachLocalSyncOptions, type JsonChangeLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncError, type LocalSyncErrorCode, type LocalSyncState, attachLocalSync, defaultJsonChangeLimits };
62
- //# sourceMappingURL=local-sync.d.cts.map
61
+ export { type AttachLocalSyncOptions, type JsonChangeLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncError, type LocalSyncErrorCode, type LocalSyncState, attachLocalSync, defaultJsonChangeLimits };
@@ -58,5 +58,4 @@ type AttachLocalSyncOptions<TSchema extends ObjectSchema<object>> = {
58
58
  //#region core/src/local-sync/session.d.ts
59
59
  declare const attachLocalSync: <TSchema extends ObjectSchema<object>>(input: AttachLocalSyncOptions<TSchema>) => Promise<LocalSync>;
60
60
  //#endregion
61
- export { type AttachLocalSyncOptions, type JsonChangeLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncError, type LocalSyncErrorCode, type LocalSyncState, attachLocalSync, defaultJsonChangeLimits };
62
- //# sourceMappingURL=local-sync.d.ts.map
61
+ export { type AttachLocalSyncOptions, type JsonChangeLimits, type JsonPrimitive, type JsonValue, type LocalSync, LocalSyncError, type LocalSyncErrorCode, type LocalSyncState, attachLocalSync, defaultJsonChangeLimits };
@@ -511,5 +511,3 @@ const attachLocalSync = async (input) => {
511
511
  };
512
512
  //#endregion
513
513
  export { LocalSyncError, attachLocalSync, defaultJsonChangeLimits };
514
-
515
- //# sourceMappingURL=local-sync.js.map
package/dist/react.cjs CHANGED
@@ -57,5 +57,3 @@ exports.useHistory = useHistory;
57
57
  exports.useInput = useInput;
58
58
  exports.useProjection = useProjection;
59
59
  exports.useReadable = useReadable;
60
-
61
- //# sourceMappingURL=react.cjs.map
package/dist/react.d.cts CHANGED
@@ -14,5 +14,4 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
14
14
  redo(): OperationResult<TCommit>;
15
15
  };
16
16
  //#endregion
17
- export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
18
- //# sourceMappingURL=react.d.cts.map
17
+ export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
package/dist/react.d.ts CHANGED
@@ -14,5 +14,4 @@ declare function useHistory<TCommit>(history: LocalHistory<TCommit>): HistorySta
14
14
  redo(): OperationResult<TCommit>;
15
15
  };
16
16
  //#endregion
17
- export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
18
- //# sourceMappingURL=react.d.ts.map
17
+ export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
package/dist/react.js CHANGED
@@ -51,5 +51,3 @@ function useHistory(history) {
51
51
  }
52
52
  //#endregion
53
53
  export { ProjectionProvider, useDocumentSelector, useHistory, useInput, useProjection, useReadable };
54
-
55
- //# sourceMappingURL=react.js.map
@@ -24,5 +24,3 @@ const installOwn = (parent, key, present, value) => {
24
24
  };
25
25
  //#endregion
26
26
  export { isPlainObject as n, isRecord as r, installOwn as t };
27
-
28
- //# sourceMappingURL=record-B2yRhYsc.js.map
@@ -41,5 +41,3 @@ Object.defineProperty(exports, "isRecord", {
41
41
  return isRecord;
42
42
  }
43
43
  });
44
-
45
- //# sourceMappingURL=record-ChYUi8PP.cjs.map
@@ -185,6 +185,12 @@ const readNamedDependencyEntries = (dependencies, label) => {
185
185
  };
186
186
  /** Creates the durable dependency value exposed to pure derive callbacks. */
187
187
  const snapshotDependencyValue = (source) => source.kind === "value" ? source.value : snapshotCollectionView(source.read);
188
+ /** Builds the same readonly named value boundary for scalar and keyed pure computations. */
189
+ const snapshotProjectionValues = (names, sources) => {
190
+ const values = Object.create(null);
191
+ for (let index = 0; index < names.length; index++) values[names[index]] = snapshotDependencyValue(sources[index]);
192
+ return Object.freeze(values);
193
+ };
188
194
  /** Compiles the shared named Projection dependency declaration contract. */
189
195
  const compileProjectionDependencies = (dependencies, label) => {
190
196
  const names = [];
@@ -1083,6 +1089,4 @@ const createKeyedTransform = (definition) => {
1083
1089
  return projection;
1084
1090
  };
1085
1091
  //#endregion
1086
- export { ownProjections as A, snapshotDependencyValue as C, defineProcessor as D, snapshotCollectionView as E, projectionRef as M, profile as N, defineSource as O, compileProjectionDependencies as S, mapRead as T, assertSynchronous as _, collectionChangeTouchesKey as a, ProjectionError as b, assertKeyedProjection as c, outputKind as d, createKeyRelation as f, assertScope as g, snapshotArray as h, collectionChangeIntersects as i, producerOf as j, isProjection as k, compileKeyedDependencies as l, sameArray as m, keyedAbsent as n, collectionHasStructuralChange as o, iterableMatchesArray as p, collectionChange as r, createCollectionChange as s, createKeyedTransform as t, createKeyedDependencyRuntime as u, createScheduler as v, collectionView as w, collectKeyedInvalidation as x, ProjectionDisposedError as y };
1087
-
1088
- //# sourceMappingURL=transform-RghG_Qxs.js.map
1092
+ export { ownProjections as A, snapshotProjectionValues as C, defineProcessor as D, snapshotCollectionView as E, projectionRef as M, profile as N, defineSource as O, compileProjectionDependencies as S, mapRead as T, assertSynchronous as _, collectionChangeTouchesKey as a, ProjectionError as b, assertKeyedProjection as c, outputKind as d, createKeyRelation as f, assertScope as g, snapshotArray as h, collectionChangeIntersects as i, producerOf as j, isProjection as k, compileKeyedDependencies as l, sameArray as m, keyedAbsent as n, collectionHasStructuralChange as o, iterableMatchesArray as p, collectionChange as r, createCollectionChange as s, createKeyedTransform as t, createKeyedDependencyRuntime as u, createScheduler as v, collectionView as w, collectKeyedInvalidation as x, ProjectionDisposedError as y };