@vworlds/vecs 1.0.15 → 1.0.17

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 (181) hide show
  1. package/README.md +249 -119
  2. package/dist/component.d.ts +52 -76
  3. package/dist/component.js +60 -45
  4. package/dist/component.js.map +1 -1
  5. package/dist/component_meta.d.ts +98 -0
  6. package/dist/component_meta.js +65 -0
  7. package/dist/component_meta.js.map +1 -0
  8. package/dist/dsl.d.ts +46 -34
  9. package/dist/dsl.js +459 -61
  10. package/dist/dsl.js.map +1 -1
  11. package/dist/entity/entity.base.d.ts +57 -0
  12. package/dist/entity/entity.base.js +81 -0
  13. package/dist/entity/entity.base.js.map +1 -0
  14. package/dist/entity/entity.components.d.ts +117 -0
  15. package/dist/entity/entity.components.js +244 -0
  16. package/dist/entity/entity.components.js.map +1 -0
  17. package/dist/entity/entity.d.ts +35 -0
  18. package/dist/entity/entity.identity.d.ts +8 -0
  19. package/dist/entity/entity.identity.js +15 -0
  20. package/dist/entity/entity.identity.js.map +1 -0
  21. package/dist/entity/entity.js +33 -0
  22. package/dist/entity/entity.js.map +1 -0
  23. package/dist/entity/entity.lifecycle.d.ts +12 -0
  24. package/dist/entity/entity.lifecycle.js +111 -0
  25. package/dist/entity/entity.lifecycle.js.map +1 -0
  26. package/dist/entity/entity.queries.d.ts +3 -0
  27. package/dist/entity/entity.queries.js +33 -0
  28. package/dist/entity/entity.queries.js.map +1 -0
  29. package/dist/entity/entity.relationships.d.ts +9 -0
  30. package/dist/entity/entity.relationships.js +74 -0
  31. package/dist/entity/entity.relationships.js.map +1 -0
  32. package/dist/entity/index.d.ts +2 -0
  33. package/dist/entity/index.js +3 -0
  34. package/dist/entity/index.js.map +1 -0
  35. package/dist/filter.d.ts +27 -8
  36. package/dist/filter.js +33 -18
  37. package/dist/filter.js.map +1 -1
  38. package/dist/index.d.ts +13 -5
  39. package/dist/index.js +13 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/inject.d.ts +80 -0
  42. package/dist/inject.js +270 -0
  43. package/dist/inject.js.map +1 -0
  44. package/dist/module.d.ts +23 -0
  45. package/dist/module.js +17 -0
  46. package/dist/module.js.map +1 -0
  47. package/dist/modules/identity.d.ts +15 -0
  48. package/dist/modules/identity.js +41 -0
  49. package/dist/modules/identity.js.map +1 -0
  50. package/dist/modules/singleton.d.ts +26 -0
  51. package/dist/modules/singleton.js +41 -0
  52. package/dist/modules/singleton.js.map +1 -0
  53. package/dist/package.json +12 -1
  54. package/dist/phase.d.ts +2 -2
  55. package/dist/query/index.d.ts +6 -0
  56. package/dist/query/index.js +5 -0
  57. package/dist/query/index.js.map +1 -0
  58. package/dist/query/query.00.base.d.ts +23 -0
  59. package/dist/query/query.00.base.js +77 -0
  60. package/dist/query/query.00.base.js.map +1 -0
  61. package/dist/query/query.01.reactive.d.ts +7 -0
  62. package/dist/query/query.01.reactive.js +58 -0
  63. package/dist/query/query.01.reactive.js.map +1 -0
  64. package/dist/query/query.02.lifecycle.d.ts +6 -0
  65. package/dist/query/query.02.lifecycle.js +63 -0
  66. package/dist/query/query.02.lifecycle.js.map +1 -0
  67. package/dist/query/query.03.tracking.d.ts +15 -0
  68. package/dist/query/query.03.tracking.js +31 -0
  69. package/dist/query/query.03.tracking.js.map +1 -0
  70. package/dist/query/query.04.callbacks.d.ts +14 -0
  71. package/dist/query/query.04.callbacks.js +65 -0
  72. package/dist/query/query.04.callbacks.js.map +1 -0
  73. package/dist/query/query.05.updates.d.ts +14 -0
  74. package/dist/query/query.05.updates.js +81 -0
  75. package/dist/query/query.05.updates.js.map +1 -0
  76. package/dist/query/query.06.predicate.d.ts +13 -0
  77. package/dist/query/query.06.predicate.js +40 -0
  78. package/dist/query/query.06.predicate.js.map +1 -0
  79. package/dist/query/query.07.groups.d.ts +41 -0
  80. package/dist/query/query.07.groups.js +110 -0
  81. package/dist/query/query.07.groups.js.map +1 -0
  82. package/dist/query/query.d.ts +53 -0
  83. package/dist/query/query.js +138 -0
  84. package/dist/query/query.js.map +1 -0
  85. package/dist/relationship.d.ts +19 -0
  86. package/dist/relationship.js +18 -0
  87. package/dist/relationship.js.map +1 -0
  88. package/dist/system.d.ts +37 -23
  89. package/dist/system.js +80 -64
  90. package/dist/system.js.map +1 -1
  91. package/dist/terms/all_term.d.ts +32 -0
  92. package/dist/terms/all_term.js +41 -0
  93. package/dist/terms/all_term.js.map +1 -0
  94. package/dist/terms/any_term.d.ts +33 -0
  95. package/dist/terms/any_term.js +42 -0
  96. package/dist/terms/any_term.js.map +1 -0
  97. package/dist/terms/build.d.ts +62 -0
  98. package/dist/terms/build.js +382 -0
  99. package/dist/terms/build.js.map +1 -0
  100. package/dist/terms/component_term.d.ts +37 -0
  101. package/dist/terms/component_term.js +49 -0
  102. package/dist/terms/component_term.js.map +1 -0
  103. package/dist/terms/empty_term.d.ts +6 -0
  104. package/dist/terms/empty_term.js +12 -0
  105. package/dist/terms/empty_term.js.map +1 -0
  106. package/dist/terms/index.d.ts +11 -0
  107. package/dist/terms/index.js +12 -0
  108. package/dist/terms/index.js.map +1 -0
  109. package/dist/terms/not_term.d.ts +35 -0
  110. package/dist/terms/not_term.js +47 -0
  111. package/dist/terms/not_term.js.map +1 -0
  112. package/dist/terms/only_term.d.ts +47 -0
  113. package/dist/terms/only_term.js +79 -0
  114. package/dist/terms/only_term.js.map +1 -0
  115. package/dist/terms/predicate_term.d.ts +80 -0
  116. package/dist/terms/predicate_term.js +109 -0
  117. package/dist/terms/predicate_term.js.map +1 -0
  118. package/dist/terms/target_term.d.ts +43 -0
  119. package/dist/terms/target_term.js +87 -0
  120. package/dist/terms/target_term.js.map +1 -0
  121. package/dist/terms/term.d.ts +94 -0
  122. package/dist/terms/term.js +202 -0
  123. package/dist/terms/term.js.map +1 -0
  124. package/dist/terms/world_term.d.ts +68 -0
  125. package/dist/terms/world_term.js +99 -0
  126. package/dist/terms/world_term.js.map +1 -0
  127. package/dist/timer.js +2 -2
  128. package/dist/timer.js.map +1 -1
  129. package/dist/util/array_map.js +12 -0
  130. package/dist/util/array_map.js.map +1 -1
  131. package/dist/util/bitset.js +107 -22
  132. package/dist/util/bitset.js.map +1 -1
  133. package/dist/util/dense_set.d.ts +1 -0
  134. package/dist/util/dense_set.js +90 -0
  135. package/dist/util/dense_set.js.map +1 -0
  136. package/dist/util/id_pool.d.ts +30 -0
  137. package/dist/util/id_pool.js +222 -0
  138. package/dist/util/id_pool.js.map +1 -0
  139. package/dist/world/index.d.ts +3 -0
  140. package/dist/world/index.js +3 -0
  141. package/dist/world/index.js.map +1 -0
  142. package/dist/world/world.base.d.ts +6 -0
  143. package/dist/world/world.base.js +21 -0
  144. package/dist/world/world.base.js.map +1 -0
  145. package/dist/world/world.components.d.ts +67 -0
  146. package/dist/world/world.components.js +93 -0
  147. package/dist/world/world.components.js.map +1 -0
  148. package/dist/world/world.d.ts +29 -0
  149. package/dist/world/world.deferred.d.ts +13 -0
  150. package/dist/world/world.deferred.js +93 -0
  151. package/dist/world/world.deferred.js.map +1 -0
  152. package/dist/world/world.entities.d.ts +18 -0
  153. package/dist/world/world.entities.js +97 -0
  154. package/dist/world/world.entities.js.map +1 -0
  155. package/dist/world/world.js +39 -0
  156. package/dist/world/world.js.map +1 -0
  157. package/dist/world/world.modules.d.ts +12 -0
  158. package/dist/world/world.modules.js +21 -0
  159. package/dist/world/world.modules.js.map +1 -0
  160. package/dist/world/world.pipeline.d.ts +21 -0
  161. package/dist/world/world.pipeline.js +106 -0
  162. package/dist/world/world.pipeline.js.map +1 -0
  163. package/dist/world/world.pools.d.ts +9 -0
  164. package/dist/world/world.pools.js +63 -0
  165. package/dist/world/world.pools.js.map +1 -0
  166. package/dist/world/world.queries.d.ts +18 -0
  167. package/dist/world/world.queries.js +101 -0
  168. package/dist/world/world.queries.js.map +1 -0
  169. package/dist/world/world.storage.d.ts +7 -0
  170. package/dist/world/world.storage.js +26 -0
  171. package/dist/world/world.storage.js.map +1 -0
  172. package/package.json +12 -1
  173. package/dist/entity.d.ts +0 -215
  174. package/dist/entity.js +0 -457
  175. package/dist/entity.js.map +0 -1
  176. package/dist/query.d.ts +0 -251
  177. package/dist/query.js +0 -353
  178. package/dist/query.js.map +0 -1
  179. package/dist/world.d.ts +0 -389
  180. package/dist/world.js +0 -631
  181. package/dist/world.js.map +0 -1
