@adobe/data 0.9.80 → 0.9.82

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,220 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { Database } from "./database.js";
3
+ /**
4
+ * Compile-time tests for `Database.Read<DB>` and the `db.derive`
5
+ * callback surface. Type-only — nothing here executes. `@ts-expect-error`
6
+ * marks the accesses that MUST NOT compile (the footguns the read projection
7
+ * removes structurally).
8
+ */
9
+ const plugin = Database.Plugin.create({
10
+ components: {
11
+ x: { type: "number" },
12
+ y: { type: "string" },
13
+ },
14
+ resources: {
15
+ frameRate: { type: "number", default: 30 },
16
+ },
17
+ archetypes: {
18
+ Foo: ["x"],
19
+ },
20
+ indexes: {
21
+ byX: { key: "x" },
22
+ byXUnique: { key: "x", unique: true },
23
+ },
24
+ });
25
+ const db = Database.create(plugin);
26
+ // ============================================================================
27
+ // derive — POSITIVE: the read surface a compute body is allowed to touch
28
+ // ============================================================================
29
+ function derivePositive() {
30
+ // value reads
31
+ const gotten = db.derive((d) => d.get(0, "x"));
32
+ const selected = db.derive((d) => d.select(["x"]));
33
+ // presence `select` — `exclude` is allowed (membership-based)
34
+ db.derive((d) => d.select(["x"], { exclude: ["y"] }));
35
+ // …but the value-dependent options are NOT on the derive surface: they can
36
+ // only be tracked coarsely, so a value-keyed / ordered reactive read must go
37
+ // through a declared index.
38
+ db.derive((d) =>
39
+ // @ts-expect-error `where` is not offered on a derive's select — use an index
40
+ d.select(["x"], { where: { x: 1 } }));
41
+ db.derive((d) =>
42
+ // @ts-expect-error `order` is not offered on a derive's select — use an index
43
+ d.select(["x"], { order: { x: true } }));
44
+ // whole-entity read
45
+ db.derive((d) => d.read(0));
46
+ // projection read: exactly the requested fields, optionality preserved,
47
+ // unrequested fields (incl. id) excluded
48
+ db.derive((d) => {
49
+ const p = d.read(0, ["x", "y"]);
50
+ if (p !== null) {
51
+ const _x = p.x;
52
+ const _y = p.y;
53
+ void _x;
54
+ void _y;
55
+ // @ts-expect-error `id` was not requested, so it is not on the projection
56
+ p.id;
57
+ }
58
+ return p;
59
+ });
60
+ // archetype read: narrowed to the archetype's own row (no extra fields)
61
+ db.derive((d) => {
62
+ const foo = d.read(0, db.archetypes.Foo);
63
+ if (foo !== null) {
64
+ const _x = foo.x;
65
+ // @ts-expect-error `y` is not part of the Foo archetype — narrowed read excludes it
66
+ foo.y;
67
+ }
68
+ return foo;
69
+ });
70
+ // resource reads
71
+ const frameRate = db.derive((d) => d.resources.frameRate);
72
+ // archetype identity — and the realistic composition select(archetype.components)
73
+ db.derive((d) => d.archetypes.Foo.components);
74
+ db.derive((d) => d.archetypes.Foo.id);
75
+ db.derive((d) => d.select(d.archetypes.Foo.components));
76
+ // index lookups
77
+ db.derive((d) => d.indexes.byX.find({ x: 1 }));
78
+ db.derive((d) => d.indexes.byX.findRange({ x: 1 }));
79
+ // a unique index also exposes `get`
80
+ const head = db.derive((d) => d.indexes.byXUnique.get({ x: 1 }));
81
+ }
82
+ function deriveInputsPositive() {
83
+ // inputs are injected as current values, strongly typed by unwrapping each Observe
84
+ const sum = db.derive({ n: numberInput, s: stringInput }, (d, inputs) => {
85
+ // the first arg is still the read projection
86
+ const r = d.resources.frameRate;
87
+ return `${inputs.s}:${inputs.n + r}`;
88
+ });
89
+ // a body that mixes an ECS read with an injected input value
90
+ const mixed = db.derive({ n: numberInput }, (d, inputs) => (d.get(0, "x") ?? 0) + inputs.n);
91
+ }
92
+ function deriveInputsNegative() {
93
+ db.derive({ n: numberInput }, (d, inputs) => {
94
+ void d;
95
+ // @ts-expect-error `n` unwraps to number, not string
96
+ const bad = inputs.n;
97
+ return bad;
98
+ });
99
+ db.derive({ n: numberInput }, (d, inputs) => {
100
+ void d;
101
+ // @ts-expect-error `m` is not an injected input
102
+ return inputs.m;
103
+ });
104
+ // @ts-expect-error an input value must be an Observe, not a bare value
105
+ db.derive({ n: 123 }, (d, inputs) => inputs.n);
106
+ }
107
+ // ============================================================================
108
+ // derive — NEGATIVE: everything the read projection removes
109
+ // ============================================================================
110
+ function deriveNegative() {
111
+ db.derive((d) => {
112
+ // @ts-expect-error observers are not exposed — a derive subscribes to its own reads
113
+ return d.observe;
114
+ });
115
+ db.derive((d) => {
116
+ // @ts-expect-error transactions / writes are not exposed to a read-only derive
117
+ return d.transactions;
118
+ });
119
+ db.derive((d) => {
120
+ // @ts-expect-error queryArchetypes (raw column access) is not exposed
121
+ return d.queryArchetypes;
122
+ });
123
+ db.derive((d) => {
124
+ // @ts-expect-error locate (row access) is not exposed
125
+ return d.locate;
126
+ });
127
+ db.derive((d) => {
128
+ // @ts-expect-error per-archetype column access is not exposed
129
+ return d.archetypes.Foo.columns;
130
+ });
131
+ db.derive((d) => {
132
+ // @ts-expect-error per-archetype rowCount (table access) is not exposed
133
+ return d.archetypes.Foo.rowCount;
134
+ });
135
+ db.derive((d) => {
136
+ // @ts-expect-error per-archetype insert (write) is not exposed
137
+ return d.archetypes.Foo.insert;
138
+ });
139
+ db.derive((d) => {
140
+ // @ts-expect-error index observe is not exposed — a derive subscribes for you
141
+ return d.indexes.byX.observe;
142
+ });
143
+ }
144
+ function readProjectionPositive() {
145
+ const v = rd.get(0, "x");
146
+ const ids = rd.select(["x"]);
147
+ const excluded = rd.select(["x"], { exclude: ["y"] });
148
+ const fr = rd.resources.frameRate;
149
+ rd.archetypes.Foo.components.has("x");
150
+ const found = rd.indexes.byX.find({ x: 1 });
151
+ void v;
152
+ void ids;
153
+ void excluded;
154
+ void fr;
155
+ void found;
156
+ }
157
+ function readProjectionNegative() {
158
+ // @ts-expect-error observers omitted from the read projection
159
+ rd.observe;
160
+ // @ts-expect-error index observe omitted from the read projection
161
+ rd.indexes.byX.observe;
162
+ // @ts-expect-error table/column access omitted from the read projection
163
+ rd.archetypes.Foo.columns;
164
+ // @ts-expect-error transactions omitted from the read projection
165
+ rd.transactions;
166
+ // @ts-expect-error `where` (value-dependent) omitted from the read projection's select
167
+ rd.select(["x"], { where: { x: 1 } });
168
+ // @ts-expect-error `order` (value-dependent) omitted from the read projection's select
169
+ rd.select(["x"], { order: { x: true } });
170
+ }
171
+ // ============================================================================
172
+ // Read distributes over an INTERSECTION (Option A). The structural definition
173
+ // means `Database.Read<A & B>` merges both members' read surfaces, and because
174
+ // `derive` passes `Database.Read<this>`, a derive on an intersection receiver
175
+ // sees indexes + resources + archetypes from BOTH members — so a consumer of a
176
+ // composed `A & B` database (e.g. an indexed core intersected with a
177
+ // resource-computed layer) never needs to cast.
178
+ // ============================================================================
179
+ const pluginA = Database.Plugin.create({
180
+ components: { a: { type: "number" } },
181
+ resources: { ra: { type: "number", default: 0 } },
182
+ archetypes: { AOnly: ["a"] },
183
+ indexes: { byA: { key: "a" } },
184
+ });
185
+ const pluginB = Database.Plugin.create({
186
+ components: { b: { type: "string" } },
187
+ resources: { rb: { type: "string", default: "" } },
188
+ archetypes: { BOnly: ["b"] },
189
+ indexes: { byB: { key: "b" } },
190
+ });
191
+ const dbA = Database.create(pluginA);
192
+ const dbB = Database.create(pluginB);
193
+ function intersectionRead() {
194
+ // both members' resources
195
+ const _ra = rb2.resources.ra;
196
+ const _rb = rb2.resources.rb;
197
+ // both members' indexes (find-only)
198
+ const _fa = rb2.indexes.byA.find({ a: 1 });
199
+ const _fb = rb2.indexes.byB.find({ b: "x" });
200
+ // both members' archetype identities
201
+ rb2.archetypes.AOnly.components.has("a");
202
+ rb2.archetypes.BOnly.components.has("b");
203
+ void _ra;
204
+ void _rb;
205
+ void _fa;
206
+ void _fb;
207
+ }
208
+ function intersectionDerive() {
209
+ // `Database.Read<this>` on an intersection receiver → merged surface.
210
+ both.derive((d) => {
211
+ const _ra = d.resources.ra;
212
+ const _rb = d.resources.rb;
213
+ d.indexes.byA.find({ a: 1 });
214
+ d.indexes.byB.find({ b: "x" });
215
+ void _ra;
216
+ void _rb;
217
+ return 0;
218
+ });
219
+ }
220
+ //# sourceMappingURL=database-read.type-test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-read.type-test.js","sourceRoot":"","sources":["../../../src/ecs/database/database-read.type-test.ts"],"names":[],"mappings":"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"}
@@ -138,6 +138,38 @@ export interface Database<C extends Components = {}, R extends ResourceComponent
138
138
  archetype(id: ArchetypeId): Observe<void>;
