@vworlds/vecs 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ npx lint-staged
package/.prettierrc ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "semi": true,
3
+ "singleQuote": false,
4
+ "tabWidth": 2,
5
+ "trailingComma": "es5",
6
+ "printWidth": 100
7
+ }
package/README.md CHANGED
@@ -12,14 +12,15 @@ yarn add @vworlds/vecs
12
12
 
13
13
  ## Concepts
14
14
 
15
- | Concept | What it is |
16
- |---|---|
17
- | **World** | Central container. Owns all entities, runs all systems and queries. |
18
- | **Component** | A plain data class. Extend `Component` and attach instances to entities. |
19
- | **Entity** | An integer id with a set of components. Create via the world. |
20
- | **Query** | A reactive, always-updated set of entities that match a predicate. |
21
- | **System** | A `Query` with per-tick runtime logic (phases, `update`, `each`, `run`). |
22
- | **Filter** | A non-reactive, one-shot scan: walks all world entities on each `forEach` call. |
15
+ | Concept | What it is |
16
+ | ------------------------ | ------------------------------------------------------------------------------- |
17
+ | **World** | Central container. Owns all entities, runs all systems and queries. |
18
+ | **Component** | A plain data class. Extend `Component` and attach instances to entities. |
19
+ | **Entity** | An integer id with a set of components. Create via the world. |
20
+ | **Query** | A reactive, always-updated set of entities that match a predicate. |
21
+ | **System** | A `Query` with per-tick runtime logic (phases, `update`, `each`, `run`). |
22
+ | **Filter** | A non-reactive, one-shot scan: walks all world entities on each `forEach` call. |
23
+ | **Exclusive components** | A group of components where at most one may be present on any entity at a time. |
23
24
 
24
25
  ### Lifecycle in brief
25
26
 
@@ -161,6 +162,23 @@ world.registerComponentType("Position", 1);
161
162
 
162
163
  After `world.start()` any further call to `registerComponent` throws.
163
164
 
165
+ #### Exclusive components
166
+
167
+ Declare a group of components that cannot coexist on the same entity. Adding a member of the group automatically removes any other member that was already present.
168
+
169
+ ```ts
170
+ world.setExclusiveComponents(Walking, Running, Idle);
171
+
172
+ const e = world.createEntity();
173
+ e.add(Walking);
174
+ e.add(Running); // Walking is automatically removed first
175
+ // e.get(Walking) === undefined, e.get(Running) is defined
176
+ ```
177
+
178
+ Each call to `setExclusiveComponents` defines one independent group. Components not in the group are unaffected. A component may belong to at most one exclusivity group (calling `setExclusiveComponents` a second time with the same class overwrites its group).
179
+
180
+ `setExclusiveComponents` may be called before or after `world.start()`.
181
+
164
182
  #### Entity management
165
183
 
166
184
  ```ts
@@ -202,10 +220,11 @@ world.start(); // distributes systems to phases, freezes component registration
202
220
  A standalone `Query` is a reactive entity set without a phase or per-tick callbacks. Use it when you need the matched set kept up-to-date automatically — for example to enumerate scene nodes or find the nearest enemy.
203
221
 
204
222
  ```ts
205
- const enemies = world.query("Enemies")
223
+ const enemies = world
224
+ .query("Enemies")
206
225
  .requires(Enemy, Health)
207
226
  .enter((e) => console.log("enemy spawned", e.eid))
208
- .exit((e) => console.log("enemy died", e.eid));
227
+ .exit((e) => console.log("enemy died", e.eid));
209
228
 
210
229
  world.start();
211
230
  // enemies.entities is kept up-to-date automatically
@@ -224,20 +243,19 @@ A `Filter` is a non-reactive, one-shot scan. It holds no tracked entity set —
224
243
  world.filter([Position]).forEach((e) => console.log(e.eid));
225
244
 
226
245
  // With component injection:
227
- world.filter([Position, Velocity])
228
- .forEach([Position, Velocity], (e, [pos, vel]) => {
229
- pos.x += vel.vx;
230
- });
246
+ world.filter([Position, Velocity]).forEach([Position, Velocity], (e, [pos, vel]) => {
247
+ pos.x += vel.vx;
248
+ });
231
249
 
232
250
  // Full DSL, with auto-deduced required components:
233
- world.filter({ AND: [{ HAS: Position }, { HAS: Velocity }] })
251
+ world
252
+ .filter({ AND: [{ HAS: Position }, { HAS: Velocity }] })
234
253
  .forEach([Position, Velocity], (e, [pos, vel]) => {
235
254
  pos.x += vel.vx; // pos and vel are non-null — deduced from AND of HAS
236
255
  });
237
256
 
238
257
  // Manual type hint for queries the extractor can't see through:
239
- world.filter({ OR: [Position, Velocity] }, [Position])
240
- .forEach([Position], (e, [pos]) => pos.x);
258
+ world.filter({ OR: [Position, Velocity] }, [Position]).forEach([Position], (e, [pos]) => pos.x);
241
259
  ```
242
260
 
243
261
  Unlike `Query`, a `Filter` requires no name, no `world.start()`, and no `destroy()` — create it anywhere and discard it freely.
@@ -247,16 +265,16 @@ Unlike `Query`, a `Filter` requires no name, no `world.start()`, and no `destroy
247
265
  ```ts
248
266
  // Declare phases in the order they should run each frame:
249
267
  const preUpdate = world.addPhase("preupdate");
250
- const update = world.addPhase("update");
251
- const send = world.addPhase("send");
268
+ const update = world.addPhase("update");
269
+ const send = world.addPhase("send");
252
270
 
253
271
  // Each frame, run all phases in registration order:
254
272
  world.progress(Date.now(), deltaMs);
255
273
 
256
274
  // Or drive individual phases manually:
257
275
  world.runPhase(preUpdate, Date.now(), deltaMs);
258
- world.runPhase(update, Date.now(), deltaMs);
259
- world.runPhase(send, Date.now(), deltaMs);
276
+ world.runPhase(update, Date.now(), deltaMs);
277
+ world.runPhase(send, Date.now(), deltaMs);
260
278
  ```
261
279
 
262
280
  Systems with no explicit phase go into a built-in `"update"` phase.
@@ -266,10 +284,11 @@ Systems with no explicit phase go into a built-in `"update"` phase.
266
284
  A hook is a shorthand for reacting to a single component's lifecycle without writing a full system:
267
285
 
268
286
  ```ts
269
- world.hook(Sprite)
270
- .onAdd((sprite) => sprite.initialize(scene))
287
+ world
288
+ .hook(Sprite)
289
+ .onAdd((sprite) => sprite.initialize(scene))
271
290
  .onRemove((sprite) => sprite.destroy())
272
- .onSet((sprite) => sprite.syncToScene());
291
+ .onSet((sprite) => sprite.syncToScene());
273
292
  ```
274
293
 
275
294
  `onSet` fires whenever `component.modified()` is called.
@@ -297,12 +316,12 @@ pos.modified(); // tell the world this component changed
297
316
 
298
317
  Every component instance exposes:
299
318
 
300
- | Property / Method | Description |
301
- |---|---|
302
- | `entity` | The `Entity` this component belongs to. |
303
- | `meta` | `ComponentMeta` — holds the type id, name, and bitset pointer. |
304
- | `type` | Numeric type id (shorthand for `meta.type`). |
305
- | `modified()` | Queue an `onSet` / `update` notification. Call after mutating fields. |
319
+ | Property / Method | Description |
320
+ | ----------------- | --------------------------------------------------------------------- |
321
+ | `entity` | The `Entity` this component belongs to. |
322
+ | `meta` | `ComponentMeta` — holds the type id, name, and bitset pointer. |
323
+ | `type` | Numeric type id (shorthand for `meta.type`). |
324
+ | `modified()` | Queue an `onSet` / `update` notification. Call after mutating fields. |
306
325
 
307
326
  ---
308
327
 
@@ -312,21 +331,21 @@ Every component instance exposes:
312
331
  const e = world.createEntity();
