@adobe/data 0.9.82 → 0.9.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/ecs/archetype/archetype.d.ts +23 -0
  2. package/dist/ecs/archetype/archetype.js.map +1 -1
  3. package/dist/ecs/database/create-plugin.d.ts +2 -1
  4. package/dist/ecs/database/create-plugin.js.map +1 -1
  5. package/dist/ecs/database/database.d.ts +6 -5
  6. package/dist/ecs/database/database.js.map +1 -1
  7. package/dist/ecs/database/database.partition.test.d.ts +1 -0
  8. package/dist/ecs/database/database.partition.test.js +45 -0
  9. package/dist/ecs/database/database.partition.test.js.map +1 -0
  10. package/dist/ecs/database/database.partition.type-test.d.ts +1 -0
  11. package/dist/ecs/database/database.partition.type-test.js +41 -0
  12. package/dist/ecs/database/database.partition.type-test.js.map +1 -0
  13. package/dist/ecs/database/deep-extends-chain.type-test.d.ts +255 -255
  14. package/dist/ecs/database/index.d.ts +0 -1
  15. package/dist/ecs/database/index.js +0 -1
  16. package/dist/ecs/database/index.js.map +1 -1
  17. package/dist/ecs/database/transactional-store/transactional-store.d.ts +6 -5
  18. package/dist/ecs/store/core/core.d.ts +33 -8
  19. package/dist/ecs/store/core/create-core.d.ts +12 -2
  20. package/dist/ecs/store/core/create-core.js +141 -22
  21. package/dist/ecs/store/core/create-core.js.map +1 -1
  22. package/dist/ecs/store/core/create-core.partition.test.d.ts +1 -0
  23. package/dist/ecs/store/core/create-core.partition.test.js +229 -0
  24. package/dist/ecs/store/core/create-core.partition.test.js.map +1 -0
  25. package/dist/ecs/store/core/select-entities.js +87 -21
  26. package/dist/ecs/store/core/select-entities.js.map +1 -1
  27. package/dist/ecs/store/core/select-entities.partition.test.d.ts +1 -0
  28. package/dist/ecs/store/core/select-entities.partition.test.js +93 -0
  29. package/dist/ecs/store/core/select-entities.partition.test.js.map +1 -0
  30. package/dist/ecs/store/entity-select-options.d.ts +5 -1
  31. package/dist/ecs/store/partition.d.ts +63 -0
  32. package/dist/ecs/store/partition.js +3 -0
  33. package/dist/ecs/store/partition.js.map +1 -0
  34. package/dist/ecs/store/partition.type-test.d.ts +1 -0
  35. package/dist/ecs/store/partition.type-test.js +15 -0
  36. package/dist/ecs/store/partition.type-test.js.map +1 -0
  37. package/dist/ecs/store/public/create-store.d.ts +3 -1
  38. package/dist/ecs/store/public/create-store.js +19 -50
  39. package/dist/ecs/store/public/create-store.js.map +1 -1
  40. package/dist/ecs/store/public/create-store.partition.test.d.ts +1 -0
  41. package/dist/ecs/store/public/create-store.partition.test.js +111 -0
  42. package/dist/ecs/store/public/create-store.partition.test.js.map +1 -0
  43. package/dist/ecs/store/public/create-store.partition.type-test.d.ts +1 -0
  44. package/dist/ecs/store/public/create-store.partition.type-test.js +61 -0
  45. package/dist/ecs/store/public/create-store.partition.type-test.js.map +1 -0
  46. package/dist/ecs/store/store.d.ts +15 -10
  47. package/dist/ecs/store/store.js.map +1 -1
  48. package/dist/ecs/store/transaction-functions.d.ts +3 -3
  49. package/dist/schema/schema.d.ts +1 -0
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/package.json +1 -1
  52. package/references/data-lit/package.json +1 -1
  53. package/references/data-lit-tictactoe/package.json +1 -1
  54. package/references/data-react/package.json +1 -1
  55. package/references/data-react-hello/package.json +1 -1
  56. package/references/data-react-pixie/package.json +1 -1