139
139
  select<Include extends StringKeyof<C>, T extends Include>(include: readonly Include[] | ReadonlySet<string>, options?: EntitySelectOptions<C, Pick<C & RequiredComponents, T>>): Observe<readonly Entity[]>;
140
140
  };
141
+ /**
142
+ * Reactive derivation. `compute` runs against a read-only projection of this
143
+ * database ({@link Database.Read} — value / index / resource reads only; no
144
+ * observers, writes, or table access). The derive records exactly the reads
145
+ * it performs and re-emits when any could have changed: the initial value on
146
+ * subscribe, then at most once per committed transaction (synchronously at
147
+ * the commit boundary), structurally deduplicated so an unchanged result
148
+ * never re-notifies.
149
+ *
150
+ * The callback receives `Database.Read<this>`, so an *intersection* database
151
+ * resolves to the merged read surface — consumers never need to cast.
152
+ */
153
+ derive<T>(compute: (db: Database.Read<this>) => T): Observe<T>;
154
+ /**
155
+ * `derive` with a fixed record of external `inputs` — arbitrary `Observe<T>`
156
+ * values that do NOT live in the ECS (e.g. observables exposed by services).
157
+ * Their CURRENT values are injected as the second callback argument, keyed the
158
+ * same as `inputs` and unwrapped (`Observe<U> → U`); the first argument stays
159
+ * the read projection, so a body can fold external values and ECS reads into
160
+ * one synchronous expression.
161
+ *
162
+ * The inputs are subscribed once, at the root (not read dynamically inside the
163
+ * body), so the set is fixed for the life of the derive. The derive recomputes
164
+ * when any input emits OR an ECS read it recorded could have changed; like
165
+ * {@link Observe.fromProperties}, the first value is withheld until every input
166
+ * has produced one. Anything dynamic — an input set that depends on data, or
167
+ * an input whose arguments come from an ECS read — composes with
168
+ * {@link Observe.withSwitch} / {@link Observe.fromKeys} around the derive.
169
+ */
170
+ derive<I extends Record<string, Observe<unknown>>, T>(inputs: I, compute: (db: Database.Read<this>, inputs: {
171
+ readonly [K in keyof I]: I[K] extends Observe<infer U> ? U : never;
172
+ }) => T): Observe<T>;
141
173
  /**
142
174
  * Wipes all entities and resets all resources to their plugin defaults,
143
175
  * preserving database identity (observers, transaction wrappers, sync
@@ -209,12 +241,47 @@ export declare namespace Database {
209
241
  * expansion that amplifies TS7056 serialization overflow in deep extends chains.
210
242
  */