313
332
  ```
314
333
 
315
- | Property / Method | Description |
316
- |---|---|
317
- | `eid` | Unique numeric entity id. |
318
- | `world` | The `World` that owns this entity. |
319
- | `add(Class)` | Attach a component; returns the typed instance. Idempotent. |
320
- | `set(Class, props)` | Like `add`, but also assigns the given partial properties onto the instance. Returns the typed instance. |
321
- | `get(Class)` | Return the component instance, or `undefined` if not present. |
322
- | `remove(Class)` | Detach a component (triggers `onRemove` hooks and `exit` callbacks). |
323
- | `destroy()` | Remove all components and unregister the entity. Recurses to children. |
324
- | `empty` | `true` when no components are attached. |
325
- | `forEachComponent(cb)` | Iterate over all attached components. |
326
- | `parent` | Parent entity in the scene hierarchy, or `undefined`. |
327
- | `children` | `Set<Entity>` of direct children (lazy, created on first access). |
328
- | `events` | Typed event emitter. Currently emits `"destroy"` before teardown. |
329
- | `properties` | `Map<string, any>` free-form bag for module-level bookkeeping. |
334
+ | Property / Method | Description |
335
+ | ---------------------- | -------------------------------------------------------------------------------------------------------- |
336
+ | `eid` | Unique numeric entity id. |
337
+ | `world` | The `World` that owns this entity. |
338
+ | `add(Class)` | Attach a component; returns the typed instance. Idempotent. |
339
+ | `set(Class, props)` | Like `add`, but also assigns the given partial properties onto the instance. Returns the typed instance. |
340
+ | `get(Class)` | Return the component instance, or `undefined` if not present. |
341
+ | `remove(Class)` | Detach a component (triggers `onRemove` hooks and `exit` callbacks). |
342
+ | `destroy()` | Remove all components and unregister the entity. Recurses to children. |
343
+ | `empty` | `true` when no components are attached. |
344
+ | `forEachComponent(cb)` | Iterate over all attached components. |
345
+ | `parent` | Parent entity in the scene hierarchy, or `undefined`. |
346
+ | `children` | `Set<Entity>` of direct children (lazy, created on first access). |
347
+ | `events` | Typed event emitter. Currently emits `"destroy"` before teardown. |
348
+ | `properties` | `Map<string, any>` free-form bag for module-level bookkeeping. |
330
349
 
331
350
  #### Parent–child hierarchy
332
351
 
@@ -367,15 +386,15 @@ Declare which entities the system should track:
367
386
 
368
387
  **Query operators:**
369
388
 
370
- | Operator | Meaning |
371
- |---|---|
372
- | `{ HAS: [A, B] }` | Entity has all of A and B |
389
+ | Operator | Meaning |
390
+ | ---------------------- | ---------------------------------------- |
391
+ | `{ HAS: [A, B] }` | Entity has all of A and B |
373
392
  | `{ HAS_ONLY: [A, B] }` | Entity has exactly A and B, nothing else |
374
- | `{ AND: [q1, q2] }` | Both sub-queries must match |
375
- | `{ OR: [q1, q2] }` | Either sub-query matches |
376
- | `{ NOT: q }` | Sub-query must not match |
377
- | `{ PARENT: q }` | Entity's parent matches q |
378
- | An array `[A, B]` | Shorthand for `HAS: [A, B]` |
393
+ | `{ AND: [q1, q2] }` | Both sub-queries must match |
394
+ | `{ OR: [q1, q2] }` | Either sub-query matches |
395
+ | `{ NOT: q }` | Sub-query must not match |
396
+ | `{ PARENT: q }` | Entity's parent matches q |
397
+ | An array `[A, B]` | Shorthand for `HAS: [A, B]` |
379
398
 
380
399
  **Type inference:** `requires()` records the listed classes as a type parameter on the system. Callbacks in `.sort()`, `.each()`, and `.update()` inject then treat those components as non-nullable — no `!` needed. For complex `query()` expressions the type system cannot introspect, pass a second argument as an explicit hint:
381
400
 
@@ -467,7 +486,8 @@ Enable sorted entity tracking. Matched entities are stored in an ordered set who
467
486
  Components declared via `requires()` are non-null in the compare callback.
468
487
 
469
488
  ```ts
470
- world.system("Render")
489
+ world
490
+ .system("Render")
471
491
  .requires(Position, Sprite)
472
492
  .sort([Position], ([posA], [posB]) => posA.z - posB.z)