@@ -0,0 +1,229 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { describe, it, expect } from "vitest";
3
+ import { createCore } from "./create-core.js";
4
+ import { constBufferType } from "../../../typed-buffer/create-const-buffer.js";
5
+ const positionSchema = {
6
+ type: "object",
7
+ properties: { x: { type: "number" }, y: { type: "number" } },
8
+ };
9
+ // A partition component: every distinct `cell` value gets its own archetype.
10
+ const cellSchema = { type: "integer", partition: true };
11
+ const makeCore = () => createCore({ cell: cellSchema, position: positionSchema });
12
+ describe("partition components", () => {
13
+ describe("ensureArchetype return discrimination", () => {
14
+ it("returns a Router (no dense view) when a partition key is present without a value", () => {
15
+ const core = makeCore();
16
+ const router = core.ensureArchetype(["id", "cell", "position"]);
17
+ expect(typeof router.insert).toBe("function");
18
+ // A family has no single dense column view. `in` (not a cast) — the
19
+ // Router type has no such members, so probe presence structurally.
20
+ expect("columns" in router).toBe(false);
21
+ expect("rowCount" in router).toBe(false);
22
+ });
23
+ it("returns a concrete Archetype when the partition value is supplied", () => {
24
+ const core = makeCore();
25
+ const arch = core.ensureArchetype(["id", "cell", "position"], { cell: 7 });
26
+ expect(arch.columns).toBeDefined();
27
+ expect(arch.rowCount).toBe(0);
28
+ });
29
+ it("returns a concrete Archetype (not a Router) when no partition component is in the set", () => {
30
+ const core = makeCore();
31
+ const arch = core.ensureArchetype(["id", "position"]);
32
+ expect(arch.columns).toBeDefined();
33
+ expect(typeof arch.insert).toBe("function");
34
+ });
35
+ });
36
+ describe("routing insert", () => {
37
+ it("routes rows with distinct partition values into distinct archetypes", () => {
38
+ const core = makeCore();
39
+ const router = core.ensureArchetype(["id", "cell", "position"]);
40
+ const a = router.insert({ cell: 1, position: { x: 1, y: 1 } });
41
+ const b = router.insert({ cell: 2, position: { x: 2, y: 2 } });
42
+ const c = router.insert({ cell: 1, position: { x: 3, y: 3 } });
43
+ const cell1 = core.ensureArchetype(["id", "cell", "position"], { cell: 1 });
44
+ const cell2 = core.ensureArchetype(["id", "cell", "position"], { cell: 2 });
45
+ // Same value → same archetype; different value → different archetype.
46
+ expect(cell1).not.toBe(cell2);
47
+ expect(cell1.rowCount).toBe(2); // a and c
48
+ expect(cell2.rowCount).toBe(1); // b
49
+ expect(core.locate(a).archetype).toBe(cell1);
50
+ expect(core.locate(c).archetype).toBe(cell1);
51
+ expect(core.locate(b).archetype).toBe(cell2);
52
+ });
53
+ it("stores the partition value as a const column (zero per-row bytes)", () => {
54
+ const core = makeCore();
55
+ core.ensureArchetype(["id", "cell", "position"]).insert({ cell: 42, position: { x: 0, y: 0 } });
56
+ const arch = core.ensureArchetype(["id", "cell", "position"], { cell: 42 });
57
+ expect(arch.columns.cell.type).toBe(constBufferType);
58
+ expect(arch.columns.cell.typedArrayElementSizeInBytes).toBe(0);
59
+ expect(arch.columns.cell.get(0)).toBe(42);
60
+ });
61
+ it("reads the routed partition value back through the entity", () => {
62
+ const core = makeCore();
63
+ const router = core.ensureArchetype(["id", "cell", "position"]);
64
+ const e = router.insert({ cell: 9, position: { x: 5, y: 6 } });
65
+ expect(core.get(e, "cell")).toBe(9);
66
+ expect(core.read(e)).toMatchObject({ cell: 9, position: { x: 5, y: 6 } });
67
+ });
68
+ });
69
+ describe("queryArchetypes", () => {
70
+ it("returns every value-child of a partitioned component set", () => {
71
+ const core = makeCore();
72
+ const router = core.ensureArchetype(["id", "cell", "position"]);
73
+ router.insert({ cell: 1, position: { x: 0, y: 0 } });
74
+ router.insert({ cell: 2, position: { x: 0, y: 0 } });
75
+ router.insert({ cell: 3, position: { x: 0, y: 0 } });
76
+ const all = core.queryArchetypes(["cell", "position"]);
77
+ expect(all.length).toBe(3);
78
+ });
79
+ it("filters to a single value-child with a partition `where` (broad phase)", () => {
80
+ const core = makeCore();
81
+ const router = core.ensureArchetype(["id", "cell", "position"]);
82
+ router.insert({ cell: 1, position: { x: 0, y: 0 } });
83
+ router.insert({ cell: 2, position: { x: 0, y: 0 } });
84
+ router.insert({ cell: 2, position: { x: 0, y: 0 } });
85
+ const cell2 = core.queryArchetypes(["cell", "position"], { where: { cell: 2 } });
86
+ expect(cell2.length).toBe(1);
87
+ expect(cell2[0].columns.cell.get(0)).toBe(2);
88
+ expect(cell2[0].rowCount).toBe(2);
89
+ const none = core.queryArchetypes(["cell", "position"], { where: { cell: 99 } });
90
+ expect(none.length).toBe(0);
91
+ });
92
+ });
93
+ describe("update migration", () => {
94
+ it("migrates an entity to a new value-child when its partition value changes", () => {
95
+ const core = makeCore();
96
+ const router = core.ensureArchetype(["id", "cell", "position"]);
97
+ const e = router.insert({ cell: 1, position: { x: 7, y: 8 } });
98
+ const cell1 = core.ensureArchetype(["id", "cell", "position"], { cell: 1 });
99
+ const cell2 = core.ensureArchetype(["id", "cell", "position"], { cell: 2 });
100
+ expect(cell1.rowCount).toBe(1);
101
+ expect(cell2.rowCount).toBe(0);
102
+ core.update(e, { cell: 2 });
103
+ // Same entity id, moved archetype, position preserved.
104
+ expect(core.locate(e).archetype).toBe(cell2);
105
+ expect(cell1.rowCount).toBe(0);
106
+ expect(cell2.rowCount).toBe(1);
107
+ expect(core.get(e, "cell")).toBe(2);
108
+ expect(core.read(e)).toMatchObject({ cell: 2, position: { x: 7, y: 8 } });
109
+ });
110
+ it("does not migrate when a non-partition field changes", () => {
111
+ const core = makeCore();
112
+ const router = core.ensureArchetype(["id", "cell", "position"]);
113
+ const e = router.insert({ cell: 5, position: { x: 1, y: 1 } });
114
+ const cell5 = core.locate(e).archetype;
115
+ core.update(e, { position: { x: 9, y: 9 } });
116
+ expect(core.locate(e).archetype).toBe(cell5);
117
+ expect(core.read(e)).toMatchObject({ cell: 5, position: { x: 9, y: 9 } });
118
+ });
119
+ it("does not migrate when a partition value is set to its current value", () => {
120
+ const core = makeCore();
121
+ const router = core.ensureArchetype(["id", "cell", "position"]);
122
+ const e = router.insert({ cell: 3, position: { x: 0, y: 0 } });
123
+ const before = core.locate(e).archetype;
124
+ core.update(e, { cell: 3 });
125
+ expect(core.locate(e).archetype).toBe(before);
126
+ });
127
+ });
128
+ describe("serialization", () => {
129
+ it("round-trips partition children (values + rows) through toData/fromData", () => {
130
+ const core = makeCore();
131
+ const router = core.ensureArchetype(["id", "cell", "position"]);
132
+ const a = router.insert({ cell: 1, position: { x: 1, y: 1 } });
133
+ const b = router.insert({ cell: 2, position: { x: 2, y: 2 } });
134
+ const snapshot = core.toData(true);
135
+ const restored = makeCore();
136
+ restored.fromData(snapshot);
137
+ expect(restored.get(a, "cell")).toBe(1);
138
+ expect(restored.get(b, "cell")).toBe(2);
139
+ expect(restored.read(a)).toMatchObject({ cell: 1, position: { x: 1, y: 1 } });
140
+ expect(restored.read(b)).toMatchObject({ cell: 2, position: { x: 2, y: 2 } });
141
+ const cell1 = restored.ensureArchetype(["id", "cell", "position"], { cell: 1 });
142
+ expect(cell1.columns.cell.type).toBe(constBufferType);
143
+ expect(cell1.rowCount).toBe(1);
144
+ });
145
+ });
146
+ describe("multiple partition components together", () => {
147
+ // Two partition components → archetypes are the *cross product* of the
148
+ // distinct (cell, layer) value pairs actually used.
149
+ const makeGridCore = () => createCore({
150
+ cell: { type: "integer", partition: true },
151
+ layer: { type: "integer", partition: true },
152
+ value: { type: "number" },
153
+ });
154
+ const keys = ["id", "cell", "layer", "value"];
155
+ it("creates one archetype per distinct (cell, layer) pair, each with both const columns", () => {
156
+ const core = makeGridCore();
157
+ const router = core.ensureArchetype(keys);
158
+ const cells = [0, 1];
159
+ const layers = [0, 1, 2];
160
+ for (const cell of cells)
161
+ for (const layer of layers) {
162
+ router.insert({ cell, layer, value: cell * 10 + layer });
163
+ }
164
+ const archetypes = core.queryArchetypes(["cell", "layer", "value"]);
165
+ expect(archetypes.length).toBe(cells.length * layers.length); // 2 × 3 = 6
166
+ const combos = new Set();
167
+ for (const arch of archetypes) {
168
+ expect(arch.rowCount).toBe(1);
169
+ // BOTH partition columns are zero-per-row const buffers.
170
+ expect(arch.columns.cell.type).toBe(constBufferType);
171
+ expect(arch.columns.layer.type).toBe(constBufferType);
172
+ combos.add(`${arch.columns.cell.get(0)},${arch.columns.layer.get(0)}`);
173
+ }
174
+ expect(combos.size).toBe(6);
175
+ });
176
+ it("routes on the full (cell, layer) tuple — same pair shares an archetype, either differing splits", () => {
177
+ const core = makeGridCore();
178
+ const router = core.ensureArchetype(keys);
179
+ const a = router.insert({ cell: 1, layer: 2, value: 0 });
180
+ const b = router.insert({ cell: 1, layer: 2, value: 1 }); // same pair
181
+ const c = router.insert({ cell: 1, layer: 3, value: 2 }); // layer differs
182
+ const d = router.insert({ cell: 9, layer: 2, value: 3 }); // cell differs
183
+ expect(core.locate(a).archetype).toBe(core.locate(b).archetype);
184
+ expect(core.locate(a).archetype).not.toBe(core.locate(c).archetype);
185
+ expect(core.locate(a).archetype).not.toBe(core.locate(d).archetype);
186
+ const arch12 = core.ensureArchetype(keys, { cell: 1, layer: 2 });
187
+ expect(core.locate(a).archetype).toBe(arch12);
188
+ expect(arch12.rowCount).toBe(2);
189
+ expect(core.read(a)).toMatchObject({ cell: 1, layer: 2, value: 0 });
190
+ });
191
+ it("queryArchetypes `where` filters on one or both partition components", () => {
192
+ const core = makeGridCore();
193
+ const router = core.ensureArchetype(keys);
194
+ for (const cell of [0, 1])
195
+ for (const layer of [0, 1, 2]) {
196
+ router.insert({ cell, layer, value: 0 });
197
+ }
198
+ // One component → all pairs sharing it (cell=1 across 3 layers).
199
+ expect(core.queryArchetypes(["cell", "layer", "value"], { where: { cell: 1 } }).length).toBe(3);
200
+ // Both components → exactly the one pair.
201
+ const one = core.queryArchetypes(["cell", "layer", "value"], { where: { cell: 1, layer: 2 } });
202
+ expect(one.length).toBe(1);
203
+ expect(one[0].columns.cell.get(0)).toBe(1);
204
+ expect(one[0].columns.layer.get(0)).toBe(2);
205
+ });
206
+ it("migrating one partition value keeps the other and lands in the correct combined archetype", () => {
207
+ const core = makeGridCore();
208
+ const router = core.ensureArchetype(keys);
209
+ const e = router.insert({ cell: 1, layer: 2, value: 5 });
210
+ core.update(e, { cell: 3 }); // change cell only
211
+ expect(core.get(e, "cell")).toBe(3);
212
+ expect(core.get(e, "layer")).toBe(2); // preserved
213
+ expect(core.locate(e).archetype).toBe(core.ensureArchetype(keys, { cell: 3, layer: 2 }));
214
+ // The old (1, 2) archetype is now empty.
215
+ expect(core.ensureArchetype(keys, { cell: 1, layer: 2 }).rowCount).toBe(0);
216
+ });
217
+ });
218
+ describe("feature is inert without partition components", () => {
219
+ it("a store with no partition component behaves exactly as before", () => {
220
+ const core = createCore({ position: positionSchema });
221
+ const arch = core.ensureArchetype(["id", "position"]);
222
+ // Concrete archetype, direct insert, dense columns — no Router anywhere.
223
+ expect(arch.columns).toBeDefined();
224
+ const e = arch.insert({ position: { x: 1, y: 2 } });
225
+ expect(core.read(e)).toMatchObject({ position: { x: 1, y: 2 } });
226
+ });
227
+ });
228
+ });
229
+ //# sourceMappingURL=create-core.partition.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-core.partition.test.js","sourceRoot":"","sources":["../../../../src/ecs/store/core/create-core.partition.test.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,10 @@
2
2
  import { selectRows } from "../../../table/select-rows.js";