211
243
  type FromPlugin<P extends Database.Plugin> = Database<FromSchemas<RemoveIndex<P['components']>>, FromSchemas<RemoveIndex<P['resources']>>, RemoveIndex<P['archetypes']>, ToTransactionFunctions<RemoveIndex<P['transactions']>>, StringKeyof<P['systems']>, ToActionFunctions<RemoveIndex<P['actions']>>, FromServiceFactories<RemoveIndex<P['services']>>, FromComputedFactories<RemoveIndex<P['computed']>>, RemoveIndex<P['indexes']>>;
244
+ /**
245
+ * The read-only projection of a Database that a `db.derive` callback
246
+ * receives. It exposes only the auto-trackable read surface —
247
+ * - value reads: `get`, `read`, `select`
248
+ * - resource reads: `resources`
249
+ * - index lookups: `indexes.<name>.find` / `findRange` / `get`
250
+ * - archetype identity: `archetypes.<name>.components` / `id`
251
+ * — and structurally OMITS everything a derived computation must not touch:
252
+ * - `observe` (a derive subscribes to what it reads for you)
253
+ * - transactions / actions / any write
254
+ * - direct table access: `queryArchetypes`, `locate`, and per-archetype
255
+ * `columns` / `rowCount` / `insert` / row reads
256
+ * - `services` / `computed` / lifecycle (`extend`, `reset`, `toData`, …)
257
+ *
258
+ * Because the surface is narrowed structurally, misuse is a compile error
259
+ * rather than a value that must be guarded / thrown on at runtime.
260
+ */
261
+ type Read<DB extends Database<any, any, any, any, any, any, any, any, any>> = Pick<DB, "get" | "read" | "resources"> & {
262
+ select(include: readonly string[] | ReadonlySet<string>, options?: {
263
+ readonly exclude?: readonly string[];
264
+ }): readonly Entity[];
265
+ readonly indexes: {
266
+ readonly [K in keyof DB["indexes"]]: Omit<DB["indexes"][K], "observe">;
267
+ };
268
+ readonly archetypes: {
269
+ readonly [K in keyof DB["archetypes"]]: Pick<DB["archetypes"][K], "components" | "id">;
270
+ };
271
+ };
212
272
  const create: typeof createDatabase;