473
493
  .each([Position, Sprite], (e, [pos, sprite]) => {
@@ -500,31 +520,36 @@ Called every tick when the system's phase runs, regardless of entity state. Use
500
520
  A standalone query is created via `world.query(name)` and configured through the same fluent builder API as `System` (`requires`, `query`, `enter`, `exit`, `sort`, `track`, `forEach`, `entities`). It has no phase and no per-tick callbacks.
501
521
 
502
522
  ```ts
503
- const projectiles = world.query("Projectiles")
523
+ const projectiles = world
524
+ .query("Projectiles")
504
525
  .requires(Position, Velocity)
505
526
  .sort([Position], ([a], [b]) => a.z - b.z)
506
- .enter([Position], (e, [pos]) => { pos.x = spawnX; });
527
+ .enter([Position], (e, [pos]) => {
528
+ pos.x = spawnX;
529
+ });
507
530
 
508
531
  world.start();
509
532
 
510
533
  // Anywhere in game code:
511
- projectiles.forEach((e) => { /* ... */ });
534
+ projectiles.forEach((e) => {
535
+ /* ... */
536
+ });
512
537
  console.log(projectiles.entities.size, "active projectiles");
513
538
  ```
514
539
 
515
- | Method | Description |
516
- |---|---|
517
- | `.requires(...components)` | Set the membership predicate and start tracking. |
518
- | `.query(expr)` | Set the membership predicate using the {@link SystemQuery} DSL. |
519
- | `.enter(callback)` / `.enter(inject, callback)` | Fires when an entity joins the query. |
520
- | `.exit(callback)` / `.exit(inject, callback)` | Fires when an entity leaves the query. |
521
- | `.sort(components, compare)` | Store matched entities in sorted order. |
522
- | `.track()` | Enable tracking (implied by `sort`; backfills when called after `start`). |
523
- | `.belongs(e)` | Returns `true` if the entity satisfies the predicate. |
524
- | `.forEach(callback)` | Iterate all currently tracked entities (entity only). |
525
- | `.forEach(components, callback)` | Iterate with component injection — same signature as `Filter.forEach`. |
526
- | `.entities` | `ReadonlySet<Entity>` of all currently tracked entities. |
527
- | `.destroy()` | Remove the query from the world and all entities. See below. |
540
+ | Method | Description |
541
+ | ----------------------------------------------- | ------------------------------------------------------------------------- |
542
+ | `.requires(...components)` | Set the membership predicate and start tracking. |
543
+ | `.query(expr)` | Set the membership predicate using the {@link SystemQuery} DSL. |
544
+ | `.enter(callback)` / `.enter(inject, callback)` | Fires when an entity joins the query. |
545
+ | `.exit(callback)` / `.exit(inject, callback)` | Fires when an entity leaves the query. |
546
+ | `.sort(components, compare)` | Store matched entities in sorted order. |
547
+ | `.track()` | Enable tracking (implied by `sort`; backfills when called after `start`). |
548
+ | `.belongs(e)` | Returns `true` if the entity satisfies the predicate. |
549
+ | `.forEach(callback)` | Iterate all currently tracked entities (entity only). |
550
+ | `.forEach(components, callback)` | Iterate with component injection — same signature as `Filter.forEach`. |
551
+ | `.entities` | `ReadonlySet<Entity>` of all currently tracked entities. |
552
+ | `.destroy()` | Remove the query from the world and all entities. See below. |
528
553
 
529
554
  #### `.destroy()`
530
555
 
@@ -550,9 +575,9 @@ A `Filter` is created via `world.filter(dsl)` and provides a non-reactive `forEa
550
575
  const f = world.filter([Position, Velocity]);
551
576
  ```
552
577
 
553
- | Method | Description |
554
- |---|---|
555
- | `.forEach(callback)` | Walk all world entities; invoke callback for each matching one. |
578
+ | Method | Description |
579
+ | -------------------------------- | -------------------------------------------------------------------------- |
580
+ | `.forEach(callback)` | Walk all world entities; invoke callback for each matching one. |
556
581
  | `.forEach(components, callback)` | Same, with component injection and non-null types for required components. |
557
582
 
558
583
  **Type inference** works the same way as for `requires()` on systems/queries: component classes extractable from the DSL (`HAS`, `HAS_ONLY`, plain arrays, and `AND` of those) are non-nullable in the callback tuple. Pass a `_guaranteed` second argument to `world.filter()` as a manual override when inference can't reach:
@@ -65,9 +65,17 @@ export declare class ComponentMeta implements Hook<Component> {
65
65
  readonly componentName: string;
66
66
  /** Pre-computed bit-pointer into the entity archetype {@link Bitset}. */
67
67
  readonly bitPtr: BitPtr;
68
- private onAddHandler;
69
- private onRemoveHandler;
70
- private onSetHandler;
68
+ /** @internal */
69
+ _onAddHandler: ((c: Component) => void) | undefined;
70
+ /** @internal */
71
+ _onRemoveHandler: ((c: Component) => void) | undefined;
72
+ /** @internal */
73
+ _onSetHandler: ((c: Component) => void) | undefined;
74
+ /**
75
+ * Type ids of components that cannot coexist with this one on the same entity.
76
+ * Set via {@link World.setExclusiveComponents}. `undefined` means no restrictions.
77
+ */
78
+ exclusive: number[] | undefined;
71
79
  constructor(Class: typeof Component, type: number, componentName: string);
72
80
  /** @inheritdoc */
73
81
  onAdd(handler: (c: Component) => void): ComponentMeta;
@@ -105,7 +113,8 @@ export declare class Component {
105
113
  readonly entity: Entity;
106
114
  /** Registration metadata (type id, name, bit-pointer). */
107
115
  readonly meta: ComponentMeta;
108
- private dirty;
116
+ /** @internal */
117
+ _dirty: boolean;
109
118
  constructor(
110
119
  /** The entity this component belongs to. */
111
120
  entity: Entity,
package/dist/component.js CHANGED
@@ -11,6 +11,11 @@ import { BitPtr, Bitset } from "./util/bitset.js";
11
11
  */
12
12
  export class ComponentMeta {
13
13
  constructor(Class, type, componentName) {
14
+ /**
15
+ * Type ids of components that cannot coexist with this one on the same entity.
16
+ * Set via {@link World.setExclusiveComponents}. `undefined` means no restrictions.
17
+ */
18
+ this.exclusive = undefined;
14
19
  this.Class = Class;
15
20
  this.type = type;
16
21
  this.componentName = componentName;
@@ -18,17 +23,17 @@ export class ComponentMeta {
18
23
  }
19
24
  /** @inheritdoc */
20
25
  onAdd(handler) {
21
- this.onAddHandler = handler;
26
+ this._onAddHandler = handler;
22
27
  return this;
23
28
  }
24
29
  /** @inheritdoc */
25
30
  onRemove(handler) {
26
- this.onRemoveHandler = handler;
31
+ this._onRemoveHandler = handler;
27
32
  return this;
28
33
  }
29
34
  /** @inheritdoc */
30
35
  onSet(handler) {
31
- this.onSetHandler = handler;
36
+ this._onSetHandler = handler;
32
37
  return this;
33
38
  }
34
39
  }
@@ -60,7 +65,8 @@ export class Component {
60
65
  meta) {
61
66
  this.entity = entity;
62
67
  this.meta = meta;
63
- this.dirty = false;
68
+ /** @internal */
69
+ this._dirty = false;
64
70
  }
65
71
  /** Numeric type id — shorthand for `this.meta.type`. */
66
72
  get type() {
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoDlD;;;;;;;;;GASG;AACH,MAAM,OAAO,aAAa;IAaxB,YAAY,KAAuB,EAAE,IAAY,EAAE,aAAqB;QACtE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAA+B;QAC7C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,SAAS;IAGpB;IACE,4CAA4C;IAC5B,MAAc;IAC9B,0DAA0D;IAC1C,IAAmB;QAFnB,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAe;QAN7B,UAAK,GAAY,KAAK,CAAC;IAO5B,CAAC;IAEJ,wDAAwD;IACxD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,kEAAkE;IAC3D,QAAQ;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAA4B,EAC5B,KAAY;IAEZ,MAAM,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAoDlD;;;;;;;;;GASG;AACH,MAAM,OAAO,aAAa;IAqBxB,YAAY,KAAuB,EAAE,IAAY,EAAE,aAAqB;QANxE;;;WAGG;QACI,cAAS,GAAyB,SAAS,CAAC;QAGjD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,QAAQ,CAAC,OAA+B;QAC7C,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kBAAkB;IACX,KAAK,CAAC,OAA+B;QAC1C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAQD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,SAAS;IAIpB;IACE,4CAA4C;IAC5B,MAAc;IAC9B,0DAA0D;IAC1C,IAAmB;QAFnB,WAAM,GAAN,MAAM,CAAQ;QAEd,SAAI,GAAJ,IAAI,CAAe;QAPrC,gBAAgB;QACT,WAAM,GAAY,KAAK,CAAC;IAO5B,CAAC;IAEJ,wDAAwD;IACxD,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACxB,CAAC;IAED,mEAAmE;IACnE,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED;;;;;;OAMG;IACI,QAAQ;QACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,kEAAkE;IAC3D,QAAQ;QACb,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;IACjC,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAA4B,EAAE,KAAY;IAClF,MAAM,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/dsl.d.ts CHANGED
@@ -65,7 +65,10 @@ export type ExtractRequired<Q> = Q extends typeof Component ? [Q] : Q extends re
65
65
  } ? ExtractRequired<H> : Q extends {
66
66
  AND: infer A extends readonly QueryDSL[];
67
67
  } ? ExtractAndChain<A> : [];
68
- type ExtractAndChain<A extends readonly QueryDSL[]> = A extends readonly [infer First, ...infer Rest extends readonly QueryDSL[]] ? [...ExtractRequired<First>, ...ExtractAndChain<Rest>] : [];
68
+ type ExtractAndChain<A extends readonly QueryDSL[]> = A extends readonly [
69
+ infer First,
70
+ ...infer Rest extends readonly QueryDSL[]
71
+ ] ? [...ExtractRequired<First>, ...ExtractAndChain<Rest>] : [];
69
72
  /** Convert a {@link QueryDSL} expression into a runtime entity-test predicate. */
70
73
  export declare function buildEntityTest(world: World, q: QueryDSL): EntityTestFunc;
71
74
  export {};
package/dist/dsl.js CHANGED
@@ -21,8 +21,7 @@ function PARENT(func) {
21
21
  }
22
22
  /** Convert a {@link QueryDSL} expression into a runtime entity-test predicate. */
23
23
  export function buildEntityTest(world, q) {
24
- if (typeof q === "number" ||
25
- (typeof q === "function" && q.prototype instanceof Component)) {
24
+ if (typeof q === "number" || (typeof q === "function" && q.prototype instanceof Component)) {
26
25
  return HAS(world, q);
27
26
  }
28
27
  else if (typeof q === "function") {
package/dist/dsl.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dsl.js","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dsl.js","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"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"}
package/dist/entity.d.ts CHANGED
@@ -47,7 +47,8 @@ export declare class Entity {
47
47
  _events: EntityEvents;
48
48
  /** Parent entity in the scene hierarchy, or `undefined` if root. */
49
49
  parent: Entity | undefined;
50
- private _children;
50
+ /** @internal */
51
+ _children: Set<Entity> | undefined;
51
52
  _archetypeChanged: boolean;
52
53
  private destroyed;
53
54
  constructor(
@@ -63,6 +64,7 @@ export declare class Entity {
63
64
  * both will keep the parent–child links consistent.
64
65
  */
65
66
  get children(): Set<Entity>;
67
+ private getComponentInstance;
66
68
  /**
67
69
  * Add a component of type `Class` to this entity and return the instance.
68
70
  *
@@ -151,7 +153,8 @@ export declare class Entity {
151
153
  _updateQueries(): void;
152
154
  /** `true` when the entity has no components attached. */
153
155
  get empty(): boolean;
154
- private _destroy;
156
+ /** @internal */
157
+ _destroy(): void;
155
158
  /**
156
159
  * Destroy this entity and recursively destroy all of its children.
157
160
  *
package/dist/entity.js CHANGED
@@ -53,26 +53,45 @@ export class Entity {
53
53
  * both will keep the parent–child links consistent.
54
54
  */
55
55
  get children() {
56
- if (!this._children)
56
+ if (!this._children) {
57
57
  this._children = new Set();
58
+ }
58
59
  return this._children;
59
60
  }
61
+ getComponentInstance(meta) {
62
+ const c = new meta.Class(this, meta);
63
+ const hook = meta._onAddHandler;
64
+ if (hook) {
65
+ hook(c);
66
+ }
67
+ return c;
68
+ }
60
69
  add(typeOrClass, markAsModified = true) {
61
70
  const type = this.world.getComponentType(typeOrClass);
62
71
  let c = this.components.get(type);
63
72
  if (c) {
64
73
  return c;
65
74
  }
66
- c = this.world["getComponentInstance"](typeOrClass, this);
75
+ const meta = this.world.getComponentMeta(typeOrClass);
76
+ if (meta.exclusive) {
77
+ for (const exclusiveType of meta.exclusive) {
78
+ if (this.components.has(exclusiveType)) {
79
+ this.remove(exclusiveType);
80
+ }
81
+ }
82
+ }
83
+ c = this.getComponentInstance(meta);
67
84
  this.components.set(type, c);
68
85
  this.componentBitmask.add(type);
69
86
  this.world._notifyComponentAdded(this, c);
70
- if (markAsModified)
87
+ if (markAsModified) {
71
88
  this.world._queueUpdatedComponent(c);
89
+ }
72
90
  return c;
73
91
  }
74
92
  set(typeOrClass, props) {
75
- const c = this.add(typeOrClass);
93
+ const c = this.add(typeOrClass, false);
94
+ this.world._queueUpdatedComponent(c);
76
95
  return Object.assign(c, props);
77
96
  }
78
97
  remove(typeOrClass) {
@@ -130,8 +149,9 @@ export class Entity {
130
149
  _purgeQuery(q) {
131
150
  this.queries.delete(q);
132
151
  const idx = this.newQueries.indexOf(q);
133
- if (idx !== -1)
152
+ if (idx !== -1) {
134
153
  this.newQueries.splice(idx, 1);
154
+ }
135
155
  }
136
156
  /** @internal */
137
157
  _addQuery(q) {
@@ -157,9 +177,11 @@ export class Entity {
157
177
  get empty() {
158
178
  return this.components.size == 0;
159
179
  }
180
+ /** @internal */
160
181
  _destroy() {
161
- if (this.destroyed)
182
+ if (this.destroyed) {
162
183
  return;
184
+ }
163
185
  this.destroyed = true;
164
186
  this.queries.forEach((q) => {
165
187
  q._exit(this);
@@ -1 +1 @@
1
- {"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,MAAM;IA0BjB;IACE,+CAA+C;IAC/B,KAAY;IAC5B,0DAA0D;IAC1C,GAAW;QAFX,UAAK,GAAL,KAAK,CAAO;QAEZ,QAAG,GAAH,GAAG,CAAQ;QA7BrB,eAAU,GAAG,IAAI,QAAQ,EAAa,CAAC,CAAC,oCAAoC;QAC5E,sBAAiB,GAAG,IAAI,QAAQ,EAAa,CAAC,CAAC,4CAA4C;QAEnG;;;;WAIG;QACa,qBAAgB,GAAG,IAAI,MAAM,EAAE,CAAC;QAC/B,YAAO,GAAG,IAAI,GAAG,EAAS,CAAC;QAC3B,eAAU,GAAY,EAAE,CAAC;QAE1C;;;WAGG;QACI,eAAU,GAAG,IAAI,GAAG,EAAe,CAAC;QAMpC,sBAAiB,GAAY,KAAK,CAAC;QAClC,cAAS,GAAG,KAAK,CAAC;IAOvB,CAAC;IAEJ;;;;;;OAMG;IACH,IAAW,QAAQ;QACjB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,IAAI,CAAC,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;QACxD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IA4BM,GAAG,CACR,WAAsC,EACtC,iBAA0B,IAAI;QAE9B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAEtD,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,EAAE;YACL,OAAO,CAAC,CAAC;SACV;QACD,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAE1D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,cAAc;YAAE,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO,CAAC,CAAC;IACX,CAAC;IAqBM,GAAG,CACR,WAAsC,EACtC,KAAyB;QAEzB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,WAAkB,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IAkBM,MAAM,CAAC,WAAsC;QAClD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,EAAE;YACL,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;SAC7C;IACH,CAAC;IAED,mEAAmE;IAC5D,eAAe,CAAC,SAAoB;QACzC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACI,GAAG,CACR,WAAuB,EACvB,cAAuB,KAAK;QAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAEtD,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,IAAI,WAAW,EAAE;YACrB,OAAO,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAgC,CAAC;SACxE;QACD,OAAO,CAAgC,CAAC;IAC1C,CAAC;IAED;;;;;;;OAOG;IACH,IAAW,MAAM;QACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,EAAE,CAAC;SAC7B;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,gBAAgB;IACT,SAAS,CAAC,CAAQ;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,+FAA+F;IACxF,WAAW,CAAC,CAAQ;QACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;IAED,gBAAgB;IACT,SAAS,CAAC,CAAQ;QACvB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;SAChB;IACH,CAAC;IAED,gBAAgB;IACT,YAAY,CAAC,CAAQ;QAC1B,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAC1B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SACf;IACH,CAAC;IAED,gBAAgB;IACT,cAAc;QACnB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,yDAAyD;IACzD,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,CAAC;IACnC,CAAC;IAEO,QAAQ;QACd,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACzB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAErB,IAAI,IAAI,CAAC,OAAO,EAAE;YAChB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;SAC5C;IACH,CAAC;IAED;;;;;;OAMG;IACI,OAAO;QACZ,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC9B,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;SACzB;IACH,CAAC;IAED,gBAAgB;IACT,sBAAsB;QAC3B,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACI,gBAAgB,CAAC,QAAgC;QACtD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,oDAAoD;IAC7C,QAAQ;QACb,OAAO,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
package/dist/filter.js CHANGED
@@ -1,4 +1,4 @@
1
- import { buildEntityTest, } from "./dsl.js";
1
+ import { buildEntityTest } from "./dsl.js";
2
2
  /**
3
3
  * A non-reactive, one-shot entity filter.
4
4
  *
@@ -35,15 +35,17 @@ export class Filter {
35
35
  forEach(componentsOrCallback, callback) {
36
36
  if (typeof componentsOrCallback === "function") {
37
37
  this.world._forEachEntity((e) => {
38
- if (this.belongs(e))
38
+ if (this.belongs(e)) {
39
39
  componentsOrCallback(e);
40
+ }
40
41
  });
41
42
  }
42
43
  else {
43
44
  const types = componentsOrCallback.map((C) => this.world.getComponentType(C));
44
45
  this.world._forEachEntity((e) => {
45
- if (!this.belongs(e))
46
+ if (!this.belongs(e)) {
46
47
  return;
48
+ }
47
49
  const resolved = types.map((t) => e.get(t));
48
50
  callback(e, resolved);
49
51
  });
@@ -1 +1 @@
1
- {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,eAAe,GAIhB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,MAAM;IAGjB,YACmB,KAAY,EAC7B,GAAa;QADI,UAAK,GAAL,KAAK,CAAO;QAG7B,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IA8BM,OAAO,CACZ,oBAEyB,EACzB,QAGS;QAET,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE;YAC9C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;YAC/C,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3C,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAC/B,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,OAAO;gBAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,QAAS,CAAC,CAAC,EAAE,QAAe,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;SACJ;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAA0D,MAAM,UAAU,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,MAAM;IAGjB,YACmB,KAAY,EAC7B,GAAa;QADI,UAAK,GAAL,KAAK,CAAO;QAG7B,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;IA2BM,OAAO,CACZ,oBAA6D,EAC7D,QAAoF;QAEpF,IAAI,OAAO,oBAAoB,KAAK,UAAU,EAAE;YAC9C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;oBACnB,oBAAoB,CAAC,CAAC,CAAC,CAAC;iBACzB;YACH,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,MAAM,KAAK,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9E,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;oBACpB,OAAO;iBACR;gBACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC5C,QAAS,CAAC,CAAC,EAAE,QAAe,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;SACJ;IACH,CAAC;CACF"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vworlds/vecs",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -10,10 +10,18 @@
10
10
  "build": "yarn clean && yarn compile",
11
11
  "compile": "tsc --build && cp \"./package.json\" ./dist/",
12
12
  "test": "vitest run",
13
- "test:watch": "vitest"
13
+ "test:watch": "vitest",
14
+ "lint": "eslint src/ tests/",
15
+ "prepare": "husky"
14
16
  },
15
17
  "devDependencies": {
16
18
  "@types/node": "^20.0.0",
19
+ "@typescript-eslint/eslint-plugin": "^8.59.1",
20
+ "@typescript-eslint/parser": "^8.59.1",
21
+ "eslint": "^10.2.1",
22
+ "husky": "^9.1.7",
23
+ "lint-staged": "^16.4.0",
24
+ "prettier": "^3.8.3",
17
25
  "rimraf": "^5.0.0",
18
26
  "typescript": "^4.8.4",
19
27
  "vitest": "^1.6.0"
@@ -25,5 +33,11 @@
25
33
  "repository": {
26
34
  "type": "git",
27
35
  "url": "https://github.com/vworlds/vecs"
36
+ },
37
+ "lint-staged": {
38
+ "*.ts": [
39
+ "prettier --write",
40
+ "eslint --fix"
41
+ ]
28
42
  }
29
43
  }