@ecsia/core 0.1.0

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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/bitmask/bitmask.d.ts +21 -0
  4. package/dist/bitmask/bitmask.d.ts.map +1 -0
  5. package/dist/bitmask/bitmask.js +103 -0
  6. package/dist/bitmask/bitmask.js.map +1 -0
  7. package/dist/bitmask/index.d.ts +3 -0
  8. package/dist/bitmask/index.d.ts.map +1 -0
  9. package/dist/bitmask/index.js +2 -0
  10. package/dist/bitmask/index.js.map +1 -0
  11. package/dist/component/accessor.d.ts +40 -0
  12. package/dist/component/accessor.d.ts.map +1 -0
  13. package/dist/component/accessor.js +220 -0
  14. package/dist/component/accessor.js.map +1 -0
  15. package/dist/component/column-set.d.ts +20 -0
  16. package/dist/component/column-set.d.ts.map +1 -0
  17. package/dist/component/column-set.js +60 -0
  18. package/dist/component/column-set.js.map +1 -0
  19. package/dist/component/define.d.ts +23 -0
  20. package/dist/component/define.d.ts.map +1 -0
  21. package/dist/component/define.js +155 -0
  22. package/dist/component/define.js.map +1 -0
  23. package/dist/component/descriptors.d.ts +3 -0
  24. package/dist/component/descriptors.d.ts.map +1 -0
  25. package/dist/component/descriptors.js +147 -0
  26. package/dist/component/descriptors.js.map +1 -0
  27. package/dist/component/index.d.ts +10 -0
  28. package/dist/component/index.d.ts.map +1 -0
  29. package/dist/component/index.js +6 -0
  30. package/dist/component/index.js.map +1 -0
  31. package/dist/component/sidecar.d.ts +58 -0
  32. package/dist/component/sidecar.d.ts.map +1 -0
  33. package/dist/component/sidecar.js +136 -0
  34. package/dist/component/sidecar.js.map +1 -0
  35. package/dist/config.d.ts +55 -0
  36. package/dist/config.d.ts.map +1 -0
  37. package/dist/config.js +70 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/entity/codec.d.ts +45 -0
  40. package/dist/entity/codec.d.ts.map +1 -0
  41. package/dist/entity/codec.js +53 -0
  42. package/dist/entity/codec.js.map +1 -0
  43. package/dist/entity/index-allocator.d.ts +46 -0
  44. package/dist/entity/index-allocator.d.ts.map +1 -0
  45. package/dist/entity/index-allocator.js +121 -0
  46. package/dist/entity/index-allocator.js.map +1 -0
  47. package/dist/entity/index.d.ts +13 -0
  48. package/dist/entity/index.d.ts.map +1 -0
  49. package/dist/entity/index.js +7 -0
  50. package/dist/entity/index.js.map +1 -0
  51. package/dist/entity/record.d.ts +28 -0
  52. package/dist/entity/record.d.ts.map +1 -0
  53. package/dist/entity/record.js +42 -0
  54. package/dist/entity/record.js.map +1 -0
  55. package/dist/entity/ref.d.ts +70 -0
  56. package/dist/entity/ref.d.ts.map +1 -0
  57. package/dist/entity/ref.js +104 -0
  58. package/dist/entity/ref.js.map +1 -0
  59. package/dist/entity/reservation.d.ts +12 -0
  60. package/dist/entity/reservation.d.ts.map +1 -0
  61. package/dist/entity/reservation.js +28 -0
  62. package/dist/entity/reservation.js.map +1 -0
  63. package/dist/entity/store.d.ts +60 -0
  64. package/dist/entity/store.d.ts.map +1 -0
  65. package/dist/entity/store.js +193 -0
  66. package/dist/entity/store.js.map +1 -0
  67. package/dist/env.d.ts +2 -0
  68. package/dist/env.d.ts.map +1 -0
  69. package/dist/env.js +12 -0
  70. package/dist/env.js.map +1 -0
  71. package/dist/ids.d.ts +9 -0
  72. package/dist/ids.d.ts.map +1 -0
  73. package/dist/ids.js +8 -0
  74. package/dist/ids.js.map +1 -0
  75. package/dist/index.d.ts +29 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +33 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/inspect-surface.d.ts +27 -0
  80. package/dist/inspect-surface.d.ts.map +1 -0
  81. package/dist/inspect-surface.js +14 -0
  82. package/dist/inspect-surface.js.map +1 -0
  83. package/dist/internal.d.ts +19 -0
  84. package/dist/internal.d.ts.map +1 -0
  85. package/dist/internal.js +19 -0
  86. package/dist/internal.js.map +1 -0
  87. package/dist/memory/allocU32.d.ts +25 -0
  88. package/dist/memory/allocU32.d.ts.map +1 -0
  89. package/dist/memory/allocU32.js +95 -0
  90. package/dist/memory/allocU32.js.map +1 -0
  91. package/dist/memory/buffers.d.ts +94 -0
  92. package/dist/memory/buffers.d.ts.map +1 -0
  93. package/dist/memory/buffers.js +308 -0
  94. package/dist/memory/buffers.js.map +1 -0
  95. package/dist/memory/index.d.ts +7 -0
  96. package/dist/memory/index.d.ts.map +1 -0
  97. package/dist/memory/index.js +4 -0
  98. package/dist/memory/index.js.map +1 -0
  99. package/dist/memory/layout.d.ts +37 -0
  100. package/dist/memory/layout.d.ts.map +1 -0
  101. package/dist/memory/layout.js +116 -0
  102. package/dist/memory/layout.js.map +1 -0
  103. package/dist/query/compile.d.ts +73 -0
  104. package/dist/query/compile.d.ts.map +1 -0
  105. package/dist/query/compile.js +158 -0
  106. package/dist/query/compile.js.map +1 -0
  107. package/dist/query/engine.d.ts +48 -0
  108. package/dist/query/engine.d.ts.map +1 -0
  109. package/dist/query/engine.js +230 -0
  110. package/dist/query/engine.js.map +1 -0
  111. package/dist/query/index.d.ts +8 -0
  112. package/dist/query/index.d.ts.map +1 -0
  113. package/dist/query/index.js +10 -0
  114. package/dist/query/index.js.map +1 -0
  115. package/dist/query/live-query.d.ts +122 -0
  116. package/dist/query/live-query.d.ts.map +1 -0
  117. package/dist/query/live-query.js +543 -0
  118. package/dist/query/live-query.js.map +1 -0
  119. package/dist/query/sparse-set.d.ts +18 -0
  120. package/dist/query/sparse-set.d.ts.map +1 -0
  121. package/dist/query/sparse-set.js +126 -0
  122. package/dist/query/sparse-set.js.map +1 -0
  123. package/dist/reactivity/change-version.d.ts +19 -0
  124. package/dist/reactivity/change-version.d.ts.map +1 -0
  125. package/dist/reactivity/change-version.js +76 -0
  126. package/dist/reactivity/change-version.js.map +1 -0
  127. package/dist/reactivity/index.d.ts +12 -0
  128. package/dist/reactivity/index.d.ts.map +1 -0
  129. package/dist/reactivity/index.js +12 -0
  130. package/dist/reactivity/index.js.map +1 -0
  131. package/dist/reactivity/log.d.ts +83 -0
  132. package/dist/reactivity/log.d.ts.map +1 -0
  133. package/dist/reactivity/log.js +260 -0
  134. package/dist/reactivity/log.js.map +1 -0
  135. package/dist/reactivity/observer-commands.d.ts +40 -0
  136. package/dist/reactivity/observer-commands.d.ts.map +1 -0
  137. package/dist/reactivity/observer-commands.js +111 -0
  138. package/dist/reactivity/observer-commands.js.map +1 -0
  139. package/dist/reactivity/observers.d.ts +50 -0
  140. package/dist/reactivity/observers.d.ts.map +1 -0
  141. package/dist/reactivity/observers.js +127 -0
  142. package/dist/reactivity/observers.js.map +1 -0
  143. package/dist/reactivity/reactivity.d.ts +141 -0
  144. package/dist/reactivity/reactivity.d.ts.map +1 -0
  145. package/dist/reactivity/reactivity.js +479 -0
  146. package/dist/reactivity/reactivity.js.map +1 -0
  147. package/dist/reactivity/structural-journal.d.ts +30 -0
  148. package/dist/reactivity/structural-journal.d.ts.map +1 -0
  149. package/dist/reactivity/structural-journal.js +77 -0
  150. package/dist/reactivity/structural-journal.js.map +1 -0
  151. package/dist/registry.d.ts +26 -0
  152. package/dist/registry.d.ts.map +1 -0
  153. package/dist/registry.js +58 -0
  154. package/dist/registry.js.map +1 -0
  155. package/dist/serialize-surface.d.ts +170 -0
  156. package/dist/serialize-surface.d.ts.map +1 -0
  157. package/dist/serialize-surface.js +6 -0
  158. package/dist/serialize-surface.js.map +1 -0
  159. package/dist/storage/archetype.d.ts +38 -0
  160. package/dist/storage/archetype.d.ts.map +1 -0
  161. package/dist/storage/archetype.js +47 -0
  162. package/dist/storage/archetype.js.map +1 -0
  163. package/dist/storage/cold-store.d.ts +41 -0
  164. package/dist/storage/cold-store.d.ts.map +1 -0
  165. package/dist/storage/cold-store.js +100 -0
  166. package/dist/storage/cold-store.js.map +1 -0
  167. package/dist/storage/index.d.ts +10 -0
  168. package/dist/storage/index.d.ts.map +1 -0
  169. package/dist/storage/index.js +5 -0
  170. package/dist/storage/index.js.map +1 -0
  171. package/dist/storage/signature.d.ts +27 -0
  172. package/dist/storage/signature.d.ts.map +1 -0
  173. package/dist/storage/signature.js +115 -0
  174. package/dist/storage/signature.js.map +1 -0
  175. package/dist/storage/storage.d.ts +72 -0
  176. package/dist/storage/storage.d.ts.map +1 -0
  177. package/dist/storage/storage.js +192 -0
  178. package/dist/storage/storage.js.map +1 -0
  179. package/dist/storage/store.d.ts +88 -0
  180. package/dist/storage/store.d.ts.map +1 -0
  181. package/dist/storage/store.js +473 -0
  182. package/dist/storage/store.js.map +1 -0
  183. package/dist/util/stable-index.d.ts +29 -0
  184. package/dist/util/stable-index.d.ts.map +1 -0
  185. package/dist/util/stable-index.js +51 -0
  186. package/dist/util/stable-index.js.map +1 -0
  187. package/dist/world.d.ts +262 -0
  188. package/dist/world.d.ts.map +1 -0
  189. package/dist/world.js +831 -0
  190. package/dist/world.js.map +1 -0
  191. package/package.json +52 -0