3
3
  import { compare } from "../../../functions/compare.js";
4
4
  export const selectEntities = (core, include, options) => {
5
- const archetypes = core.queryArchetypes(include, options);
5
+ // Pass only archetype-level options (exclude) to queryArchetypes. `options.where`
6
+ // here is a row-level Filter and is applied per-row below via selectRows — it
7
+ // must NOT be forwarded as queryArchetypes' partition-equality `where`.
8
+ const archetypes = core.queryArchetypes(include, options?.exclude ? { exclude: options.exclude } : undefined);
6
9
  let length = 0;
7
10
  for (const archetype of archetypes) {
8
11
  length += archetype.rowCount;
@@ -30,32 +33,95 @@ export const selectEntities = (core, include, options) => {
30
33
  }
31
34
  return entities;
32
35
  }
33
- // now we know there is an order, there might be a where
34
- // ordering means we are going to want to extract the order values into an array that also contains id
35
- const entityValues = new Array();
36
- for (const archetype of archetypes) {
37
- const idTypedArray = archetype.columns.id.getTypedArray();
38
- for (const row of selectRows(archetype, options.where)) {
39
- const entityValue = { id: idTypedArray[row] };
40
- for (const order in options.order) {
41
- entityValue[order] = archetype.columns[order].get(row);
42
- }
43
- entityValues.push(entityValue);
44
- }
36
+ // ── Ordered results ─────────────────────────────────────────────────────
37
+ // When the *leading run* of order keys are partition components, each
38
+ // archetype holds a constant value for them, so the archetypes already
39
+ // bucket the rows on that leading key. We can then sort the buckets by
40
+ // value, sort only the *remaining* keys within each bucket, and concatenate
41
+ // in bucket order — turning an O(N log N) sort into O(N log(N/K)), and O(N)
42
+ // when a partition key is the sole order key. When no leading order key is a
43
+ // partition component (leadCount === 0) this falls back to one full sort,
44
+ // matching the previous behaviour exactly.
45
+ const order = options.order;
46
+ const schemas = core.componentSchemas;
47
+ // Keys of `order` are, by OrderClause<Pick<…, Include>>, exactly the picked
48
+ // component keys — safe to view as Include[].
49
+ const orderKeys = Object.keys(order);
50
+ let leadCount = 0;
51
+ while (leadCount < orderKeys.length && schemas[orderKeys[leadCount]]?.partition === true) {
52
+ leadCount++;
45
53
  }
46
- // now that we have the entity values with the order values, we can sort the entity values
47
- entityValues.sort((a, b) => {
48
- for (const order in options.order) {
54
+ const compareByKeys = (keys, a, b) => {
55
+ for (const key of keys) {
49
56
  // `compare` (code-point for strings, numeric for numbers) — not
50
57
  // `a - b`, which is NaN for string order keys, and never locale.
51
- const cmp = compare(a[order], b[order]);
52
- if (cmp !== 0) {
53
- const ascending = options.order[order];
54
- return ascending ? cmp : -cmp;
58
+ const cmp = compare(a[key], b[key]);
59
+ if (cmp !== 0)
60
+ return order[key] ? cmp : -cmp;
61
+ }
62
+ return 0;
63
+ };
64
+ // Gather ids for `archs`, sorted by `sortKeys` (empty → left in archetype +
65
+ // row order). `where` is applied per row. A stable sort over the same gather
66
+ // order keeps tie-ordering identical to the single full sort.
67
+ const collect = (archs, sortKeys) => {
68
+ if (sortKeys.length === 0) {
69
+ const ids = [];
70
+ for (const archetype of archs) {
71
+ const idTypedArray = archetype.columns.id.getTypedArray();
72
+ for (const row of selectRows(archetype, options.where)) {
73
+ ids.push(idTypedArray[row]);
74
+ }
55
75
  }
76
+ return ids;
77
+ }
78
+ const rows = [];
79
+ for (const archetype of archs) {
80
+ const idTypedArray = archetype.columns.id.getTypedArray();
81
+ for (const row of selectRows(archetype, options.where)) {
82
+ const value = { id: idTypedArray[row] };
83
+ for (const key of sortKeys)
84
+ value[key] = archetype.columns[key].get(row);
85
+ rows.push(value);
86
+ }
87
+ }
88
+ rows.sort((a, b) => compareByKeys(sortKeys, a, b));
89
+ return rows.map((r) => r.id);
90
+ };
91
+ if (leadCount === 0) {
92
+ return collect(archetypes, orderKeys);
93
+ }
94
+ // Bucket archetypes by their leading partition-value tuple, preserving
95
+ // archetype iteration order within a bucket (so tie-ordering matches the
96
+ // full sort). A bucket can span multiple archetypes (shape fan-out).
97
+ const leadKeys = orderKeys.slice(0, leadCount);
98
+ const restKeys = orderKeys.slice(leadCount);
99
+ const buckets = new Map();
100
+ for (const archetype of archetypes) {
101
+ const values = leadKeys.map((key) => archetype.columns[key].get(0));
102
+ // JSON is an unambiguous key for a primitive tuple: it distinguishes
103
+ // 1 from "1" and never collides across tuple boundaries.
104
+ const bucketKey = JSON.stringify(values);
105
+ let bucket = buckets.get(bucketKey);
106
+ if (!bucket) {
107
+ bucket = { values, archs: [] };
108
+ buckets.set(bucketKey, bucket);
109
+ }
110
+ bucket.archs.push(archetype);
111
+ }
112
+ const orderedBuckets = [...buckets.values()].sort((a, b) => {
113
+ for (let i = 0; i < leadKeys.length; i++) {
114
+ const cmp = compare(a.values[i], b.values[i]);
115
+ if (cmp !== 0)
116
+ return order[leadKeys[i]] ? cmp : -cmp;
56
117
  }
57
118
  return 0;
58
119
  });
59
- return entityValues.map(entityValue => entityValue.id);
120
+ const result = [];
121
+ for (const bucket of orderedBuckets) {
122
+ for (const id of collect(bucket.archs, restKeys))
123
+ result.push(id);
124
+ }
125
+ return result;
60
126
  };
61
127
  //# sourceMappingURL=select-entities.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"select-entities.js","sourceRoot":"","sources":["../../../../src/ecs/store/core/select-entities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select-entities.js","sourceRoot":"","sources":["../../../../src/ecs/store/core/select-entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { describe, it, expect } from "vitest";
3
+ import { createStore } from "../public/create-store.js";
4
+ import { compare } from "../../../functions/compare.js";
5
+ // `cell` and `region` partition; `rank` does not. The partition-aware sort in
6
+ // selectEntities must produce output identical to a naive full sort.
7
+ const schema = {
8
+ components: {
9
+ cell: { type: "integer", partition: true },
10
+ region: { type: "integer", partition: true },
11
+ rank: { type: "integer" },
12
+ },
13
+ resources: {},
14
+ archetypes: { E: ["cell", "region", "rank"] },
15
+ };
16
+ const makeStore = (rows) => {
17
+ const store = createStore(schema);
18
+ const ids = rows.map((r) => store.archetypes.E.insert(r));
19
+ return { store, ids };
20
+ };
21
+ // Independent reference: read every row and sort by the order keys with the
22
+ // same `compare` semantics selectEntities uses.
23
+ const referenceSort = (store, ids, order, where) => {
24
+ const keys = Object.keys(order);
25
+ const withVals = ids
26
+ .map((id) => ({ id, r: store.read(id) }))
27
+ .filter((x) => (where ? where(x.r) : true));
28
+ withVals.sort((a, b) => {
29
+ for (const k of keys) {
30
+ const c = compare(a.r[k], b.r[k]);
31
+ if (c !== 0)
32
+ return order[k] ? c : -c;
33
+ }
34
+ return 0;
35
+ });
36
+ return withVals.map((x) => x.id);
37
+ };
38
+ // Rows with a globally-unique `rank` so every order that ends in `rank` is a
39
+ // total order (no ties → the reference comparison is unambiguous).
40
+ const uniqueRows = (n) => Array.from({ length: n }, (_, i) => ({
41
+ cell: i % 5,
42
+ region: i % 3,
43
+ rank: (i * 7) % n, // a permutation of 0..n-1 (7 and n=100 are coprime)
44
+ }));
45
+ describe("selectEntities partition-aware ordering", () => {
46
+ const orders = [
47
+ ["sole partition key (cell asc) + rank tiebreak", { cell: true, rank: true }],
48
+ ["partition key descending (cell desc) + rank", { cell: false, rank: true }],
49
+ ["compound partition keys (cell, region) + rank", { cell: true, region: true, rank: true }],
50
+ ["partition then descending secondary (cell asc, rank desc)", { cell: true, rank: false }],
51
+ ["non-partition leading key (rank asc) — fallback path", { rank: true }],
52
+ ["non-partition leading then partition (rank asc, cell asc) — fallback", { rank: true, cell: true }],
53
+ ];
54
+ for (const [name, order] of orders) {
55
+ it(`matches a naive full sort: ${name}`, () => {
56
+ const rows = uniqueRows(100);
57
+ const { store, ids } = makeStore(rows);
58
+ const got = store.select(["cell", "region", "rank"], { order });
59
+ const expected = referenceSort(store, ids, order);
60
+ expect(got).toEqual(expected);
61
+ });
62
+ }
63
+ it("matches a naive full sort with a where filter (cell asc, rank asc)", () => {
64
+ const rows = uniqueRows(100);
65
+ const { store, ids } = makeStore(rows);
66
+ const order = { cell: true, rank: true };
67
+ const got = store.select(["cell", "region", "rank"], { where: { rank: { ">=": 50 } }, order });
68
+ const expected = referenceSort(store, ids, order, (r) => r.rank >= 50);
69
+ expect(got).toEqual(expected);
70
+ });
71
+ it("large K (many distinct partition values) still matches — exercises bucketing at scale", () => {
72
+ // Distinct cell per entity → one bucket each; sole partition order key is
73
+ // the O(N) path (no within-bucket sort).
74
+ const rows = Array.from({ length: 200 }, (_, i) => ({ cell: i, region: 0, rank: i }));
75
+ const { store, ids } = makeStore(rows);
76
+ const order = { cell: true };
77
+ expect(store.select(["cell", "region", "rank"], { order })).toEqual(referenceSort(store, ids, order));
78
+ });
79
+ it("with ties on the sole partition key, output is correctly ordered and a permutation of the input", () => {
80
+ // Many entities share each cell value → ties the reference can't
81
+ // disambiguate; assert the weaker invariants instead.
82
+ const rows = Array.from({ length: 60 }, (_, i) => ({ cell: i % 4, region: 0, rank: i }));
83
+ const { store, ids } = makeStore(rows);
84
+ const got = store.select(["cell", "region", "rank"], { order: { cell: true } });
85
+ // Non-decreasing by cell.
86
+ for (let i = 1; i < got.length; i++) {
87
+ expect(store.get(got[i - 1], "cell") <= store.get(got[i], "cell")).toBe(true);
88
+ }
89
+ // Same set of entities, none lost or duplicated.
90
+ expect([...got].sort((a, b) => a - b)).toEqual([...ids].sort((a, b) => a - b));
91
+ });
92
+ });
93
+ //# sourceMappingURL=select-entities.partition.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-entities.partition.test.js","sourceRoot":"","sources":["../../../../src/ecs/store/core/select-entities.partition.test.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AAGxD,8EAA8E;AAC9E,qEAAqE;AACrE,MAAM,MAAM,GAAG;IACX,UAAU,EAAE;QACR,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;QAC1C,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE;QAC5C,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;KAC5B;IACD,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;CACvC,CAAC;AAKX,MAAM,SAAS,GAAG,CAAC,IAAoB,EAAE,EAAE;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC,CAAC;AAEF,4EAA4E;AAC5E,gDAAgD;AAChD,MAAM,aAAa,GAAG,CAClB,KAA4C,EAC5C,GAAsB,EACtB,KAAY,EACZ,KAA2B,EACnB,EAAE;IACV,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAkB,CAAC;IACjD,MAAM,QAAQ,GAAG,GAAG;SACf,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAmB,EAAE,CAAC,CAAC;SAC1D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC;gBAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,CAAC,CAAC;IACb,CAAC,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,6EAA6E;AAC7E,mEAAmE;AACnE,MAAM,UAAU,GAAG,CAAC,CAAS,EAAS,EAAE,CACpC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,GAAG,CAAC;IACX,MAAM,EAAE,CAAC,GAAG,CAAC;IACb,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,oDAAoD;CAC1E,CAAC,CAAC,CAAC;AAER,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACrD,MAAM,MAAM,GAAsB;QAC9B,CAAC,+CAA+C,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC7E,CAAC,6CAA6C,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC5E,CAAC,+CAA+C,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC3F,CAAC,2DAA2D,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC1F,CAAC,sDAAsD,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACxE,CAAC,sEAAsE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;KACvG,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACjC,EAAE,CAAC,8BAA8B,IAAI,EAAE,EAAE,GAAG,EAAE;YAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACP,CAAC;IAED,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC1E,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/F,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,GAAG,EAAE;QAC7F,0EAA0E;QAC1E,yCAAyC;QACzC,MAAM,IAAI,GAAU,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7F,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,KAAK,GAAU,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iGAAiG,EAAE,GAAG,EAAE;QACvG,iEAAiE;QACjE,sDAAsD;QACtD,MAAM,IAAI,GAAU,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChG,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;QAEhF,0BAA0B;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAE,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,CAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpF,CAAC;QACD,iDAAiD;QACjD,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -3,9 +3,13 @@ import { ArchetypeQueryOptions } from "./core/core.js";
3
3
  export type OrderClause<T extends object> = {
4
4
  [K in keyof T]?: boolean;
5
5
  };
6
- export type EntitySelectOptions<C extends object, T extends object> = ArchetypeQueryOptions<C> & {
6
+ export type EntitySelectOptions<C extends object, T extends object> = Omit<ArchetypeQueryOptions<C>, "where"> & {
7
7
  /**
8
8
  * Filter the results by the given condition using a declarative where clause.
9
+ * This is a *row-level* {@link Filter} (supports comparison operators),
10
+ * distinct from `ArchetypeQueryOptions.where`, which is archetype-level
11
+ * partition-value equality. Select owns row filtering, so it replaces the
12
+ * inherited partition `where` rather than intersecting with it.
9
13
  */
10
14
  where?: Filter<T>;
11
15
  /**
@@ -0,0 +1,63 @@
1
+ import { StringKeyof } from "../../types/types.js";
2
+ import { ComponentSchemas } from "../component-schemas.js";
3
+ import { RequiredComponents } from "../required-components.js";
4
+ import { Archetype } from "../archetype/archetype.js";
5
+ /**
6
+ * The component keys of a schema map that are declared `partition: true`.
7
+ *
8
+ * Detection is at the *schema* level, where the marker survives — the resolved
9
+ * component value map (`FromSchemas<CS>`) has already dropped it. Requires the
10
+ * schema literal to be `as const` so `partition` is the literal `true`, not
11
+ * `boolean` (the project's `... as const satisfies Schema` idiom guarantees it).
12
+ */
13
+ export type PartitionKeysOf<CS extends ComponentSchemas> = {
14
+ [K in StringKeyof<CS>]: CS[K] extends {
15
+ partition: true;
16
+ } ? K : never;
17
+ }[StringKeyof<CS>];
18
+ /**
19
+ * Whether a component-key set intersects the store's partition keys.
20
+ *
21
+ * The `[PK] extends [never]` guard is load-bearing: when a store declares no
22
+ * partition components (`PK = never` — the default everywhere), this collapses
23
+ * to `false` *without* inspecting `Keys`. That matters because `Keys` is often a
24
+ * generic indexed access (`A[K][number]` inside a `TransactionContext<C,R,A>`);
25
+ * `Extract<GenericKeys, never>` would otherwise stay a *deferred* conditional,
26
+ * leaving `store.archetypes.<K>` as the unresolved union `Archetype.Router | Archetype`
27
+ * and breaking assignability in every generic store context. Short-circuiting
28
+ * on `PK` keeps non-partition stores paying nothing and resolving eagerly.
29
+ */
30
+ type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;
31
+ export type HasPartitionKey<Keys extends string, PK extends string> = [
32
+ PK
33
+ ] extends [never] ? false : IsAny<PK> extends true ? boolean : [Extract<Keys, PK>] extends [never] ? false : true;
34
+ /**
35
+ * The `store.archetypes.<Name>` handle for one declared archetype: a
36
+ * {@link Archetype.Router} when it includes a partition component, else the
37
+ * `Concrete` archetype type (`Archetype` or `ReadonlyArchetype`, supplied by the
38
+ * caller). `Has` is a *naked* type parameter so a `boolean` (from `PK = any`)
39
+ * distributes to `Archetype.Router<C> | Concrete`.
40
+ */
41
+ export type ArchetypeOrRouter<Has extends boolean, C extends RequiredComponents, Concrete> = Has extends true ? Archetype.Router<C> : Concrete;
42
+ /**
43
+ * Return type of `ensureArchetype(keys, values?)`:
44
+ * - a value is supplied → a concrete {@link Archetype} (the resolved member),
45
+ * regardless of partitioning — this is the same-value fast path;
46
+ * - else the key set includes a partition component → a {@link Archetype.Router} that
47
+ * routes each `insert` by the row's partition value;
48
+ * - else → a concrete {@link Archetype} (today's behavior, unchanged).
49
+ *
50
+ * When `Keys` is not statically known to include or exclude a partition
51
+ * component, `HasPartitionKey` stays a union and the result widens to
52
+ * `Archetype<C> | Archetype.Router<C>` — which still exposes `.insert` (both branches
53
+ * share it); only dense column access requires narrowing to `Archetype`.
54
+ */
55
+ export type EnsureArchetypeResult<C extends RequiredComponents, Keys extends string, PK extends string, ValueProvided extends boolean> = ValueProvided extends true ? Archetype<C> : HasPartitionKey<Keys, PK> extends true ? Archetype.Router<C> : Archetype<C>;
56
+ /**
57
+ * Type of `store.archetypes.<Name>`: a {@link Archetype.Router} when the declared archetype
58
+ * includes a partition component, else a concrete {@link Archetype}. The keys are
59
+ * statically known here (from the schema's `archetypes` map), so this never
60
+ * widens to a union — the discrimination is exact per declared name.
61
+ */
62
+ export type StoreArchetypeHandle<C extends RequiredComponents, Keys extends string, PK extends string> = HasPartitionKey<Keys, PK> extends true ? Archetype.Router<C> : Archetype<C>;
63
+ export {};
@@ -0,0 +1,3 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ export {};
3
+ //# sourceMappingURL=partition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"partition.js","sourceRoot":"","sources":["../../../src/ecs/store/partition.ts"],"names":[],"mappings":"AAAA,uDAAuD"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ // A Router can insert (routing write) ...
3
+ router.insert({ cell: 1, position: 2 });
4
+ // ... but exposes no dense view:
5
+ // @ts-expect-error - a family has no single dense column view
6
+ router.columns;
7
+ // @ts-expect-error - a family has no row count
8
+ router.rowCount;
9
+ handle.insert({ cell: 1, position: 2 });
10
+ // ... while dense access is correctly gated behind resolving to a concrete
11
+ // archetype (supply a value, or narrow):
12
+ // @ts-expect-error - .columns requires a concrete Archetype, not a possible family
13
+ handle.columns;
14
+ export {};
15
+ //# sourceMappingURL=partition.type-test.js.map