@@ -0,0 +1,37 @@
1
+ import type { Entity } from "../entity/index.js";
2
+ import type { World } from "../world/index.js";
3
+ import { Term } from "./term.js";
4
+ /**
5
+ * World-pinned leaf term that matches every entity carrying a specific
6
+ * component type.
7
+ *
8
+ * `ComponentTerm` is the component-presence index. It maintains the live set
9
+ * of entities that have the component identified by `componentEid`. The world
10
+ * routes `add`, `remove`, and `set`/`modified` commands here via the
11
+ * `notifyComponent*` helpers in `build.ts`.
12
+ *
13
+ * - **Membership** events (`componentAdded` / `componentRemoved`) propagate
14
+ * via the standard `_add`/`_delete` path and fan out to all consumers as
15
+ * enter/exit events.
16
+ * - **Data-only** changes (`componentChanged`) emit only a refresh hint via
17
+ * `_emitRefresh`, which wakes predicate terms watching this component
18
+ * without triggering a membership re-evaluation in terms that do not care
19
+ * about component values.
20
+ */
21
+ export declare class ComponentTerm extends Term {
22
+ readonly componentEid: number;
23
+ constructor(world: World, key: string, componentEid: number, onDestroy: (term: Term) => void);
24
+ /** Called by `build.ts` when the component is added to `entity`. */
25
+ componentAdded(entity: Entity): void;
26
+ /**
27
+ * Called by `build.ts` when the component's value changes on `entity`
28
+ * without a membership change.
29
+ *
30
+ * Emits a refresh hint rather than an enter/exit event so that consumers
31
+ * watching for data updates (predicate terms) are woken while
32
+ * membership-only consumers are not disturbed.
33
+ */
34
+ componentChanged(entity: Entity): void;
35
+ /** Called by `build.ts` when the component is removed from `entity`. */
36
+ componentRemoved(entity: Entity): void;
37
+ }
@@ -0,0 +1,49 @@
1
+ import { Term } from "./term.js";
2
+ /**
3
+ * World-pinned leaf term that matches every entity carrying a specific
4
+ * component type.
5
+ *
6
+ * `ComponentTerm` is the component-presence index. It maintains the live set
7
+ * of entities that have the component identified by `componentEid`. The world
8
+ * routes `add`, `remove`, and `set`/`modified` commands here via the
9
+ * `notifyComponent*` helpers in `build.ts`.
10
+ *
11
+ * - **Membership** events (`componentAdded` / `componentRemoved`) propagate
12
+ * via the standard `_add`/`_delete` path and fan out to all consumers as
13
+ * enter/exit events.
14
+ * - **Data-only** changes (`componentChanged`) emit only a refresh hint via
15
+ * `_emitRefresh`, which wakes predicate terms watching this component
16
+ * without triggering a membership re-evaluation in terms that do not care
17
+ * about component values.
18
+ */
19
+ export class ComponentTerm extends Term {
20
+ constructor(world, key, componentEid, onDestroy) {
21
+ super(world, key, "component", true, onDestroy);
22
+ this.componentEid = componentEid;
23
+ this._initializeFromWorld();
24
+ }
25
+ /** Called by `build.ts` when the component is added to `entity`. */
26
+ componentAdded(entity) {
27
+ this._add(entity);
28
+ }
29
+ /**
30
+ * Called by `build.ts` when the component's value changes on `entity`
31
+ * without a membership change.
32
+ *
33
+ * Emits a refresh hint rather than an enter/exit event so that consumers
34
+ * watching for data updates (predicate terms) are woken while
35
+ * membership-only consumers are not disturbed.
36
+ */
37
+ componentChanged(entity) {
38
+ this._emitRefresh(entity);
39
+ }
40
+ /** Called by `build.ts` when the component is removed from `entity`. */
41
+ componentRemoved(entity) {
42
+ this._delete(entity);
43
+ }
44
+ /** @internal */
45
+ _matches(entity) {
46
+ return !entity._destroyed && entity._get(this.componentEid) !== undefined;
47
+ }
48
+ }
49
+ //# sourceMappingURL=component_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component_term.js","sourceRoot":"","sources":["../../src/terms/component_term.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,aAAc,SAAQ,IAAI;IACrC,YACE,KAAY,EACZ,GAAW,EACK,YAAoB,EACpC,SAA+B;QAE/B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAHhC,iBAAY,GAAZ,YAAY,CAAQ;QAIpC,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED,oEAAoE;IAC7D,cAAc,CAAC,MAAc;QAClC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAED;;;;;;;OAOG;IACI,gBAAgB,CAAC,MAAc;QACpC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;IAED,wEAAwE;IACjE,gBAAgB,CAAC,MAAc;QACpC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,MAAc;QAC/B,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,SAAS,CAAC;IAC5E,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { World } from "../world/index.js";
2
+ import { Term } from "./term.js";
3
+ /** World-pinned leaf term that matches no entities; the materialization of `false`. */
4
+ export declare class EmptyTerm extends Term {
5
+ constructor(world: World, key: string, onDestroy: (term: Term) => void);
6
+ }
@@ -0,0 +1,12 @@
1
+ import { Term } from "./term.js";
2
+ /** World-pinned leaf term that matches no entities; the materialization of `false`. */
3
+ export class EmptyTerm extends Term {
4
+ constructor(world, key, onDestroy) {
5
+ super(world, key, "empty", true, onDestroy);
6
+ }
7
+ /** @internal */
8
+ _matches(_entity) {
9
+ return false;
10
+ }
11
+ }
12
+ //# sourceMappingURL=empty_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty_term.js","sourceRoot":"","sources":["../../src/terms/empty_term.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,uFAAuF;AACvF,MAAM,OAAO,SAAU,SAAQ,IAAI;IACjC,YAAmB,KAAY,EAAE,GAAW,EAAE,SAA+B;QAC3E,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,OAAe;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ export { Term, TermEventKind, type TermConsumer, type TermKind } from "./term.js";
2
+ export { WorldTerm } from "./world_term.js";
3
+ export { ComponentTerm } from "./component_term.js";
4
+ export { EmptyTerm } from "./empty_term.js";
5
+ export { AllTerm } from "./all_term.js";
6
+ export { AnyTerm } from "./any_term.js";
7
+ export { NotTerm } from "./not_term.js";
8
+ export { OnlyTerm } from "./only_term.js";
9
+ export { PredicateTerm, type MergedInfo } from "./predicate_term.js";
10
+ export { TargetTerm } from "./target_term.js";
11
+ export { getTerm, getCachedTerm, notifyComponentAdded, notifyComponentChanged, notifyComponentRemoved, notifyEntityCreated, notifyEntityDestroyed, } from "./build.js";
@@ -0,0 +1,12 @@
1
+ export { Term } from "./term.js";
2
+ export { WorldTerm } from "./world_term.js";
3
+ export { ComponentTerm } from "./component_term.js";
4
+ export { EmptyTerm } from "./empty_term.js";
5
+ export { AllTerm } from "./all_term.js";
6
+ export { AnyTerm } from "./any_term.js";
7
+ export { NotTerm } from "./not_term.js";
8
+ export { OnlyTerm } from "./only_term.js";
9
+ export { PredicateTerm } from "./predicate_term.js";
10
+ export { TargetTerm } from "./target_term.js";
11
+ export { getTerm, getCachedTerm, notifyComponentAdded, notifyComponentChanged, notifyComponentRemoved, notifyEntityCreated, notifyEntityDestroyed, } from "./build.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/terms/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmD,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,OAAO,EACP,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,35 @@
1
+ import type { Entity } from "../entity/index.js";
2
+ import type { World } from "../world/index.js";
3
+ import { Term } from "./term.js";
4
+ import type { QueryDSL } from "../dsl.js";
5
+ import type { getTerm as GetTermFn } from "./build.js";
6
+ /**
7
+ * Composite term that matches entities in the world but **not** in a child
8
+ * term.
9
+ *
10
+ * Children: `[worldTerm, child]`. The world leaf provides lifecycle
11
+ * (creation/destruction); the child provides the set to negate.
12
+ */
13
+ export declare class NotTerm extends Term {
14
+ constructor(world: World, key: string, worldTerm: Term, child: Term, onDestroy: (term: Term) => void);
15
+ /**
16
+ * Build a `NotTerm` for the given child DSL.
17
+ *
18
+ * @param world - Owning world.
19
+ * @param childDSL - The DSL expression to negate.
20
+ * @param key - Canonical cache key.
21
+ * @param getTerm - Term canonicalizer / cache accessor.
22
+ * @param onDestroy - Called when the last consumer unsubscribes.
23
+ */
24
+ static build(world: World, childDSL: QueryDSL, key: string, getTerm: typeof GetTermFn, onDestroy: (term: Term) => void): NotTerm;
25
+ /**
26
+ * No-op override: a pure negation term does not need to re-evaluate on a
27
+ * data or shape refresh.
28
+ *
29
+ * `NotTerm` membership flips only when the child's membership changes (a
30
+ * real enter/exit) or when the world emits a lifecycle event — both of
31
+ * which arrive via `onTermEvent`, not `onTermRefresh`. Reacting to refresh
32
+ * hints would cause spurious `_sync` calls with no change in result.
33
+ */
34
+ onTermRefresh(_entity: Entity): void;
35
+ }
@@ -0,0 +1,47 @@
1
+ import { Term } from "./term.js";
2
+ /**
3
+ * Composite term that matches entities in the world but **not** in a child
4
+ * term.
5
+ *
6
+ * Children: `[worldTerm, child]`. The world leaf provides lifecycle
7
+ * (creation/destruction); the child provides the set to negate.
8
+ */
9
+ export class NotTerm extends Term {
10
+ constructor(world, key, worldTerm, child, onDestroy) {
11
+ super(world, key, "not", false, onDestroy);
12
+ this._setChildren([worldTerm, child]);
13
+ this._initializeFromWorld();
14
+ }
15
+ /**
16
+ * Build a `NotTerm` for the given child DSL.
17
+ *
18
+ * @param world - Owning world.
19
+ * @param childDSL - The DSL expression to negate.
20
+ * @param key - Canonical cache key.
21
+ * @param getTerm - Term canonicalizer / cache accessor.
22
+ * @param onDestroy - Called when the last consumer unsubscribes.
23
+ */
24
+ static build(world, childDSL, key, getTerm, onDestroy) {
25
+ const worldTerm = getTerm(world, true);
26
+ const child = getTerm(world, childDSL);
27
+ return new NotTerm(world, key, worldTerm, child, onDestroy);
28
+ }
29
+ /**
30
+ * No-op override: a pure negation term does not need to re-evaluate on a
31
+ * data or shape refresh.
32
+ *
33
+ * `NotTerm` membership flips only when the child's membership changes (a
34
+ * real enter/exit) or when the world emits a lifecycle event — both of
35
+ * which arrive via `onTermEvent`, not `onTermRefresh`. Reacting to refresh
36
+ * hints would cause spurious `_sync` calls with no change in result.
37
+ */
38
+ onTermRefresh(_entity) {
39
+ // Shape/data refreshes do not affect a pure negation unless the child emits
40
+ // a real membership event, or the world emits a lifecycle event.
41
+ }
42
+ /** @internal */
43
+ _matches(entity) {
44
+ return this._children[0].has(entity) && !this._children[1].has(entity);
45
+ }
46
+ }
47
+ //# sourceMappingURL=not_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"not_term.js","sourceRoot":"","sources":["../../src/terms/not_term.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC;;;;;;GAMG;AACH,MAAM,OAAO,OAAQ,SAAQ,IAAI;IAC/B,YACE,KAAY,EACZ,GAAW,EACX,SAAe,EACf,KAAW,EACX,SAA+B;QAE/B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,YAAY,CAAC,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;QACtC,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,CACjB,KAAY,EACZ,QAAkB,EAClB,GAAW,EACX,OAAyB,EACzB,SAA+B;QAE/B,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC;IAED;;;;;;;;OAQG;IACa,aAAa,CAAC,OAAe;QAC3C,4EAA4E;QAC5E,iEAAiE;IACnE,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,MAAc;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACzE,CAAC;CACF"}
@@ -0,0 +1,47 @@
1
+ import type { Entity } from "../entity/index.js";
2
+ import type { World } from "../world/index.js";
3
+ import { Term } from "./term.js";
4
+ import type { getTerm as GetTermFn } from "./build.js";
5
+ /**
6
+ * Composite term that matches entities carrying **exactly** the specified set
7
+ * of component types — no more, no fewer.
8
+ *
9
+ * Internally composed from two children:
10
+ * - `children[0]`: an `AllTerm` (or array shorthand) for the required
11
+ * components, ensuring every listed component is present.
12
+ * - `children[1]`: the world leaf, ensuring the entity is live and
13
+ * non-component.
14
+ *
15
+ * `OnlyTerm` additionally subscribes to the **shape channel** of the world
16
+ * term so it is re-evaluated whenever *any* component is added to or removed
17
+ * from the entity — not just when one of the listed components changes
18
+ * membership. This is necessary because `only` requires `entity.components.size
19
+ * === componentEids.length`; adding an unlisted component must evict the entity
20
+ * even though the `AllTerm` child has not changed.
21
+ */
22
+ export declare class OnlyTerm extends Term {
23
+ private readonly _componentEids;
24
+ constructor(world: World, key: string, allTerm: Term, worldTerm: Term, _componentEids: readonly number[], onDestroy: (term: Term) => void);
25
+ /**
26
+ * Build an `OnlyTerm` for the given component eid list.
27
+ *
28
+ * @param world - Owning world.
29
+ * @param componentEids - Numeric component type ids that must be present and
30
+ * comprise the entire component set.
31
+ * @param key - Canonical cache key.
32
+ * @param getTerm - Term canonicalizer / cache accessor.
33
+ * @param onDestroy - Called when the last consumer unsubscribes.
34
+ */
35
+ static build(world: World, componentEids: readonly number[], key: string, getTerm: typeof GetTermFn, onDestroy: (term: Term) => void): OnlyTerm;
36
+ /**
37
+ * Shape-channel entry point: called directly by `WorldTerm` when the entity's
38
+ * component set changes.
39
+ *
40
+ * Overrides the base `onTermRefresh` to ensure a shape change always
41
+ * triggers a re-evaluation, regardless of which child emitted the hint.
42
+ * Without this override the base implementation would also call `_sync`,
43
+ * but the explicit override makes the intent clear and guards against future
44
+ * base-class changes.
45
+ */
46
+ onTermRefresh(entity: Entity): void;
47
+ }
@@ -0,0 +1,79 @@
1
+ import { Term } from "./term.js";
2
+ import { WorldTerm } from "./world_term.js";
3
+ /**
4
+ * Composite term that matches entities carrying **exactly** the specified set
5
+ * of component types — no more, no fewer.
6
+ *
7
+ * Internally composed from two children:
8
+ * - `children[0]`: an `AllTerm` (or array shorthand) for the required
9
+ * components, ensuring every listed component is present.
10
+ * - `children[1]`: the world leaf, ensuring the entity is live and
11
+ * non-component.
12
+ *
13
+ * `OnlyTerm` additionally subscribes to the **shape channel** of the world
14
+ * term so it is re-evaluated whenever *any* component is added to or removed
15
+ * from the entity — not just when one of the listed components changes
16
+ * membership. This is necessary because `only` requires `entity.components.size
17
+ * === componentEids.length`; adding an unlisted component must evict the entity
18
+ * even though the `AllTerm` child has not changed.
19
+ */
20
+ export class OnlyTerm extends Term {
21
+ constructor(world, key, allTerm, worldTerm, _componentEids, onDestroy) {
22
+ super(world, key, "only", false, onDestroy);
23
+ this._componentEids = _componentEids;
24
+ this._setChildren([allTerm, worldTerm]);
25
+ if (worldTerm instanceof WorldTerm) {
26
+ this._addChildCleanup(worldTerm.subscribeShape(this));
27
+ }
28
+ this._initializeFromWorld();
29
+ }
30
+ /**
31
+ * Build an `OnlyTerm` for the given component eid list.
32
+ *
33
+ * @param world - Owning world.
34
+ * @param componentEids - Numeric component type ids that must be present and
35
+ * comprise the entire component set.
36
+ * @param key - Canonical cache key.
37
+ * @param getTerm - Term canonicalizer / cache accessor.
38
+ * @param onDestroy - Called when the last consumer unsubscribes.
39
+ */
40
+ static build(world, componentEids, key, getTerm, onDestroy) {
41
+ // Build the inner all-term for the component set, then the world leaf.
42
+ const allTerm = getTerm(world, componentEids);
43
+ const worldTerm = getTerm(world, true);
44
+ return new OnlyTerm(world, key, allTerm, worldTerm, componentEids, onDestroy);
45
+ }
46
+ /**
47
+ * Shape-channel entry point: called directly by `WorldTerm` when the entity's
48
+ * component set changes.
49
+ *
50
+ * Overrides the base `onTermRefresh` to ensure a shape change always
51
+ * triggers a re-evaluation, regardless of which child emitted the hint.
52
+ * Without this override the base implementation would also call `_sync`,
53
+ * but the explicit override makes the intent clear and guards against future
54
+ * base-class changes.
55
+ */
56
+ onTermRefresh(entity) {
57
+ this._sync(entity);
58
+ }
59
+ /**
60
+ * @internal React only to world-kind child refreshes.
61
+ *
62
+ * `OnlyTerm` cares about world-shape events (component add/remove) because
63
+ * the component count check in `_matches` can be violated by adding an
64
+ * unlisted component. Component-kind refreshes (data-only value changes) do
65
+ * not affect `only` membership and are intentionally ignored here.
66
+ */
67
+ _onChildRefresh(entity, child) {
68
+ if (child.kind === "world") {
69
+ this._sync(entity);
70
+ }
71
+ }
72
+ /** @internal */
73
+ _matches(entity) {
74
+ return (this._children[0].has(entity) &&
75
+ this._children[1].has(entity) &&
76
+ entity.components.size === this._componentEids.length);
77
+ }
78
+ }
79
+ //# sourceMappingURL=only_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"only_term.js","sourceRoot":"","sources":["../../src/terms/only_term.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,QAAS,SAAQ,IAAI;IAChC,YACE,KAAY,EACZ,GAAW,EACX,OAAa,EACb,SAAe,EACE,cAAiC,EAClD,SAA+B;QAE/B,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;QAH3B,mBAAc,GAAd,cAAc,CAAmB;QAIlD,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;QACxC,IAAI,SAAS,YAAY,SAAS,EAAE,CAAC;YACnC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,KAAK,CACjB,KAAY,EACZ,aAAgC,EAChC,GAAW,EACX,OAAyB,EACzB,SAA+B;QAE/B,uEAAuE;QACvE,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,aAAyB,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACvC,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;IAED;;;;;;;;;OASG;IACa,aAAa,CAAC,MAAc;QAC1C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACgB,eAAe,CAAC,MAAc,EAAE,KAAW;QAC5D,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IAED,gBAAgB;IACN,QAAQ,CAAC,MAAc;QAC/B,OAAO,CACL,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;YAC7B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;YAC7B,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,CACtD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,80 @@
1
+ import { type EntityTestFunc, type QueryDSL } from "../dsl.js";
2
+ import type { Entity } from "../entity/index.js";
3
+ import type { World } from "../world/index.js";
4
+ import { Term } from "./term.js";
5
+ import type { getTerm as GetTermFn } from "./build.js";
6
+ /**
7
+ * Analysis summary derived from a collapsed `all`/`any` subtree.
8
+ *
9
+ * Produced by `_allAnyPrecheck` in `build.ts` and consumed by
10
+ * {@link PredicateTerm.buildMerged} to configure the unified class without
11
+ * first building — and then having to tear down — the composite child terms.
12
+ */
13
+ export type MergedInfo = {
14
+ componentEids: ReadonlySet<number>;
15
+ dependsOnWorld: boolean;
16
+ containsOnly: boolean;
17
+ };
18
+ /**
19
+ * A reactive predicate term that covers two related use-cases under one class:
20
+ *
21
+ * - **Plain predicate** (`kind === "predicate"`): wraps a user-supplied
22
+ * `{ test, watch }` DSL node. The predicate is evaluated whenever a watched
23
+ * component changes; membership requires the world leaf to include the entity
24
+ * (i.e. it is not destroyed and not a `Component` instance).
25
+ *
26
+ * - **Merged / diamond-collapsed** (`kind === "merged"`): wraps a compiled
27
+ * predicate for an `all`/`any` subtree that was detected to contain a
28
+ * leaf-level diamond (the same leaf reachable via two paths). Collapsing it
29
+ * into a single compiled predicate keeps the live graph a strict tree and
30
+ * avoids glitch-inducing double propagation. The optional `_worldTerm` is
31
+ * present only when the subtree depends on world lifecycle, and
32
+ * `_usesShapeRefresh` is set when the subtree contains an `only(...)` node
33
+ * (which needs a shape-channel wakeup on component add/remove).
34
+ *
35
+ * Both variants are constructed via the static factory methods
36
+ * {@link buildPredicate} and {@link buildMerged}; the constructor is not
37
+ * public.
38
+ */
39
+ export declare class PredicateTerm extends Term {
40
+ private readonly _predicate;
41
+ private readonly _worldTerm;
42
+ private readonly _usesShapeRefresh;
43
+ protected constructor(world: World, key: string, kind: "predicate" | "merged", predicate: EntityTestFunc, worldTerm: Term | undefined, watchedTerms: readonly Term[], usesShapeRefresh: boolean, onDestroy: (term: Term) => void);
44
+ /**
45
+ * Build a plain predicate term for a `{ test, watch }` DSL node.
46
+ *
47
+ * Subscribes to the world leaf plus any watched component leaves so the
48
+ * predicate is re-evaluated whenever watched component data changes.
49
+ *
50
+ * @param world - Owning world.
51
+ * @param dsl - DSL node with a `test` function and optional `watch` list.
52
+ * @param key - Canonical cache key for this term.
53
+ * @param getTerm - Term canonicalizer / cache accessor.
54
+ * @param onDestroy - Called when the last consumer unsubscribes.
55
+ */
56
+ static buildPredicate(world: World, dsl: {
57
+ test: EntityTestFunc;
58
+ watch?: unknown;
59
+ }, key: string, getTerm: typeof GetTermFn, onDestroy: (term: Term) => void): PredicateTerm;
60
+ /**
61
+ * Build a merged (diamond-collapsed) predicate term for an `all`/`any`
62
+ * subtree.
63
+ *
64
+ * The predicate is compiled from the full subtree DSL via `_compile` so no
65
+ * composite child terms need to be constructed and then torn down. The
66
+ * `worldTerm` leaf is included only when the subtree depends on world
67
+ * lifecycle; shape-refresh subscription is added only when the subtree
68
+ * contains an `only(...)` node.
69
+ *
70
+ * @param world - Owning world.
71
+ * @param dsl - The original subtree DSL to compile into a predicate.
72
+ * @param key - Canonical cache key for this term.
73
+ * @param info - Pre-computed analysis of the subtree (from `_allAnyPrecheck`).
74
+ * @param getTerm - Term canonicalizer / cache accessor.
75
+ * @param onDestroy - Called when the last consumer unsubscribes.
76
+ */
77
+ static buildMerged(world: World, dsl: QueryDSL, key: string, info: MergedInfo, getTerm: typeof GetTermFn, onDestroy: (term: Term) => void): PredicateTerm;
78
+ /** Direct shape-channel invalidation from `WorldTerm.subscribeShape`. */
79
+ onTermRefresh(entity: Entity): void;
80
+ }
@@ -0,0 +1,109 @@
1
+ import { _compile } from "../dsl.js";
2
+ import { Term } from "./term.js";
3
+ import { WorldTerm } from "./world_term.js";
4
+ /**
5
+ * A reactive predicate term that covers two related use-cases under one class:
6
+ *
7
+ * - **Plain predicate** (`kind === "predicate"`): wraps a user-supplied
8
+ * `{ test, watch }` DSL node. The predicate is evaluated whenever a watched
9
+ * component changes; membership requires the world leaf to include the entity
10
+ * (i.e. it is not destroyed and not a `Component` instance).
11
+ *
12
+ * - **Merged / diamond-collapsed** (`kind === "merged"`): wraps a compiled
13
+ * predicate for an `all`/`any` subtree that was detected to contain a
14
+ * leaf-level diamond (the same leaf reachable via two paths). Collapsing it
15
+ * into a single compiled predicate keeps the live graph a strict tree and
16
+ * avoids glitch-inducing double propagation. The optional `_worldTerm` is
17
+ * present only when the subtree depends on world lifecycle, and
18
+ * `_usesShapeRefresh` is set when the subtree contains an `only(...)` node
19
+ * (which needs a shape-channel wakeup on component add/remove).
20
+ *
21
+ * Both variants are constructed via the static factory methods
22
+ * {@link buildPredicate} and {@link buildMerged}; the constructor is not
23
+ * public.
24
+ */
25
+ export class PredicateTerm extends Term {
26
+ constructor(world, key, kind, predicate, worldTerm, watchedTerms, usesShapeRefresh, onDestroy) {
27
+ super(world, key, kind, false, onDestroy);
28
+ this._predicate = predicate;
29
+ this._worldTerm = worldTerm;
30
+ this._usesShapeRefresh = usesShapeRefresh;
31
+ this._setChildren(worldTerm ? [worldTerm, ...watchedTerms] : watchedTerms);
32
+ if (usesShapeRefresh && worldTerm instanceof WorldTerm) {
33
+ this._addChildCleanup(worldTerm.subscribeShape(this));
34
+ }
35
+ this._initializeFromWorld();
36
+ }
37
+ /**
38
+ * Build a plain predicate term for a `{ test, watch }` DSL node.
39
+ *
40
+ * Subscribes to the world leaf plus any watched component leaves so the
41
+ * predicate is re-evaluated whenever watched component data changes.
42
+ *
43
+ * @param world - Owning world.
44
+ * @param dsl - DSL node with a `test` function and optional `watch` list.
45
+ * @param key - Canonical cache key for this term.
46
+ * @param getTerm - Term canonicalizer / cache accessor.
47
+ * @param onDestroy - Called when the last consumer unsubscribes.
48
+ */
49
+ static buildPredicate(world, dsl, key, getTerm, onDestroy) {
50
+ const watch = normalizeWatch(dsl.watch);
51
+ const worldTerm = getTerm(world, true);
52
+ const watchedTerms = watch.map((eid) => getTerm(world, eid));
53
+ return new PredicateTerm(world, key, "predicate", dsl.test, worldTerm, watchedTerms, false, onDestroy);
54
+ }
55
+ /**
56
+ * Build a merged (diamond-collapsed) predicate term for an `all`/`any`
57
+ * subtree.
58
+ *
59
+ * The predicate is compiled from the full subtree DSL via `_compile` so no
60
+ * composite child terms need to be constructed and then torn down. The
61
+ * `worldTerm` leaf is included only when the subtree depends on world
62
+ * lifecycle; shape-refresh subscription is added only when the subtree
63
+ * contains an `only(...)` node.
64
+ *
65
+ * @param world - Owning world.
66
+ * @param dsl - The original subtree DSL to compile into a predicate.
67
+ * @param key - Canonical cache key for this term.
68
+ * @param info - Pre-computed analysis of the subtree (from `_allAnyPrecheck`).
69
+ * @param getTerm - Term canonicalizer / cache accessor.
70
+ * @param onDestroy - Called when the last consumer unsubscribes.
71
+ */
72
+ static buildMerged(world, dsl, key, info, getTerm, onDestroy) {
73
+ const predicate = _compile(world, dsl);
74
+ const worldTerm = info.dependsOnWorld ? getTerm(world, true) : undefined;
75
+ const watchedTerms = [...info.componentEids].map((eid) => getTerm(world, eid));
76
+ return new PredicateTerm(world, key, "merged", predicate, worldTerm, watchedTerms, info.containsOnly, onDestroy);
77
+ }
78
+ /** Direct shape-channel invalidation from `WorldTerm.subscribeShape`. */
79
+ onTermRefresh(entity) {
80
+ this._sync(entity);
81
+ }
82
+ /**
83
+ * @internal React to a child term refresh.
84
+ *
85
+ * For the plain-predicate variant (`_usesShapeRefresh === false`) only
86
+ * component-kind children trigger a re-evaluation — shape changes on the
87
+ * world leaf are irrelevant. For the merged variant, world-kind refreshes
88
+ * are also relevant when the subtree contained an `only(...)` node (because
89
+ * `only` is sensitive to which components an entity currently has, not just
90
+ * whether a specific one is present).
91
+ */
92
+ _onChildRefresh(entity, child) {
93
+ if (child.kind === "component" || (this._usesShapeRefresh && child.kind === "world")) {
94
+ this._sync(entity);
95
+ }
96
+ }
97
+ /** @internal */
98
+ _matches(entity) {
99
+ return !entity._destroyed && (this._worldTerm?.has(entity) ?? true) && this._predicate(entity);
100
+ }
101
+ }
102
+ /** @internal Deduplicate and sort a `watch` list of component eids. */
103
+ export function normalizeWatch(watch) {
104
+ if (watch === undefined) {
105
+ return [];
106
+ }
107
+ return [...new Set((watch instanceof Array ? watch : [watch]))].sort((a, b) => a - b);
108
+ }
109
+ //# sourceMappingURL=predicate_term.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicate_term.js","sourceRoot":"","sources":["../../src/terms/predicate_term.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import type { QueryDSL } from "../dsl.js";
2
+ import type { World } from "../world/index.js";
3
+ import { Term } from "./term.js";
4
+ import type { getTerm as GetTermFn } from "./build.js";
5
+ /**
6
+ * Composite term that matches entities whose relationship target satisfies a
7
+ * given inner predicate.
8
+ *
9
+ * An entity `e` matches when it carries the relationship component
10
+ * `_relationshipEid` **and** the target entity stored in that component
11
+ * satisfies `_innerTerm`.
12
+ *
13
+ * Children: `[relationshipTerm, innerTerm]`.
14
+ * - `children[0]` (`relationshipTerm`): the `ComponentTerm` for the
15
+ * relationship eid — fires when the relationship is added/removed from `e`.
16
+ * - `children[1]` (`innerTerm`): the term for the inner DSL — fires when the
17
+ * target entity transitions in or out.
18
+ *
19
+ * ## Non-standard event routing
20
+ *
21
+ * `TargetTerm` overrides `_onChildEvent` and `_onChildRefresh` to implement
22
+ * a **fan-out** strategy: when the inner term changes (the target enters or
23
+ * exits), all *sources* that point at that target via the relationship must be
24
+ * re-evaluated. This reverses the normal bottom-up signal direction. The
25
+ * fan-out is why `TargetTerm` subtrees are excluded from diamond collapsing —
26
+ * a plain compiled predicate cannot replicate this per-source walk.
27
+ */
28
+ export declare class TargetTerm extends Term {
29
+ private readonly _relationshipEid;
30
+ private readonly _innerTerm;
31
+ constructor(world: World, key: string, _relationshipEid: number, relationshipTerm: Term, _innerTerm: Term, onDestroy: (term: Term) => void);
32
+ /**
33
+ * Build a `TargetTerm` for the given relationship eid and inner DSL.
34
+ *
35
+ * @param world - Owning world.
36
+ * @param relationshipEid - Numeric eid of the relationship component type.
37
+ * @param innerDSL - DSL expression the relationship target must satisfy.
38
+ * @param key - Canonical cache key.
39
+ * @param getTerm - Term canonicalizer / cache accessor.
40
+ * @param onDestroy - Called when the last consumer unsubscribes.
41
+ */
42
+ static build(world: World, relationshipEid: number, innerDSL: QueryDSL, key: string, getTerm: typeof GetTermFn, onDestroy: (term: Term) => void): TargetTerm;
43
+ }