213
273
  const is: (value: unknown) => value is Database;
214
274
  const observeSelectDeep: <C extends Components, Include extends StringKeyof<C>>(db: Database<C, any, any, any, any, any, any, any>, include: readonly Include[] | ReadonlySet<Include | "id">, options?: EntitySelectOptions<C, Pick<C & RequiredComponents, Include>>) => Observe<readonly (RequiredComponents & { readonly [K in Include]: C[K]; })[]>;
215
275
  type Index<C extends Components = any> = StoreIndex<C, any, any, any>;
216
276
  namespace Index {
217
277
  type Handle<C extends Components, I extends StoreIndex<C, any, any, any>> = StoreIndex.Handle<C, I>;
278
+ /**
279
+ * The index handle as exposed to a `db.derive` callback: the
280
+ * synchronous lookups (`find` / `findRange` / `get`) only. `observe` is
281
+ * removed — a derive subscribes to the reads it performs automatically, so
282
+ * calling `observe` from inside one is a category error.
283
+ */
284
+ type ReadHandle<C extends Components, I extends StoreIndex<C, any, any, any>> = Omit<Handle<C, I>, "observe">;
218
285
  }
219
286
  namespace Archetype {
220
287
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/ecs/database/database.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAkBvD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,iBAAiB,IAAI,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAc1F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAsMtD,MAAM,KAAW,QAAQ,CAyGxB;AAzGD,WAAiB,QAAQ;IAmBV,eAAM,GAAG,cAAc,CAAC;IAExB,WAAE,GAAG,CAAC,KAAc,EAAqB,EAAE;QACtD,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,CAAC;IAC1L,CAAC,CAAA;IAEY,0BAAiB,GAAG,kBAAkB,CAAC;IAyDpD,IAAiB,MAAM,CAqBtB;IArBD,WAAiB,MAAM;QACR,aAAM,GAAG,YAAY,CAAC;QACtB,cAAO,GAAG,cAAc,CAAC;IAmBxC,CAAC,EArBgB,MAAM,GAAN,eAAM,KAAN,eAAM,QAqBtB;AAEH,CAAC,EAzGgB,QAAQ,KAAR,QAAQ,QAyGxB"}
1
+ {"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/ecs/database/database.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAkBvD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,iBAAiB,IAAI,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAc1F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AA0OtD,MAAM,KAAW,QAAQ,CAkKxB;AAlKD,WAAiB,QAAQ;IAoEV,eAAM,GAAG,cAAc,CAAC;IAExB,WAAE,GAAG,CAAC,KAAc,EAAqB,EAAE;QACtD,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,SAAS,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,CAAC;IAC1L,CAAC,CAAA;IAEY,0BAAiB,GAAG,kBAAkB,CAAC;IAiEpD,IAAiB,MAAM,CAqBtB;IArBD,WAAiB,MAAM;QACR,aAAM,GAAG,YAAY,CAAC;QACtB,cAAO,GAAG,cAAc,CAAC;IAmBxC,CAAC,EArBgB,MAAM,GAAN,eAAM,KAAN,eAAM,QAqBtB;AAEH,CAAC,EAlKgB,QAAQ,KAAR,QAAQ,QAkKxB"}
@@ -0,0 +1,14 @@
1
+ import { Observe } from "../../observe/index.js";
2
+ import { ReadonlyStore } from "../store/index.js";
3
+ import { TransactionResult } from "./transactional-store/transactional-store.js";
4
+ /**
5
+ * Builds `db.derive`. A single read-recording wrapper is constructed
6
+ * once and shared across every derive on this database: because a `compute`
7
+ * body is synchronous and performs no writes or nested derives, no two runs can
8
+ * overlap, so the wrapper's "currently-recording" target is reset per run and
9
+ * safely reused.
10
+ */
11
+ export declare const createDerive: <C extends object>(store: ReadonlyStore<C, any, any, any>, observeTransactions: Observe<TransactionResult<C>>) => {
12
+ <T>(compute: (db: any) => T): Observe<T>;
13
+ <I extends Record<string, Observe<unknown>>, T>(inputs: I, compute: (db: any, inputs: { readonly [K in keyof I]: I[K] extends Observe<infer U> ? U : never; }) => T): Observe<T>;
14
+ };
@@ -0,0 +1,257 @@
1
+ // © 2026 Adobe. MIT License. See /LICENSE for details.
2
+ import { Observe } from "../../observe/index.js";
3
+ import { equals } from "../../equals.js";
4
+ const emptyDeps = () => ({
5
+ entityWhole: new Set(),
6
+ entityComponents: new Map(),
7
+ columns: new Set(),
8
+ setReads: [],
9
+ });
10
+ const watchComponent = (deps, entity, component) => {
11
+ let set = deps.entityComponents.get(entity);
12
+ if (set === undefined) {
13
+ deps.entityComponents.set(entity, (set = new Set()));
14
+ }
15
+ set.add(component);
16
+ };
17
+ const affected = (deps, result) => {
18
+ const { changedEntities, changedComponents, changedArchetypes } = result;
19
+ const { entityWhole, entityComponents, columns, setReads } = deps;
20
+ // Entity deps: iterate the (usually small) *changed* set and probe the
21
+ // watched sets — O(|changedEntities|), not O(|watched|). A commit touches a
22
+ // handful of entities regardless of how many a derive reads.
23
+ if (entityWhole.size > 0 || entityComponents.size > 0) {
24
+ for (const [entity, values] of changedEntities) {
25
+ if (entityWhole.has(entity)) {
26
+ return true;
27
+ }
28
+ const watched = entityComponents.get(entity);
29
+ if (watched === undefined) {
30
+ continue;
31
+ }
32
+ if (values === null) {
33
+ // entity deleted — any scoped read of it is now stale
34
+ return true;
35
+ }
36
+ for (const component of Object.keys(values)) {
37
+ if (watched.has(component)) {
38
+ return true;
39
+ }
40
+ }
41
+ }
42
+ }
43
+ // Resource column deps.
44
+ if (columns.size > 0 && !changedComponents.isDisjointFrom(columns)) {
45
+ return true;
46
+ }
47
+ // Set-valued reads: cheap gate, then recompute-and-compare this one read.
48
+ for (const dep of setReads) {
49
+ if (dep.kind === "index") {
50
+ if (changedComponents.isDisjointFrom(dep.readColumns)) {
51
+ continue;
52
+ }
53
+ }
54
+ else if (changedArchetypes.size === 0) {
55
+ continue;
56
+ }
57
+ if (!equals(dep.last, dep.recompute())) {
58
+ return true;
59
+ }
60
+ }
61
+ return false;
62
+ };
63
+ /**
64
+ * Builds `db.derive`. A single read-recording wrapper is constructed
65
+ * once and shared across every derive on this database: because a `compute`
66
+ * body is synchronous and performs no writes or nested derives, no two runs can
67
+ * overlap, so the wrapper's "currently-recording" target is reset per run and
68
+ * safely reused.
69
+ */
70
+ export const createDerive = (store, observeTransactions) => {
71
+ // The active recording target, non-null only for the duration of one
72
+ // synchronous `compute` run.
73
+ let recording = null;
74
+ // `resources` and `indexes` are built lazily and cached: the store's
75
+ // resource and index maps are populated during database construction, which
76
+ // finishes AFTER this factory is created, but before any derive can run.
77
+ let resourcesRecorder = null;
78
+ const buildResources = () => {
79
+ const out = {};
80
+ for (const name of Object.keys(store.resources)) {
81
+ Object.defineProperty(out, name, {
82
+ enumerable: true,
83
+ get() {
84
+ if (recording) {
85
+ recording.columns.add(name);
86
+ }
87
+ return store.resources[name];
88
+ },
89
+ });
90
+ }
91
+ return out;
92
+ };
93
+ let indexesRecorder = null;
94
+ const buildIndexes = () => {
95
+ const out = {};
96
+ const storeIndexes = (store.indexes ?? {});
97
+ for (const name of Object.keys(storeIndexes)) {
98
+ const handle = storeIndexes[name];
99
+ const readColumns = new Set(handle.readColumns ?? []);
100
+ // Record a per-bucket dependency: the exact result this lookup
101
+ // returned, plus a thunk to recompute it. `affected` gates on the
102
+ // read columns then recompute-compares, so an unrelated bucket's
103
+ // change recomputes this (cheap Map-get + slice) to an identical
104
+ // sequence and is suppressed — the derive body never re-runs.
105
+ const recordLookup = (result, recompute) => {
106
+ if (recording) {
107
+ recording.setReads.push({ kind: "index", readColumns, recompute, last: result });
108
+ }
109
+ };
110
+ const readHandle = {
111
+ find: (arg) => {
112
+ const result = handle.find(arg);
113
+ recordLookup(result, () => handle.find(arg));
114
+ return result;
115
+ },
116
+ findRange: (arg) => {
117
+ const result = handle.findRange(arg);
118
+ recordLookup(result, () => handle.findRange(arg));
119
+ return result;
120
+ },
121
+ };
122
+ if (typeof handle.get === "function") {
123
+ readHandle.get = (arg) => {
124
+ const result = handle.get(arg);
125
+ recordLookup(result, () => handle.get(arg));
126
+ return result;
127
+ };
128
+ }
129
+ out[name] = readHandle;
130
+ }
131
+ return out;
132
+ };
133
+ // The read-recording projection handed to `compute`. Delegates every read to
134
+ // the real store and records the dependency it implies. Typed loosely here;
135
+ // the precise `Database.Read<…>` surface is enforced at the public
136
+ // `db.derive` boundary.
137
+ const recorder = {
138
+ get: (entity, component) => {
139
+ if (recording) {
140
+ watchComponent(recording, entity, component);
141
+ }
142
+ return store.get(entity, component);
143
+ },
144
+ read: (entity, archetypeOrComponents) => {
145
+ if (recording) {
146
+ if (archetypeOrComponents === undefined) {
147
+ recording.entityWhole.add(entity);
148
+ }
149
+ else if (Array.isArray(archetypeOrComponents)) {
150
+ for (const component of archetypeOrComponents) {
151
+ watchComponent(recording, entity, component);
152
+ }
153
+ }
154
+ else {
155
+ for (const component of archetypeOrComponents.components) {
156
+ watchComponent(recording, entity, component);
157
+ }
158
+ }
159
+ }
160
+ return store.read(entity, archetypeOrComponents);
161
+ },
162
+ // Presence select only — `include` + `exclude`, no `where` / `order`
163
+ // (value-dependent options are omitted from the derive surface; use a
164
+ // declared index for value-keyed or ordered reactive reads). Recorded as
165
+ // a set-valued read gated on `changedArchetypes`: the result is
166
+ // membership-shaped, so a pure value write can never move it, and an
167
+ // unrelated migration recompute-compares to the same sequence.
168
+ select: (include, options) => {
169
+ const exclude = options?.exclude;
170
+ const args = [include, exclude === undefined ? undefined : { exclude }];
171
+ const run = () => store.select(...args);
172
+ const result = run();
173
+ if (recording) {
174
+ recording.setReads.push({ kind: "select", recompute: run, last: result });
175
+ }
176
+ return result;
177
+ },
178
+ get resources() {
179
+ return (resourcesRecorder ??= buildResources());
180
+ },
181
+ get indexes() {
182
+ return (indexesRecorder ??= buildIndexes());
183
+ },
184
+ // Archetype identity (components / id) is static, so reading it records
185
+ // no dependency; delegate to the real archetypes.
186
+ archetypes: store.archetypes,
187
+ };
188
+ // Implementation signature — hidden; callers only ever see the two typed
189
+ // overloads above. `inputs` is `any` here solely because an overloaded impl
190
+ // signature must remain callable for the typed overload (whose `inputs` param
191
+ // is checked contravariantly); the public surface stays fully typed.
192
+ function derive(arg1, arg2) {
193
+ const inputObservables = typeof arg1 === "function" ? undefined : arg1;
194
+ const compute = typeof arg1 === "function" ? arg1 : arg2;
195
+ if (compute === undefined) {
196
+ throw new Error("db.derive requires a compute function");
197
+ }
198
+ return (notify) => {
199
+ let last;
200
+ let hasLast = false;
201
+ let deps = emptyDeps();
202
+ // Latest injected input snapshot; `ready` gates the ECS commit path
203
+ // until the inputs exist (no inputs → ready immediately).
204
+ let latestInputs;
205
+ let ready = inputObservables === undefined;
206
+ const run = () => {
207
+ recording = emptyDeps();
208
+ try {
209
+ return compute(recorder, latestInputs);
210
+ }
211
+ finally {
212
+ deps = recording;
213
+ recording = null;
214
+ }
215
+ };
216
+ const emit = (value) => {
217
+ if (!hasLast || !equals(last, value)) {
218
+ last = value;
219
+ hasLast = true;
220
+ notify(value);
221
+ }
222
+ };
223
+ // ECS commit gate — recompute when a recorded read could have changed.
224
+ // `observeTransactions` fires once per committed transaction, so a
225
+ // recompute happens at most once per commit, synchronously at the
226
+ // commit boundary (the same cadence as `observe.entity` / the raw
227
+ // component observers a hand-written computed would use). Guarded by
228
+ // `ready` so it never runs before the first dep set is recorded.
229
+ const unobserveTransactions = observeTransactions((result) => {
230
+ if (ready && affected(deps, result)) {
231
+ emit(run());
232
+ }
233
+ });
234
+ if (inputObservables === undefined) {
235
+ emit(run());
236
+ return () => {
237
+ unobserveTransactions();
238
+ };
239
+ }
240
+ // Inputs are subscribed once here at the root — never read inside the
241
+ // recording run — so the set is fixed for the derive's lifetime. Each
242
+ // emission refreshes the injected snapshot and recomputes; the first
243
+ // (all inputs present) is also the derive's first value.
244
+ const unobserveInputs = Observe.fromProperties(inputObservables)((values) => {
245
+ latestInputs = values;
246
+ ready = true;
247
+ emit(run());
248
+ });
249
+ return () => {
250
+ unobserveInputs();
251
+ unobserveTransactions();
252
+ };
253
+ };
254
+ }
255
+ return derive;
256
+ };
257
+ //# sourceMappingURL=observe-derive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observe-derive.js","sourceRoot":"","sources":["../../../src/ecs/database/observe-derive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};