@@ -0,0 +1,104 @@
1
+ // The pooled EntityRef identity carrier: ONE object per world, NOT per
2
+ // entity, NOT a Proxy. This module owns its identity fields and location resolution; the
3
+ // read/write accessor split is installed on the prototype here but its body
4
+ // delegates to a pluggable AccessorResolver the world injects, so this module stays free of any
5
+ // dependency on the component/storage layers.
6
+ import { NO_ENTITY } from './codec.js';
7
+ import { ARCHETYPE_NONE } from './record.js';
8
+ /**
9
+ * EntityRef is a POOLED SINGLETON: there is exactly ONE instance per world, and `world.entity(h)`
10
+ * re-points (rebinds) that one object at `h` and returns it — it does NOT allocate a fresh ref per
11
+ * call. The pooling contract is therefore:
12
+ *
13
+ * - The handle you bind is valid only until the NEXT `world.entity(...)` call, or until the bound
14
+ * entity is despawned / structurally moved. A reference captured in a local and used across
15
+ * either event aliases the wrong row.
16
+ * - Do NOT hold the ref across a `world.entity()` call. Re-resolve with `world.entity(h)` at the
17
+ * point of use, or extract the plain field values you need into locals first.
18
+ *
19
+ * To turn the classic silent-corruption footgun into a loud failure, the RANDOM-ACCESS read()/write()
20
+ * accessors verify on every call that the currently-bound handle is still alive and still occupies the
21
+ * location this ref cached at bind time; a stale/recycled/moved binding THROWS instead of reading or
22
+ * writing the wrong entity's row. (Query-iteration element accessors are a separate, hot path and are
23
+ * intentionally NOT guarded here.)
24
+ */
25
+ export class EntityRef {
26
+ #records;
27
+ #resolver = null;
28
+ #isAlive = null;
29
+ __handle = NO_ENTITY;
30
+ __archetypeId = ARCHETYPE_NONE;
31
+ __row = 0;
32
+ /** Set when bound via `{ lenient: true }` (e.g. an onRemove observer resolving a just-despawned entity). */
33
+ __lenient = false;
34
+ constructor(records) {
35
+ this.#records = records;
36
+ }
37
+ /** Public, frozen-surface accessor for the bound handle (the non-`__` form referenced by ). */
38
+ get handle() {
39
+ return this.__handle;
40
+ }
41
+ /** Inject the world's accessor resolver (world wiring). */
42
+ __setResolver(resolver) {
43
+ this.#resolver = resolver;
44
+ }
45
+ /** Inject the world's liveness probe so random-access read/write can fail loud on a stale binding. */
46
+ __setLiveness(isAlive) {
47
+ this.#isAlive = isAlive;
48
+ }
49
+ /** Re-point this pooled ref at a (validated-alive) handle and resolve its location. */
50
+ __bind(handle, lenient = false) {
51
+ this.__handle = handle;
52
+ this.__lenient = lenient;
53
+ const loc = this.#records.resolveLocation(handle);
54
+ this.__archetypeId = loc.archetypeId;
55
+ this.__row = loc.row;
56
+ return this;
57
+ }
58
+ /**
59
+ * Assert the ref's cached binding still names the SAME live entity at the SAME location. Throws an
60
+ * actionable error if the bound entity was despawned/recycled (liveness) or structurally moved since
61
+ * bind (location drift) — both of which mean a held ref would otherwise read/write the wrong row.
62
+ */
63
+ #assertFresh(verb) {
64
+ // A lenient binding deliberately resolves a possibly-dead/shuffled slot (e.g. an onRemove observer
65
+ // reading the just-despawned entity's last values); the caller has opted out of the guard.
66
+ if (this.__lenient)
67
+ return;
68
+ const isAlive = this.#isAlive;
69
+ if (isAlive !== null && !isAlive(this.__handle)) {
70
+ throw new Error(`EntityRef.${verb}(): entity ${this.__handle} is no longer alive. The pooled EntityRef is rebound by ` +
71
+ `world.entity(...) and invalidated on despawn — do not hold it across calls; re-resolve via world.entity(h).`);
72
+ }
73
+ const loc = this.#records.resolveLocation(this.__handle);
74
+ if (loc.archetypeId !== this.__archetypeId || loc.row !== this.__row) {
75
+ throw new Error(`EntityRef.${verb}(): stale binding for entity ${this.__handle} — it moved since this ref was resolved ` +
76
+ `(another world.entity(...) call or a structural change rebound the pooled ref). Re-resolve via world.entity(h).`);
77
+ }
78
+ }
79
+ /**
80
+ * Deeply-`Readonly` view of `def`'s fields for this entity.
81
+ * The `const C` parameter recovers the inferred `ReadOf<C>` so a random-access read is typed without
82
+ * caller casts; assignment through it is a TS2540 compile error. RANDOM-ACCESS path: guarded against a
83
+ * stale/recycled/moved pooled binding (see class jsdoc).
84
+ */
85
+ read(def) {
86
+ if (this.#resolver === null)
87
+ throw new Error('EntityRef.read: no accessor resolver installed');
88
+ this.#assertFresh('read');
89
+ return this.#resolver.resolveRead(this.__handle, this.__archetypeId, this.__row, def);
90
+ }
91
+ /**
92
+ * Mutable, write-tracked `WriteView<S>` of `def`'s fields for this entity. The `const C` parameter
93
+ * recovers the inferred `WriteOf<C>` so a random-access write is typed without caller casts; every
94
+ * setter additionally drives the write log (the only tracked-mutation path). RANDOM-ACCESS path:
95
+ * guarded against a stale/recycled/moved pooled binding (see class jsdoc).
96
+ */
97
+ write(def) {
98
+ if (this.#resolver === null)
99
+ throw new Error('EntityRef.write: no accessor resolver installed');
100
+ this.#assertFresh('write');
101
+ return this.#resolver.resolveWrite(this.__handle, this.__archetypeId, this.__row, def);
102
+ }
103
+ }
104
+ //# sourceMappingURL=ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref.js","sourceRoot":"","sources":["../../src/entity/ref.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { EntityHandle } from './codec.js';
2
+ import type { EntityIndex } from './index-allocator.js';
3
+ export interface EntityReservation {
4
+ /** Pre-fully-formed handles, ready to use. */
5
+ readonly handles: readonly EntityHandle[];
6
+ readonly workerIndex: number;
7
+ }
8
+ /** Reserve `count` entity handles for `workerIndex` to consume mid-wave. Serial-phase only. */
9
+ export declare function reserveEntityBlock(index: EntityIndex, workerIndex: number, count: number): EntityReservation;
10
+ /** After the wave, reclaim any handles the worker did not consume (returns them to the pool). */
11
+ export declare function returnReservedIds(index: EntityIndex, reservation: EntityReservation, consumedCount: number): void;
12
+ //# sourceMappingURL=reservation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reservation.d.ts","sourceRoot":"","sources":["../../src/entity/reservation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAEvD,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED,+FAA+F;AAC/F,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAS5G;AAED,iGAAiG;AACjG,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAWjH"}
@@ -0,0 +1,28 @@
1
+ // The worker-ID reservation handshake. v1 ships the LAYOUT plus the
2
+ // single-thread path: the main thread reserves a block by calling the ordinary serial
3
+ // `allocEntity`, so the entities are fully alive the instant they are reserved. The
4
+ // Atomics.sub-on-reservedHead worker take is the v2 path exercised at.
5
+ /** Reserve `count` entity handles for `workerIndex` to consume mid-wave. Serial-phase only. */
6
+ export function reserveEntityBlock(index, workerIndex, count) {
7
+ if (!Number.isInteger(count) || count < 0) {
8
+ throw new RangeError(`reserveEntityBlock count must be a non-negative integer; got ${count}`);
9
+ }
10
+ const handles = [];
11
+ for (let i = 0; i < count; i++) {
12
+ handles.push(index.allocEntity());
13
+ }
14
+ return { handles, workerIndex };
15
+ }
16
+ /** After the wave, reclaim any handles the worker did not consume (returns them to the pool). */
17
+ export function returnReservedIds(index, reservation, consumedCount) {
18
+ if (!Number.isInteger(consumedCount) || consumedCount < 0 || consumedCount > reservation.handles.length) {
19
+ throw new RangeError(`returnReservedIds consumedCount must be an integer in [0, ${reservation.handles.length}]; got ${consumedCount}`);
20
+ }
21
+ // Free the unconsumed tail in reverse so the free-list reissues them LIFO.
22
+ for (let i = reservation.handles.length - 1; i >= consumedCount; i--) {
23
+ const h = reservation.handles[i];
24
+ if (h !== undefined && index.isAlive(h))
25
+ index.freeEntity(h);
26
+ }
27
+ }
28
+ //# sourceMappingURL=reservation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reservation.js","sourceRoot":"","sources":["../../src/entity/reservation.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,sFAAsF;AACtF,oFAAoF;AACpF,uEAAuE;AAWvE,+FAA+F;AAC/F,MAAM,UAAU,kBAAkB,CAAC,KAAkB,EAAE,WAAmB,EAAE,KAAa;IACvF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,UAAU,CAAC,gEAAgE,KAAK,EAAE,CAAC,CAAA;IAC/F,CAAC;IACD,MAAM,OAAO,GAAmB,EAAE,CAAA;IAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAA;AACjC,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,iBAAiB,CAAC,KAAkB,EAAE,WAA8B,EAAE,aAAqB;IACzG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,aAAa,GAAG,CAAC,IAAI,aAAa,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACxG,MAAM,IAAI,UAAU,CAClB,6DAA6D,WAAW,CAAC,OAAO,CAAC,MAAM,UAAU,aAAa,EAAE,CACjH,CAAA;IACH,CAAC;IACD,2EAA2E;IAC3E,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,aAAa,EAAE,CAAC,EAAE,EAAE,CAAC;QACrE,MAAM,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,CAAC,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC9D,CAAC;AACH,CAAC"}
@@ -0,0 +1,60 @@
1
+ import type { EntityGeneration, EntityHandle, EntityIndex as EntityIndexBrand, HandleLayout } from './codec.js';
2
+ import { EntityIndex } from './index-allocator.js';
3
+ import { ARCHETYPE_NONE, EntityRecord } from './record.js';
4
+ import { EntityRef } from './ref.js';
5
+ import type { AccessorResolver } from './ref.js';
6
+ export interface EntityStoreConfig {
7
+ readonly layout: HandleLayout;
8
+ readonly maxEntities: number;
9
+ readonly shared: boolean;
10
+ }
11
+ export interface HandleStats {
12
+ readonly aliveCount: number;
13
+ readonly minted: number;
14
+ readonly capacity: number;
15
+ readonly wrapTimeFormula: string;
16
+ }
17
+ export declare class EntityStore {
18
+ #private;
19
+ readonly layout: HandleLayout;
20
+ constructor(config: EntityStoreConfig);
21
+ setLifecycle(hooks: {
22
+ onSpawn(handle: EntityHandle): void;
23
+ onDespawn(handle: EntityHandle): void;
24
+ }): void;
25
+ spawn(): EntityHandle;
26
+ despawn(handle: EntityHandle): void;
27
+ isAlive(handle: EntityHandle): boolean;
28
+ entity(handle: EntityHandle, opts?: {
29
+ lenient?: boolean;
30
+ }): EntityRef;
31
+ encodeHandle(index: number, generation: number): EntityHandle;
32
+ decodeHandle(handle: EntityHandle): {
33
+ index: EntityIndexBrand;
34
+ generation: EntityGeneration;
35
+ };
36
+ /** Install the read/write accessor resolver onto the pooled ref (world wiring). */
37
+ setAccessorResolver(resolver: AccessorResolver): void;
38
+ get index(): EntityIndex;
39
+ get records(): EntityRecord;
40
+ /**
41
+ * The two entity-record region backings (archetypeId, archetypeRow), for the worker bootstrap
42
+ * manifest. A worker resolves an entity's (archetypeId, row) from these shared
43
+ * regions — reading ARCHETYPE TABLES ONLY, never the bitmask. Backings are SAB when
44
+ * threaded + isolation present; otherwise plain AB (the worker path then has nothing to share).
45
+ */
46
+ sharedRecordRegions(): {
47
+ archetypeId: ArrayBufferLike;
48
+ archetypeRow: ArrayBufferLike;
49
+ };
50
+ /** The full (generational) handle occupying `index` — the query engine's index→handle resolver. */
51
+ handleOfIndex(index: number): EntityHandle;
52
+ /** index → its (archetypeId, row) location — the query engine's resolveLocation seam. */
53
+ locationOfIndex(index: number): {
54
+ archetypeId: number;
55
+ row: number;
56
+ };
57
+ handleStats(): HandleStats;
58
+ }
59
+ export { ARCHETYPE_NONE };
60
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/entity/store.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,IAAI,gBAAgB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC/G,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAElD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAOhD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;CACjC;AAED,qBAAa,WAAW;;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;gBAoBjB,MAAM,EAAE,iBAAiB;IAqErC,YAAY,CAAC,KAAK,EAAE;QAAE,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI;IAIzG,KAAK,IAAI,YAAY;IAYrB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IASnC,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO;IAItC,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS;IASrE,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY;IAU7D,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG;QAAE,KAAK,EAAE,gBAAgB,CAAC;QAAC,UAAU,EAAE,gBAAgB,CAAA;KAAE;IAO7F,mFAAmF;IACnF,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAIrD,IAAI,KAAK,IAAI,WAAW,CAEvB;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED;;;;;OAKG;IACH,mBAAmB,IAAI;QAAE,WAAW,EAAE,eAAe,CAAC;QAAC,YAAY,EAAE,eAAe,CAAA;KAAE;IAOtF,mGAAmG;IACnG,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY;IAI1C,yFAAyF;IACzF,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAIpE,WAAW,IAAI,WAAW;CAmB3B;AAED,OAAO,EAAE,cAAc,EAAE,CAAA"}
@@ -0,0 +1,193 @@
1
+ // Construction wiring for the entity layer: allocate the five
2
+ // identity/record flat arrays through memory.allocU32, sized by maxEntities, and assemble the
3
+ // EntityIndex + EntityRecord + pooled EntityRef. Lives between the world facade and the
4
+ // per-module primitives so world.ts stays a thin delegator.
5
+ import { allocU32 } from '../memory/index.js';
6
+ import { handleIndex, makeHandle } from './codec.js';
7
+ import { EntityIndex } from './index-allocator.js';
8
+ import { ARCHETYPE_NONE, EntityRecord } from './record.js';
9
+ import { EntityRef } from './ref.js';
10
+ // EMPTY_ARCHETYPE_ID is normatively; the empty-signature archetype is
11
+ // dense id 0 (a real archetype, distinct from the ARCHETYPE_NONE sentinel). Storage lands at;
12
+ // until then a freshly spawned entity records archetype 0 at row 0.
13
+ const EMPTY_ARCHETYPE_ID = 0;
14
+ export class EntityStore {
15
+ layout;
16
+ #index;
17
+ #records;
18
+ #ref;
19
+ #maxEntities;
20
+ /** Hard mint ceiling: the index space, minus the reserved NO_ENTITY slot when threaded. */
21
+ #ceiling;
22
+ /** Current addressable length; doubles on growth up to `#ceiling`. */
23
+ #addressable;
24
+ #wrapWarned = false;
25
+ // Held only so growth re-reads/re-publishes the layout structs from the same regions.
26
+ #regions;
27
+ constructor(config) {
28
+ this.layout = config.layout;
29
+ this.#maxEntities = config.maxEntities;
30
+ this.#addressable = config.maxEntities;
31
+ // The index space is [0, maxIndex]; when threaded, maxIndex is reserved for the NO_ENTITY
32
+ // sentinel so a minted+wrapped handle can never alias 0xffffffff.
33
+ this.#ceiling = config.shared ? config.layout.maxIndex : config.layout.maxIndex + 1;
34
+ const opts = { shared: config.shared, maxLength: config.layout.capacity };
35
+ this.#regions = {
36
+ sparse: allocU32(config.maxEntities, opts),
37
+ dense: allocU32(config.maxEntities, opts),
38
+ generation: allocU32(config.maxEntities, opts),
39
+ recordArchetypeId: allocU32(config.maxEntities, opts),
40
+ recordArchetypeRow: allocU32(config.maxEntities, opts),
41
+ };
42
+ const bounds = { addressable: this.#addressable, ceiling: this.#ceiling };
43
+ this.#index = new EntityIndex(config.layout, this.#indexArrays(), bounds, (need) => this.#grow(need));
44
+ this.#records = new EntityRecord(config.layout, this.#recordArrays());
45
+ this.#ref = new EntityRef(this.#records);
46
+ this.#ref.__setLiveness((handle) => this.#index.isAlive(handle));
47
+ }
48
+ /**
49
+ * Grow every identity/record region to at least `need` elements (doubling), then
50
+ * re-publish the widened views to the index/record/ref structs and return the new addressable
51
+ * length. Returns the unchanged length when growth is impossible (capped at `#ceiling`), which
52
+ * makes the allocator throw CapacityExceeded. Serial-phase only.
53
+ */
54
+ #grow(need) {
55
+ if (need <= this.#addressable)
56
+ return this.#addressable;
57
+ const cap = Math.min(this.#ceiling, this.layout.capacity);
58
+ if (this.#addressable >= cap)
59
+ return this.#addressable;
60
+ let next = this.#addressable;
61
+ while (next < need)
62
+ next = Math.min(cap, next * 2);
63
+ if (next <= this.#addressable)
64
+ return this.#addressable;
65
+ for (const region of Object.values(this.#regions))
66
+ region.grow(next);
67
+ this.#addressable = next;
68
+ // Length-tracking views over resizable buffers widen in place, but re-publishing keeps the
69
+ // non-resizable fallback path correct too.
70
+ this.#index.rebind(this.#indexArrays(), next);
71
+ this.#records.rebind(this.#recordArrays());
72
+ return next;
73
+ }
74
+ #indexArrays() {
75
+ return {
76
+ sparse: this.#regions.sparse.view,
77
+ dense: this.#regions.dense.view,
78
+ generation: this.#regions.generation.view,
79
+ };
80
+ }
81
+ #recordArrays() {
82
+ return {
83
+ recordArchetypeId: this.#regions.recordArchetypeId.view,
84
+ recordArchetypeRow: this.#regions.recordArchetypeRow.view,
85
+ };
86
+ }
87
+ /**
88
+ * Storage hook installed at: places a freshly-minted handle into its initial archetype (via
89
+ * allocRow) and commits the record; on despawn it performs the + bitmask clear
90
+ * BEFORE identity invalidation. Until installed, spawn falls back to the empty-archetype row 0.
91
+ */
92
+ #lifecycle = null;
93
+ setLifecycle(hooks) {
94
+ this.#lifecycle = hooks;
95
+ }
96
+ spawn() {
97
+ const handle = this.#index.allocEntity();
98
+ if (this.#lifecycle !== null) {
99
+ this.#lifecycle.onSpawn(handle);
100
+ }
101
+ else {
102
+ const index = handleIndex(handle, this.layout);
103
+ this.#records.commitRecord(index, EMPTY_ARCHETYPE_ID, 0);
104
+ }
105
+ this.#warnOnWrap();
106
+ return handle;
107
+ }
108
+ despawn(handle) {
109
+ if (!this.#index.isAlive(handle))
110
+ return;
111
+ // Storage runs removeRow + bitmask clear here; identity invalidation (freeEntity) runs
112
+ // LAST so the above could still resolve the dying entity's location.
113
+ this.#lifecycle?.onDespawn(handle);
114
+ this.#index.freeEntity(handle);
115
+ this.#warnOnWrap();
116
+ }
117
+ isAlive(handle) {
118
+ return this.#index.isAlive(handle);
119
+ }
120
+ entity(handle, opts) {
121
+ if (!this.#index.isAlive(handle)) {
122
+ // Dead handles throw unless the caller opts into lenient resolution (it then binds
123
+ // the stale handle anyway; the location words are whatever the slot last held).
124
+ if (opts?.lenient !== true)
125
+ throw new Error(`entity(${handle}): handle is not alive`);
126
+ }
127
+ return this.#ref.__bind(handle, opts?.lenient === true);
128
+ }
129
+ encodeHandle(index, generation) {
130
+ if (index < 0 || index > this.layout.maxIndex) {
131
+ throw new RangeError(`index out of range [0, ${this.layout.maxIndex}]; got ${index}`);
132
+ }
133
+ if (generation < 0 || generation > this.layout.maxGeneration) {
134
+ throw new RangeError(`generation out of range [0, ${this.layout.maxGeneration}]; got ${generation}`);
135
+ }
136
+ return makeHandle(index, generation, this.layout);
137
+ }
138
+ decodeHandle(handle) {
139
+ return {
140
+ index: ((handle & this.layout.indexMask) >>> 0),
141
+ generation: ((handle >>> this.layout.generationShift) & this.layout.generationMask),
142
+ };
143
+ }
144
+ /** Install the read/write accessor resolver onto the pooled ref (world wiring). */
145
+ setAccessorResolver(resolver) {
146
+ this.#ref.__setResolver(resolver);
147
+ }
148
+ get index() {
149
+ return this.#index;
150
+ }
151
+ get records() {
152
+ return this.#records;
153
+ }
154
+ /**
155
+ * The two entity-record region backings (archetypeId, archetypeRow), for the worker bootstrap
156
+ * manifest. A worker resolves an entity's (archetypeId, row) from these shared
157
+ * regions — reading ARCHETYPE TABLES ONLY, never the bitmask. Backings are SAB when
158
+ * threaded + isolation present; otherwise plain AB (the worker path then has nothing to share).
159
+ */
160
+ sharedRecordRegions() {
161
+ return {
162
+ archetypeId: this.#regions.recordArchetypeId.backing,
163
+ archetypeRow: this.#regions.recordArchetypeRow.backing,
164
+ };
165
+ }
166
+ /** The full (generational) handle occupying `index` — the query engine's index→handle resolver. */
167
+ handleOfIndex(index) {
168
+ return this.#index.handleOfIndex(index);
169
+ }
170
+ /** index → its (archetypeId, row) location — the query engine's resolveLocation seam. */
171
+ locationOfIndex(index) {
172
+ return { archetypeId: this.#records.archetypeIdOf(index), row: this.#records.rowOf(index) };
173
+ }
174
+ handleStats() {
175
+ return {
176
+ aliveCount: this.#index.aliveCount,
177
+ minted: this.#index.denseLen,
178
+ capacity: this.#maxEntities,
179
+ wrapTimeFormula: `2^${this.layout.generationBits} / recycleRate`,
180
+ };
181
+ }
182
+ #warnOnWrap() {
183
+ if (this.#wrapWarned || !this.#index.wrapped)
184
+ return;
185
+ this.#wrapWarned = true;
186
+ // Dev-mode-only signal so users can raise generationBits; never a production throw.
187
+ if (typeof console !== 'undefined') {
188
+ console.warn(`[ecsia] entity generation wrapped (generationBits=${this.layout.generationBits}); stale-handle aliasing window reached — consider raising generationBits`);
189
+ }
190
+ }
191
+ }
192
+ export { ARCHETYPE_NONE };
193
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/entity/store.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const IS_DEV: boolean;
2
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,EAAE,OAMjB,CAAA"}
package/dist/env.js ADDED
@@ -0,0 +1,12 @@
1
+ // Portable dev-mode detection. Evaluated ONCE: browsers have no `process` (typeof guard),
2
+ // permission-less Deno THROWS on env access (try/catch), Node reads NODE_ENV. Defaults to
3
+ // dev=true where unknowable — extra guards beat silent production behavior in a sandbox.
4
+ export const IS_DEV = (() => {
5
+ try {
6
+ return typeof process === 'undefined' || process.env?.['NODE_ENV'] !== 'production';
7
+ }
8
+ catch {
9
+ return true;
10
+ }
11
+ })();
12
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,0FAA0F;AAC1F,yFAAyF;AACzF,MAAM,CAAC,MAAM,MAAM,GAAY,CAAC,GAAG,EAAE;IACnC,IAAI,CAAC;QACH,OAAO,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,YAAY,CAAA;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC,CAAC,EAAE,CAAA"}
package/dist/ids.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /** A dense component type id. Branded so raw numbers can't be passed where a ComponentId is required. */
2
+ export type ComponentId = number & {
3
+ readonly __ecsiaComponentId: unique symbol;
4
+ };
5
+ /** The reserved "no component" sentinel. Also the shape-log CREATE/DESTROY marker. */
6
+ export declare const NO_COMPONENT: ComponentId;
7
+ /** First id handed out to user components; everything below is reserved. */
8
+ export declare const FIRST_USER_COMPONENT_ID: ComponentId;
9
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAIA,yGAAyG;AACzG,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,kBAAkB,EAAE,OAAO,MAAM,CAAA;CAAE,CAAA;AAEjF,sFAAsF;AACtF,eAAO,MAAM,YAAY,EAAQ,WAAW,CAAA;AAE5C,4EAA4E;AAC5E,eAAO,MAAM,uBAAuB,EAAQ,WAAW,CAAA"}
package/dist/ids.js ADDED
@@ -0,0 +1,8 @@
1
+ // Reserved ComponentId space (C3).
2
+ // ComponentId 0 is NEVER a user component: it is the NO_COMPONENT sentinel, doubling as the
3
+ // CREATE/DESTROY shape-log "no component" marker and the changeVersion sentinel.
4
+ /** The reserved "no component" sentinel. Also the shape-log CREATE/DESTROY marker. */
5
+ export const NO_COMPONENT = 0;
6
+ /** First id handed out to user components; everything below is reserved. */
7
+ export const FIRST_USER_COMPONENT_ID = 1;
8
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,4FAA4F;AAC5F,iFAAiF;AAKjF,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAgB,CAAA;AAE5C,4EAA4E;AAC5E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAgB,CAAA"}
@@ -0,0 +1,29 @@
1
+ export type { ComponentId } from './ids.js';
2
+ export { ConfigError, resolveOptions } from './config.js';
3
+ export type { WorldOptions, ResolvedWorldOptions, ResolvedReactivityOptions, ReactivityOptions, SchedulerOptions, ObserverCadence, ChangeTracking, WorkerOption, } from './config.js';
4
+ export { createWorld } from './world.js';
5
+ export type { World, WorldPhase } from './world.js';
6
+ export { NO_ENTITY, NULL_ENTITY, isNoEntity, EntityRef, handleIndex } from './entity/index.js';
7
+ export type { EntityHandle, EntityIndex, HandleLayout } from './entity/index.js';
8
+ export { defineComponent, defineTag, } from './component/index.js';
9
+ export { createStableIndex } from './util/stable-index.js';
10
+ export type { StableIndex } from './util/stable-index.js';
11
+ export { ShapeKind, onAdd, onRemove, onChange, } from './reactivity/index.js';
12
+ export type { ObserverHandle, ObserverTerm, ObserverContext, } from './reactivity/index.js';
13
+ export type { SharedHandleManifest, ColumnGrowthNotice, ColumnGrowthLog } from './memory/index.js';
14
+ export { vec, vec2, vec3, vec4, staticString, object, field, MAX_QUERY_ARITY, read, write, has, without, optional, } from '@ecsia/schema';
15
+ export type { ScalarToken, VecToken, StaticStringToken, ObjectToken, RichToken, FieldToken, FieldSpec, FieldValue, Schema, ComponentDef, ComponentOptions, ReadView, WriteView, ReadOf, WriteOf, SchemaOf, QueryTerm, QueryElement, Query, QueryChunk, LooseQuery, Has, HasWrite, RelationDef, RelationOptions, PairDef, WildcardToken, Tick, } from '@ecsia/schema';
16
+ export { NO_COMPONENT, FIRST_USER_COMPONENT_ID } from './ids.js';
17
+ export type { WorldApplySurface, RelationsHost } from './world.js';
18
+ export type { SerializationSurface, SerializeArchetype, SerializeComponentColumns, SerializeComponentMeta, SerializeRichField, SerializePair, SerializeRelationProvider, SerializeStructuralRecord, } from './serialize-surface.js';
19
+ export type { InspectSurface, InspectArchetype, InspectQuery } from './inspect-surface.js';
20
+ export { makeHandleLayout, ARCHETYPE_NONE, reserveEntityBlock, returnReservedIds } from './entity/index.js';
21
+ export type { EntityReservation } from './entity/index.js';
22
+ export { encodeEid, decodeEid, elementCtor, elementBytes, makeColumnLayout, } from './memory/index.js';
23
+ export type { ColumnKey, RegionKey, RuntimeCapabilities, Column, ElementKind, TypedArray, ColumnLayout, } from './memory/index.js';
24
+ export { buildColumnSet, bindAccessorRow } from './component/index.js';
25
+ export type { ColumnSet } from './component/index.js';
26
+ export type { StorageStrategy } from '@ecsia/schema';
27
+ export type { ResolvedPair } from './query/index.js';
28
+ export { IS_DEV } from './env.js';
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ // @ecsia/core — the single-threaded kernel. PUBLIC surface.
2
+ //
3
+ // This barrel is split into two sections:
4
+ // • PUBLIC — the documented user/umbrella surface: createWorld + config, component/tag definition,
5
+ // entity sentinels, reactivity observer builders, and the schema token/inference re-exports the
6
+ // umbrella (ecsia) curates.
7
+ // • INTERNAL (cross-package) — kernel seams that sibling packages (@ecsia/{relations,serialization})
8
+ // import via '@ecsia/core'. They are NOT user API, but removing them would break those siblings,
9
+ // so they stay exported here under a clearly-marked banner rather than on a hidden subpath
10
+ // (package.json#exports maps only `.`).
11
+ //
12
+ // The rest of the kernel (store/bitmask/registry/query-engine/memory-backing classes + low-level
13
+ // schema helpers) is implementation detail and lives in ./internal.ts — NOT re-exported here. This
14
+ // package's own tests reach those through a relative `../src/internal.js` import.
15
+ export { ConfigError, resolveOptions } from './config.js';
16
+ export { createWorld } from './world.js';
17
+ export { NO_ENTITY, NULL_ENTITY, isNoEntity, EntityRef, handleIndex } from './entity/index.js';
18
+ export { defineComponent, defineTag, } from './component/index.js';
19
+ export { createStableIndex } from './util/stable-index.js';
20
+ export { ShapeKind, onAdd, onRemove, onChange, } from './reactivity/index.js';
21
+ // Schema surface re-exported so users import tokens/inference from @ecsia/core (the umbrella).
22
+ export { vec, vec2, vec3, vec4, staticString, object, field, MAX_QUERY_ARITY, read, write, has, without, optional, } from '@ecsia/schema';
23
+ // ===========================================================================
24
+ // INTERNAL (cross-package) — imported by @ecsia/{relations,serialization} via '@ecsia/core'.
25
+ // NOT user API; kept here only because those siblings need them and exports map only `.`.
26
+ // ===========================================================================
27
+ export { NO_COMPONENT, FIRST_USER_COMPONENT_ID } from './ids.js';
28
+ export { makeHandleLayout, ARCHETYPE_NONE, reserveEntityBlock, returnReservedIds } from './entity/index.js';
29
+ export { encodeEid, decodeEid, elementCtor, elementBytes, makeColumnLayout, } from './memory/index.js';
30
+ export { buildColumnSet, bindAccessorRow } from './component/index.js';
31
+ // INTERNAL (cross-package): portable dev-mode flag
32
+ export { IS_DEV } from './env.js';
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,EAAE;AACF,0CAA0C;AAC1C,mGAAmG;AACnG,gGAAgG;AAChG,4BAA4B;AAC5B,qGAAqG;AACrG,iGAAiG;AACjG,2FAA2F;AAC3F,wCAAwC;AACxC,EAAE;AACF,iGAAiG;AACjG,mGAAmG;AACnG,kFAAkF;AAOlF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAWzD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG9F,OAAO,EACL,eAAe,EACf,SAAS,GACV,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAG1D,OAAO,EACL,SAAS,EACT,KAAK,EACL,QAAQ,EACR,QAAQ,GACT,MAAM,uBAAuB,CAAA;AAS9B,+FAA+F;AAC/F,OAAO,EACL,GAAG,EACH,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,eAAe,EACf,IAAI,EACJ,KAAK,EACL,GAAG,EACH,OAAO,EACP,QAAQ,GACT,MAAM,eAAe,CAAA;AAiCtB,8EAA8E;AAC9E,6FAA6F;AAC7F,0FAA0F;AAC1F,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAA;AAgBhE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAG3G,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAW1B,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAMtE,mDAAmD;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,27 @@
1
+ import type { ComponentId } from '@ecsia/schema';
2
+ /** One archetype's identity census — INCLUDING cold + empty archetypes (the `__serialize` gap). */
3
+ export interface InspectArchetype {
4
+ readonly id: number;
5
+ /** The sorted canonical signature (ComponentIds, including tag/pair/presence ids). */
6
+ readonly signature: readonly ComponentId[];
7
+ readonly count: number;
8
+ /** false = hot (column-backed tables); true = cold (lazily-materialized, archetype-storage ). */
9
+ readonly cold: boolean;
10
+ }
11
+ /** One live (compiled, cached) query's introspectable shape — the QueryEngine enumeration gap. */
12
+ export interface InspectQuery {
13
+ /** The raw QueryTerm[] the query was compiled from (read/write/has/without/optional terms). */
14
+ readonly terms: readonly unknown[];
15
+ /** Number of archetypes the query currently matches. */
16
+ readonly matchedArchetypes: number;
17
+ /** Current live match count (entities satisfying the query). */
18
+ readonly size: number;
19
+ }
20
+ /** The read-only datum surface @ecsia/devtools drives. All members are serial / main-thread, pure reads. */
21
+ export interface InspectSurface {
22
+ /** Every archetype (hot AND cold, including empty), in id-ascending order. */
23
+ archetypes(): readonly InspectArchetype[];
24
+ /** Every live (cached) query, in creation order. Empty before the first `world.query(...)`. */
25
+ queries(): readonly InspectQuery[];
26
+ }
27
+ //# sourceMappingURL=inspect-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-surface.d.ts","sourceRoot":"","sources":["../src/inspect-surface.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,mGAAmG;AACnG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,sFAAsF;IACtF,QAAQ,CAAC,SAAS,EAAE,SAAS,WAAW,EAAE,CAAA;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,iGAAiG;IACjG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACvB;AAED,kGAAkG;AAClG,MAAM,WAAW,YAAY;IAC3B,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;IAClC,wDAAwD;IACxD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED,4GAA4G;AAC5G,MAAM,WAAW,cAAc;IAC7B,8EAA8E;IAC9E,UAAU,IAAI,SAAS,gBAAgB,EAAE,CAAA;IACzC,+FAA+F;IAC/F,OAAO,IAAI,SAAS,YAAY,EAAE,CAAA;CACnC"}
@@ -0,0 +1,14 @@
1
+ // The read-only introspection seam @ecsia/devtools reads through, exposed on World as `__inspect`.
2
+ // Keeps the dependency direction acyclic: devtools imports @ecsia/core for this surface; core NEVER
3
+ // imports devtools. Everything here is serial / main-thread, read-only, and side-effect-free — a pure
4
+ // view over already-live state.
5
+ //
6
+ // WHY a NEW seam (not `__serialize`): the existing SerializationSurface deliberately exposes ONLY the
7
+ // data a snapshot needs — its `archetypes()` skips COLD and EMPTY archetypes (world.ts ), and there
8
+ // is no live-query enumeration anywhere on the public/`__` surface (the QueryEngine's `liveQueries`
9
+ // getter is class-private to core). Those two data are genuinely unreachable for an inspector that wants
10
+ // the FULL archetype census (with the hot/cold flag) and the active query set. Everything else the
11
+ // inspector reports (component metadata, rich fields, relations, alive/capacity counts) is already
12
+ // reachable via `__serialize` + `world.options`, so this seam stays minimal: just the two gaps.
13
+ export {};
14
+ //# sourceMappingURL=inspect-surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-surface.js","sourceRoot":"","sources":["../src/inspect-surface.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,oGAAoG;AACpG,sGAAsG;AACtG,gCAAgC;AAChC,EAAE;AACF,sGAAsG;AACtG,oGAAoG;AACpG,oGAAoG;AACpG,yGAAyG;AACzG,mGAAmG;AACnG,mGAAmG;AACnG,gGAAgG"}