@adobe/data 0.9.79 → 0.9.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ecs/database/database-read.type-test.d.ts +1 -0
- package/dist/ecs/database/database-read.type-test.js +195 -0
- package/dist/ecs/database/database-read.type-test.js.map +1 -0
- package/dist/ecs/database/database.d.ts +49 -0
- package/dist/ecs/database/database.js.map +1 -1
- package/dist/ecs/database/observe-derive.d.ts +11 -0
- package/dist/ecs/database/observe-derive.js +226 -0
- package/dist/ecs/database/observe-derive.js.map +1 -0
- package/dist/ecs/database/observe-derive.test.d.ts +1 -0
- package/dist/ecs/database/observe-derive.test.js +166 -0
- package/dist/ecs/database/observe-derive.test.js.map +1 -0
- package/dist/ecs/database/observed/create-observed-database.js +2 -0
- package/dist/ecs/database/observed/create-observed-database.js.map +1 -1
- package/dist/ecs/database/observed/observed-database.d.ts +1 -0
- package/dist/ecs/store/core/core.d.ts +22 -1
- package/dist/ecs/store/core/create-core.js +19 -2
- package/dist/ecs/store/core/create-core.js.map +1 -1
- package/dist/observe/from-keys.d.ts +25 -0
- package/dist/observe/from-keys.js +80 -0
- package/dist/observe/from-keys.js.map +1 -0
- package/dist/observe/from-keys.test.d.ts +1 -0
- package/dist/observe/from-keys.test.js +140 -0
- package/dist/observe/from-keys.test.js.map +1 -0
- package/dist/observe/public.d.ts +1 -0
- package/dist/observe/public.js +1 -0
- package/dist/observe/public.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/references/data-lit/package.json +1 -1
- package/references/data-lit-tictactoe/package.json +1 -1
- package/references/data-react/package.json +1 -1
- package/references/data-react-hello/package.json +1 -1
- package/references/data-react-pixie/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,195 @@
|
|
|
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
|
+
// ============================================================================
|
|
83
|
+
// derive — NEGATIVE: everything the read projection removes
|
|
84
|
+
// ============================================================================
|
|
85
|
+
function deriveNegative() {
|
|
86
|
+
db.derive((d) => {
|
|
87
|
+
// @ts-expect-error observers are not exposed — a derive subscribes to its own reads
|
|
88
|
+
return d.observe;
|
|
89
|
+
});
|
|
90
|
+
db.derive((d) => {
|
|
91
|
+
// @ts-expect-error transactions / writes are not exposed to a read-only derive
|
|
92
|
+
return d.transactions;
|
|
93
|
+
});
|
|
94
|
+
db.derive((d) => {
|
|
95
|
+
// @ts-expect-error queryArchetypes (raw column access) is not exposed
|
|
96
|
+
return d.queryArchetypes;
|
|
97
|
+
});
|
|
98
|
+
db.derive((d) => {
|
|
99
|
+
// @ts-expect-error locate (row access) is not exposed
|
|
100
|
+
return d.locate;
|
|
101
|
+
});
|
|
102
|
+
db.derive((d) => {
|
|
103
|
+
// @ts-expect-error per-archetype column access is not exposed
|
|
104
|
+
return d.archetypes.Foo.columns;
|
|
105
|
+
});
|
|
106
|
+
db.derive((d) => {
|
|
107
|
+
// @ts-expect-error per-archetype rowCount (table access) is not exposed
|
|
108
|
+
return d.archetypes.Foo.rowCount;
|
|
109
|
+
});
|
|
110
|
+
db.derive((d) => {
|
|
111
|
+
// @ts-expect-error per-archetype insert (write) is not exposed
|
|
112
|
+
return d.archetypes.Foo.insert;
|
|
113
|
+
});
|
|
114
|
+
db.derive((d) => {
|
|
115
|
+
// @ts-expect-error index observe is not exposed — a derive subscribes for you
|
|
116
|
+
return d.indexes.byX.observe;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function readProjectionPositive() {
|
|
120
|
+
const v = rd.get(0, "x");
|
|
121
|
+
const ids = rd.select(["x"]);
|
|
122
|
+
const excluded = rd.select(["x"], { exclude: ["y"] });
|
|
123
|
+
const fr = rd.resources.frameRate;
|
|
124
|
+
rd.archetypes.Foo.components.has("x");
|
|
125
|
+
const found = rd.indexes.byX.find({ x: 1 });
|
|
126
|
+
void v;
|
|
127
|
+
void ids;
|
|
128
|
+
void excluded;
|
|
129
|
+
void fr;
|
|
130
|
+
void found;
|
|
131
|
+
}
|
|
132
|
+
function readProjectionNegative() {
|
|
133
|
+
// @ts-expect-error observers omitted from the read projection
|
|
134
|
+
rd.observe;
|
|
135
|
+
// @ts-expect-error index observe omitted from the read projection
|
|
136
|
+
rd.indexes.byX.observe;
|
|
137
|
+
// @ts-expect-error table/column access omitted from the read projection
|
|
138
|
+
rd.archetypes.Foo.columns;
|
|
139
|
+
// @ts-expect-error transactions omitted from the read projection
|
|
140
|
+
rd.transactions;
|
|
141
|
+
// @ts-expect-error `where` (value-dependent) omitted from the read projection's select
|
|
142
|
+
rd.select(["x"], { where: { x: 1 } });
|
|
143
|
+
// @ts-expect-error `order` (value-dependent) omitted from the read projection's select
|
|
144
|
+
rd.select(["x"], { order: { x: true } });
|
|
145
|
+
}
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Read distributes over an INTERSECTION (Option A). The structural definition
|
|
148
|
+
// means `Database.Read<A & B>` merges both members' read surfaces, and because
|
|
149
|
+
// `derive` passes `Database.Read<this>`, a derive on an intersection receiver
|
|
150
|
+
// sees indexes + resources + archetypes from BOTH members — so a consumer of a
|
|
151
|
+
// composed `A & B` database (e.g. an indexed core intersected with a
|
|
152
|
+
// resource-computed layer) never needs to cast.
|
|
153
|
+
// ============================================================================
|
|
154
|
+
const pluginA = Database.Plugin.create({
|
|
155
|
+
components: { a: { type: "number" } },
|
|
156
|
+
resources: { ra: { type: "number", default: 0 } },
|
|
157
|
+
archetypes: { AOnly: ["a"] },
|
|
158
|
+
indexes: { byA: { key: "a" } },
|
|
159
|
+
});
|
|
160
|
+
const pluginB = Database.Plugin.create({
|
|
161
|
+
components: { b: { type: "string" } },
|
|
162
|
+
resources: { rb: { type: "string", default: "" } },
|
|
163
|
+
archetypes: { BOnly: ["b"] },
|
|
164
|
+
indexes: { byB: { key: "b" } },
|
|
165
|
+
});
|
|
166
|
+
const dbA = Database.create(pluginA);
|
|
167
|
+
const dbB = Database.create(pluginB);
|
|
168
|
+
function intersectionRead() {
|
|
169
|
+
// both members' resources
|
|
170
|
+
const _ra = rb2.resources.ra;
|
|
171
|
+
const _rb = rb2.resources.rb;
|
|
172
|
+
// both members' indexes (find-only)
|
|
173
|
+
const _fa = rb2.indexes.byA.find({ a: 1 });
|
|
174
|
+
const _fb = rb2.indexes.byB.find({ b: "x" });
|
|
175
|
+
// both members' archetype identities
|
|
176
|
+
rb2.archetypes.AOnly.components.has("a");
|
|
177
|
+
rb2.archetypes.BOnly.components.has("b");
|
|
178
|
+
void _ra;
|
|
179
|
+
void _rb;
|
|
180
|
+
void _fa;
|
|
181
|
+
void _fb;
|
|
182
|
+
}
|
|
183
|
+
function intersectionDerive() {
|
|
184
|
+
// `Database.Read<this>` on an intersection receiver → merged surface.
|
|
185
|
+
both.derive((d) => {
|
|
186
|
+
const _ra = d.resources.ra;
|
|
187
|
+
const _rb = d.resources.rb;
|
|
188
|
+
d.indexes.byA.find({ a: 1 });
|
|
189
|
+
d.indexes.byB.find({ b: "x" });
|
|
190
|
+
void _ra;
|
|
191
|
+
void _rb;
|
|
192
|
+
return 0;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
//# 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,20 @@ 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
|
+
* (e.g. `IndexedCoreDatabase & ResourceComputedDatabase`) resolves to the
|
|
152
|
+
* merged read surface — consumers never need to cast.
|
|
153
|
+
*/
|
|
154
|
+
derive<T>(compute: (db: Database.Read<this>) => T): Observe<T>;
|
|
141
155
|
/**
|
|
142
156
|
* Wipes all entities and resets all resources to their plugin defaults,
|
|
143
157
|
* preserving database identity (observers, transaction wrappers, sync
|
|
@@ -209,12 +223,47 @@ export declare namespace Database {
|
|
|
209
223
|
* expansion that amplifies TS7056 serialization overflow in deep extends chains.
|
|
210
224
|
*/
|
|
211
225
|
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']>>;
|
|
226
|
+
/**
|
|
227
|
+
* The read-only projection of a Database that a `db.derive` callback
|
|
228
|
+
* receives. It exposes only the auto-trackable read surface —
|
|
229
|
+
* - value reads: `get`, `read`, `select`
|
|
230
|
+
* - resource reads: `resources`
|
|
231
|
+
* - index lookups: `indexes.<name>.find` / `findRange` / `get`
|
|
232
|
+
* - archetype identity: `archetypes.<name>.components` / `id`
|
|
233
|
+
* — and structurally OMITS everything a derived computation must not touch:
|
|
234
|
+
* - `observe` (a derive subscribes to what it reads for you)
|
|
235
|
+
* - transactions / actions / any write
|
|
236
|
+
* - direct table access: `queryArchetypes`, `locate`, and per-archetype
|
|
237
|
+
* `columns` / `rowCount` / `insert` / row reads
|
|
238
|
+
* - `services` / `computed` / lifecycle (`extend`, `reset`, `toData`, …)
|
|
239
|
+
*
|
|
240
|
+
* Because the surface is narrowed structurally, misuse is a compile error
|
|
241
|
+
* rather than a value that must be guarded / thrown on at runtime.
|
|
242
|
+
*/
|
|
243
|
+
type Read<DB extends Database<any, any, any, any, any, any, any, any, any>> = Pick<DB, "get" | "read" | "resources"> & {
|
|
244
|
+
select(include: readonly string[] | ReadonlySet<string>, options?: {
|
|
245
|
+
readonly exclude?: readonly string[];
|
|
246
|
+
}): readonly Entity[];
|
|
247
|
+
readonly indexes: {
|
|
248
|
+
readonly [K in keyof DB["indexes"]]: Omit<DB["indexes"][K], "observe">;
|
|
249
|
+
};
|
|
250
|
+
readonly archetypes: {
|
|
251
|
+
readonly [K in keyof DB["archetypes"]]: Pick<DB["archetypes"][K], "components" | "id">;
|
|
252
|
+
};
|
|
253
|
+
};
|
|
212
254
|
const create: typeof createDatabase;
|
|
213
255
|
const is: (value: unknown) => value is Database;
|
|
214
256
|
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
257
|
type Index<C extends Components = any> = StoreIndex<C, any, any, any>;
|
|
216
258
|
namespace Index {
|
|
217
259
|
type Handle<C extends Components, I extends StoreIndex<C, any, any, any>> = StoreIndex.Handle<C, I>;
|
|
260
|
+
/**
|
|
261
|
+
* The index handle as exposed to a `db.derive` callback: the
|
|
262
|
+
* synchronous lookups (`find` / `findRange` / `get`) only. `observe` is
|
|
263
|
+
* removed — a derive subscribes to the reads it performs automatically, so
|
|
264
|
+
* calling `observe` from inside one is a category error.
|
|
265
|
+
*/
|
|
266
|
+
type ReadHandle<C extends Components, I extends StoreIndex<C, any, any, any>> = Omit<Handle<C, I>, "observe">;
|
|
218
267
|
}
|
|
219
268
|
namespace Archetype {
|
|
220
269
|
/**
|
|
@@ -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;
|
|
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;AAoNtD,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,11 @@
|
|
|
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>>) => <T>(compute: (db: any) => T) => Observe<T>;
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { equals } from "../../equals.js";
|
|
3
|
+
const emptyDeps = () => ({
|
|
4
|
+
entityWhole: new Set(),
|
|
5
|
+
entityComponents: new Map(),
|
|
6
|
+
columns: new Set(),
|
|
7
|
+
setReads: [],
|
|
8
|
+
});
|
|
9
|
+
const watchComponent = (deps, entity, component) => {
|
|
10
|
+
let set = deps.entityComponents.get(entity);
|
|
11
|
+
if (set === undefined) {
|
|
12
|
+
deps.entityComponents.set(entity, (set = new Set()));
|
|
13
|
+
}
|
|
14
|
+
set.add(component);
|
|
15
|
+
};
|
|
16
|
+
const affected = (deps, result) => {
|
|
17
|
+
const { changedEntities, changedComponents, changedArchetypes } = result;
|
|
18
|
+
const { entityWhole, entityComponents, columns, setReads } = deps;
|
|
19
|
+
// Entity deps: iterate the (usually small) *changed* set and probe the
|
|
20
|
+
// watched sets — O(|changedEntities|), not O(|watched|). A commit touches a
|
|
21
|
+
// handful of entities regardless of how many a derive reads.
|
|
22
|
+
if (entityWhole.size > 0 || entityComponents.size > 0) {
|
|
23
|
+
for (const [entity, values] of changedEntities) {
|
|
24
|
+
if (entityWhole.has(entity)) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
const watched = entityComponents.get(entity);
|
|
28
|
+
if (watched === undefined) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (values === null) {
|
|
32
|
+
// entity deleted — any scoped read of it is now stale
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
for (const component of Object.keys(values)) {
|
|
36
|
+
if (watched.has(component)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Resource column deps.
|
|
43
|
+
if (columns.size > 0 && !changedComponents.isDisjointFrom(columns)) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
// Set-valued reads: cheap gate, then recompute-and-compare this one read.
|
|
47
|
+
for (const dep of setReads) {
|
|
48
|
+
if (dep.kind === "index") {
|
|
49
|
+
if (changedComponents.isDisjointFrom(dep.readColumns)) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (changedArchetypes.size === 0) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!equals(dep.last, dep.recompute())) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Builds `db.derive`. A single read-recording wrapper is constructed
|
|
64
|
+
* once and shared across every derive on this database: because a `compute`
|
|
65
|
+
* body is synchronous and performs no writes or nested derives, no two runs can
|
|
66
|
+
* overlap, so the wrapper's "currently-recording" target is reset per run and
|
|
67
|
+
* safely reused.
|
|
68
|
+
*/
|
|
69
|
+
export const createDerive = (store, observeTransactions) => {
|
|
70
|
+
// The active recording target, non-null only for the duration of one
|
|
71
|
+
// synchronous `compute` run.
|
|
72
|
+
let recording = null;
|
|
73
|
+
// `resources` and `indexes` are built lazily and cached: the store's
|
|
74
|
+
// resource and index maps are populated during database construction, which
|
|
75
|
+
// finishes AFTER this factory is created, but before any derive can run.
|
|
76
|
+
let resourcesRecorder = null;
|
|
77
|
+
const buildResources = () => {
|
|
78
|
+
const out = {};
|
|
79
|
+
for (const name of Object.keys(store.resources)) {
|
|
80
|
+
Object.defineProperty(out, name, {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get() {
|
|
83
|
+
if (recording) {
|
|
84
|
+
recording.columns.add(name);
|
|
85
|
+
}
|
|
86
|
+
return store.resources[name];
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
};
|
|
92
|
+
let indexesRecorder = null;
|
|
93
|
+
const buildIndexes = () => {
|
|
94
|
+
const out = {};
|
|
95
|
+
const storeIndexes = (store.indexes ?? {});
|
|
96
|
+
for (const name of Object.keys(storeIndexes)) {
|
|
97
|
+
const handle = storeIndexes[name];
|
|
98
|
+
const readColumns = new Set(handle.readColumns ?? []);
|
|
99
|
+
// Record a per-bucket dependency: the exact result this lookup
|
|
100
|
+
// returned, plus a thunk to recompute it. `affected` gates on the
|
|
101
|
+
// read columns then recompute-compares, so an unrelated bucket's
|
|
102
|
+
// change recomputes this (cheap Map-get + slice) to an identical
|
|
103
|
+
// sequence and is suppressed — the derive body never re-runs.
|
|
104
|
+
const recordLookup = (result, recompute) => {
|
|
105
|
+
if (recording) {
|
|
106
|
+
recording.setReads.push({ kind: "index", readColumns, recompute, last: result });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const readHandle = {
|
|
110
|
+
find: (arg) => {
|
|
111
|
+
const result = handle.find(arg);
|
|
112
|
+
recordLookup(result, () => handle.find(arg));
|
|
113
|
+
return result;
|
|
114
|
+
},
|
|
115
|
+
findRange: (arg) => {
|
|
116
|
+
const result = handle.findRange(arg);
|
|
117
|
+
recordLookup(result, () => handle.findRange(arg));
|
|
118
|
+
return result;
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
if (typeof handle.get === "function") {
|
|
122
|
+
readHandle.get = (arg) => {
|
|
123
|
+
const result = handle.get(arg);
|
|
124
|
+
recordLookup(result, () => handle.get(arg));
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
out[name] = readHandle;
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
};
|
|
132
|
+
// The read-recording projection handed to `compute`. Delegates every read to
|
|
133
|
+
// the real store and records the dependency it implies. Typed loosely here;
|
|
134
|
+
// the precise `Database.Read<…>` surface is enforced at the public
|
|
135
|
+
// `db.derive` boundary.
|
|
136
|
+
const recorder = {
|
|
137
|
+
get: (entity, component) => {
|
|
138
|
+
if (recording) {
|
|
139
|
+
watchComponent(recording, entity, component);
|
|
140
|
+
}
|
|
141
|
+
return store.get(entity, component);
|
|
142
|
+
},
|
|
143
|
+
read: (entity, archetypeOrComponents) => {
|
|
144
|
+
if (recording) {
|
|
145
|
+
if (archetypeOrComponents === undefined) {
|
|
146
|
+
recording.entityWhole.add(entity);
|
|
147
|
+
}
|
|
148
|
+
else if (Array.isArray(archetypeOrComponents)) {
|
|
149
|
+
for (const component of archetypeOrComponents) {
|
|
150
|
+
watchComponent(recording, entity, component);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
for (const component of archetypeOrComponents.components) {
|
|
155
|
+
watchComponent(recording, entity, component);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return store.read(entity, archetypeOrComponents);
|
|
160
|
+
},
|
|
161
|
+
// Presence select only — `include` + `exclude`, no `where` / `order`
|
|
162
|
+
// (value-dependent options are omitted from the derive surface; use a
|
|
163
|
+
// declared index for value-keyed or ordered reactive reads). Recorded as
|
|
164
|
+
// a set-valued read gated on `changedArchetypes`: the result is
|
|
165
|
+
// membership-shaped, so a pure value write can never move it, and an
|
|
166
|
+
// unrelated migration recompute-compares to the same sequence.
|
|
167
|
+
select: (include, options) => {
|
|
168
|
+
const exclude = options?.exclude;
|
|
169
|
+
const args = [include, exclude === undefined ? undefined : { exclude }];
|
|
170
|
+
const run = () => store.select(...args);
|
|
171
|
+
const result = run();
|
|
172
|
+
if (recording) {
|
|
173
|
+
recording.setReads.push({ kind: "select", recompute: run, last: result });
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
},
|
|
177
|
+
get resources() {
|
|
178
|
+
return (resourcesRecorder ??= buildResources());
|
|
179
|
+
},
|
|
180
|
+
get indexes() {
|
|
181
|
+
return (indexesRecorder ??= buildIndexes());
|
|
182
|
+
},
|
|
183
|
+
// Archetype identity (components / id) is static, so reading it records
|
|
184
|
+
// no dependency; delegate to the real archetypes.
|
|
185
|
+
archetypes: store.archetypes,
|
|
186
|
+
};
|
|
187
|
+
return (compute) => (notify) => {
|
|
188
|
+
let last;
|
|
189
|
+
let hasLast = false;
|
|
190
|
+
let deps = emptyDeps();
|
|
191
|
+
const run = () => {
|
|
192
|
+
recording = emptyDeps();
|
|
193
|
+
try {
|
|
194
|
+
return compute(recorder);
|
|
195
|
+
}
|
|
196
|
+
finally {
|
|
197
|
+
deps = recording;
|
|
198
|
+
recording = null;
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
const emit = (value) => {
|
|
202
|
+
if (!hasLast || !equals(last, value)) {
|
|
203
|
+
last = value;
|
|
204
|
+
hasLast = true;
|
|
205
|
+
notify(value);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
emit(run());
|
|
209
|
+
// `observeTransactions` fires once per committed transaction, so a
|
|
210
|
+
// recompute happens at most once per commit. Emit synchronously at the
|
|
211
|
+
// commit boundary — the same cadence as `observe.entity` / the raw
|
|
212
|
+
// component observers a hand-written computed would use — rather than
|
|
213
|
+
// deferring to a microtask, which would coalesce several commits in one
|
|
214
|
+
// turn (e.g. a burst of ephemeral drag commits) into a single emission
|
|
215
|
+
// and starve consumers that route per commit.
|
|
216
|
+
const unobserve = observeTransactions((result) => {
|
|
217
|
+
if (affected(deps, result)) {
|
|
218
|
+
emit(run());
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return () => {
|
|
222
|
+
unobserve();
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
//# 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 {};
|