@yagejs/core 0.5.0 → 0.6.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.
- package/dist/index.cjs +534 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +265 -13
- package/dist/index.d.ts +265 -13
- package/dist/index.js +520 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1136,6 +1136,13 @@ var Entity = class {
|
|
|
1136
1136
|
name;
|
|
1137
1137
|
/** Tags for group queries. */
|
|
1138
1138
|
tags;
|
|
1139
|
+
/**
|
|
1140
|
+
* Stable identity key, scene-scoped. Set at spawn-time when
|
|
1141
|
+
* `options.key` is passed to `scene.spawn` / `entity.spawnChild`;
|
|
1142
|
+
* `undefined` otherwise. Used with `scene.findByKey` and as a stable
|
|
1143
|
+
* id in persistent stores (e.g. `defineSet<string>("world.opened")`).
|
|
1144
|
+
*/
|
|
1145
|
+
key;
|
|
1139
1146
|
components = /* @__PURE__ */ new Map();
|
|
1140
1147
|
_destroyed = false;
|
|
1141
1148
|
_scene = null;
|
|
@@ -1206,17 +1213,21 @@ var Entity = class {
|
|
|
1206
1213
|
this._scene._addExistingEntity(child);
|
|
1207
1214
|
}
|
|
1208
1215
|
}
|
|
1209
|
-
spawnChild(name,
|
|
1216
|
+
spawnChild(name, classOrBlueprintOrOptions, paramsOrOptions, maybeOptions) {
|
|
1210
1217
|
const scene = this.scene;
|
|
1211
1218
|
if (this._children?.has(name)) {
|
|
1212
1219
|
throw new Error(
|
|
1213
1220
|
`Entity "${this.name}" already has a child named "${name}".`
|
|
1214
1221
|
);
|
|
1215
1222
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
)
|
|
1223
|
+
let child;
|
|
1224
|
+
if (classOrBlueprintOrOptions === void 0) {
|
|
1225
|
+
child = scene.spawn(name);
|
|
1226
|
+
} else if (typeof classOrBlueprintOrOptions === "object" && !("build" in classOrBlueprintOrOptions)) {
|
|
1227
|
+
child = scene.spawn(name, classOrBlueprintOrOptions);
|
|
1228
|
+
} else {
|
|
1229
|
+
child = scene.spawn(classOrBlueprintOrOptions, paramsOrOptions, maybeOptions);
|
|
1230
|
+
}
|
|
1220
1231
|
this.addChild(name, child);
|
|
1221
1232
|
return child;
|
|
1222
1233
|
}
|
|
@@ -1359,6 +1370,19 @@ var Entity = class {
|
|
|
1359
1370
|
}
|
|
1360
1371
|
return false;
|
|
1361
1372
|
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Return the stable key, or throw if this entity was spawned without one.
|
|
1375
|
+
* Use inside component `setup()` when the component depends on identity
|
|
1376
|
+
* (e.g. reading from a `defineSet` keyed by entity id).
|
|
1377
|
+
*/
|
|
1378
|
+
requireKey() {
|
|
1379
|
+
if (this.key === void 0) {
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
`Entity "${this.name}" (id=${this.id}) has no stable key. Pass { key: "..." } to scene.spawn(...) or entity.spawnChild(...).`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
return this.key;
|
|
1385
|
+
}
|
|
1362
1386
|
/**
|
|
1363
1387
|
* Internal: set the scene and callbacks. Called by Scene.spawn().
|
|
1364
1388
|
* @internal
|
|
@@ -1367,6 +1391,20 @@ var Entity = class {
|
|
|
1367
1391
|
this._scene = scene;
|
|
1368
1392
|
this.callbacks = callbacks;
|
|
1369
1393
|
}
|
|
1394
|
+
/**
|
|
1395
|
+
* Internal: assign the stable identity key. Called by `Scene._registerKey`
|
|
1396
|
+
* during spawn. Throws if the entity already has a key — keys are
|
|
1397
|
+
* immutable for an entity's lifetime.
|
|
1398
|
+
* @internal
|
|
1399
|
+
*/
|
|
1400
|
+
_setKey(key) {
|
|
1401
|
+
if (this.key !== void 0) {
|
|
1402
|
+
throw new Error(
|
|
1403
|
+
`Entity "${this.name}" already has key "${this.key}".`
|
|
1404
|
+
);
|
|
1405
|
+
}
|
|
1406
|
+
this.key = key;
|
|
1407
|
+
}
|
|
1370
1408
|
};
|
|
1371
1409
|
|
|
1372
1410
|
// src/QueryCache.ts
|
|
@@ -2549,6 +2587,17 @@ function decodeBase64(base64) {
|
|
|
2549
2587
|
__name(decodeBase64, "decodeBase64");
|
|
2550
2588
|
|
|
2551
2589
|
// src/Scene.ts
|
|
2590
|
+
var _SPAWN_OPTION_KEYS = /* @__PURE__ */ new Set(["key"]);
|
|
2591
|
+
function _looksLikeSpawnOptions(v) {
|
|
2592
|
+
if (typeof v !== "object" || v === null || Array.isArray(v)) return false;
|
|
2593
|
+
const keys = Object.keys(v);
|
|
2594
|
+
if (keys.length === 0) return false;
|
|
2595
|
+
for (const k of keys) {
|
|
2596
|
+
if (!_SPAWN_OPTION_KEYS.has(k)) return false;
|
|
2597
|
+
}
|
|
2598
|
+
return true;
|
|
2599
|
+
}
|
|
2600
|
+
__name(_looksLikeSpawnOptions, "_looksLikeSpawnOptions");
|
|
2552
2601
|
var Scene = class {
|
|
2553
2602
|
static {
|
|
2554
2603
|
__name(this, "Scene");
|
|
@@ -2574,6 +2623,7 @@ var Scene = class {
|
|
|
2574
2623
|
_entityEventHandlers;
|
|
2575
2624
|
_entityEventObserver;
|
|
2576
2625
|
_scopedServices;
|
|
2626
|
+
_identityIndex;
|
|
2577
2627
|
/** Access the EngineContext. */
|
|
2578
2628
|
get context() {
|
|
2579
2629
|
return this._context;
|
|
@@ -2622,10 +2672,26 @@ var Scene = class {
|
|
|
2622
2672
|
}, "set")
|
|
2623
2673
|
});
|
|
2624
2674
|
}
|
|
2625
|
-
spawn(nameOrBlueprintOrClass,
|
|
2675
|
+
spawn(nameOrBlueprintOrClass, paramsOrOptions, maybeOptions) {
|
|
2626
2676
|
if (typeof nameOrBlueprintOrClass === "function") {
|
|
2627
|
-
const
|
|
2677
|
+
const Ctor = nameOrBlueprintOrClass;
|
|
2678
|
+
const hasSetup = typeof Ctor.prototype.setup === "function";
|
|
2679
|
+
let params;
|
|
2680
|
+
let options2;
|
|
2681
|
+
if (maybeOptions !== void 0) {
|
|
2682
|
+
params = paramsOrOptions;
|
|
2683
|
+
options2 = maybeOptions;
|
|
2684
|
+
} else if (paramsOrOptions === void 0) {
|
|
2685
|
+
} else if (!hasSetup) {
|
|
2686
|
+
options2 = paramsOrOptions;
|
|
2687
|
+
} else if (_looksLikeSpawnOptions(paramsOrOptions)) {
|
|
2688
|
+
options2 = paramsOrOptions;
|
|
2689
|
+
} else {
|
|
2690
|
+
params = paramsOrOptions;
|
|
2691
|
+
}
|
|
2692
|
+
const entity2 = new Ctor();
|
|
2628
2693
|
entity2._setScene(this, this.entityCallbacks);
|
|
2694
|
+
if (options2?.key !== void 0) this._registerKey(entity2, options2.key);
|
|
2629
2695
|
this.entities.add(entity2);
|
|
2630
2696
|
this.bus?.emit("entity:created", { entity: entity2 });
|
|
2631
2697
|
entity2.setup?.(params);
|
|
@@ -2633,15 +2699,59 @@ var Scene = class {
|
|
|
2633
2699
|
}
|
|
2634
2700
|
const isBlueprint = typeof nameOrBlueprintOrClass === "object" && nameOrBlueprintOrClass !== null && "build" in nameOrBlueprintOrClass;
|
|
2635
2701
|
const name = isBlueprint ? nameOrBlueprintOrClass.name : nameOrBlueprintOrClass;
|
|
2702
|
+
let blueprintParams;
|
|
2703
|
+
let options;
|
|
2704
|
+
if (isBlueprint) {
|
|
2705
|
+
if (maybeOptions !== void 0) {
|
|
2706
|
+
blueprintParams = paramsOrOptions;
|
|
2707
|
+
options = maybeOptions;
|
|
2708
|
+
} else if (paramsOrOptions !== void 0 && _looksLikeSpawnOptions(paramsOrOptions)) {
|
|
2709
|
+
options = paramsOrOptions;
|
|
2710
|
+
} else {
|
|
2711
|
+
blueprintParams = paramsOrOptions;
|
|
2712
|
+
}
|
|
2713
|
+
} else {
|
|
2714
|
+
options = paramsOrOptions;
|
|
2715
|
+
}
|
|
2636
2716
|
const entity = new Entity(name);
|
|
2637
2717
|
entity._setScene(this, this.entityCallbacks);
|
|
2718
|
+
if (options?.key !== void 0) this._registerKey(entity, options.key);
|
|
2638
2719
|
this.entities.add(entity);
|
|
2639
2720
|
this.bus?.emit("entity:created", { entity });
|
|
2640
2721
|
if (isBlueprint) {
|
|
2641
|
-
nameOrBlueprintOrClass.build(
|
|
2722
|
+
nameOrBlueprintOrClass.build(
|
|
2723
|
+
entity,
|
|
2724
|
+
blueprintParams
|
|
2725
|
+
);
|
|
2642
2726
|
}
|
|
2643
2727
|
return entity;
|
|
2644
2728
|
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Look up an entity by its stable identity key, scoped to this scene.
|
|
2731
|
+
* Returns `undefined` for unknown or already-destroyed entities.
|
|
2732
|
+
*/
|
|
2733
|
+
findByKey(key) {
|
|
2734
|
+
const entity = this._identityIndex?.get(key);
|
|
2735
|
+
if (!entity || entity.isDestroyed) return void 0;
|
|
2736
|
+
return entity;
|
|
2737
|
+
}
|
|
2738
|
+
/**
|
|
2739
|
+
* Internal: register a key on a freshly spawned entity. Throws on
|
|
2740
|
+
* duplicate so callers (Scene.spawn) can abort before adding to
|
|
2741
|
+
* `this.entities` or emitting `entity:created`.
|
|
2742
|
+
* @internal
|
|
2743
|
+
*/
|
|
2744
|
+
_registerKey(entity, key) {
|
|
2745
|
+
this._identityIndex ??= /* @__PURE__ */ new Map();
|
|
2746
|
+
const existing = this._identityIndex.get(key);
|
|
2747
|
+
if (existing && !existing.isDestroyed) {
|
|
2748
|
+
throw new Error(
|
|
2749
|
+
`Scene "${this.name}" already has an entity with key "${key}". Destroy it before spawning a duplicate.`
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
entity._setKey(key);
|
|
2753
|
+
this._identityIndex.set(key, entity);
|
|
2754
|
+
}
|
|
2645
2755
|
/**
|
|
2646
2756
|
* Add an existing entity to this scene (used by Entity.addChild for auto-scene-membership).
|
|
2647
2757
|
* @internal
|
|
@@ -2792,12 +2902,17 @@ var Scene = class {
|
|
|
2792
2902
|
entity._performDestroy();
|
|
2793
2903
|
this.queryCache?.onEntityDestroyed(entity);
|
|
2794
2904
|
this.entities.delete(entity);
|
|
2905
|
+
if (entity.key !== void 0 && this._identityIndex?.get(entity.key) === entity) {
|
|
2906
|
+
this._identityIndex.delete(entity.key);
|
|
2907
|
+
}
|
|
2795
2908
|
this.bus?.emit("entity:destroyed", { entity });
|
|
2796
2909
|
}
|
|
2797
2910
|
this.destroyQueue.length = 0;
|
|
2798
2911
|
}
|
|
2799
2912
|
/**
|
|
2800
|
-
* Destroy all entities — used during scene exit.
|
|
2913
|
+
* Destroy all entities — used during scene exit. Clears the identity
|
|
2914
|
+
* index in bulk; per-entity key removal in `_flushDestroyQueue` is the
|
|
2915
|
+
* in-game path.
|
|
2801
2916
|
* @internal
|
|
2802
2917
|
*/
|
|
2803
2918
|
_destroyAllEntities() {
|
|
@@ -2808,6 +2923,7 @@ var Scene = class {
|
|
|
2808
2923
|
this.entities.clear();
|
|
2809
2924
|
this.destroyQueue.length = 0;
|
|
2810
2925
|
this._entityEventHandlers?.clear();
|
|
2926
|
+
this._identityIndex?.clear();
|
|
2811
2927
|
}
|
|
2812
2928
|
};
|
|
2813
2929
|
|
|
@@ -4471,6 +4587,387 @@ function advanceFrames(engine, n, dtMs = 1e3 / 60) {
|
|
|
4471
4587
|
}
|
|
4472
4588
|
__name(advanceFrames, "advanceFrames");
|
|
4473
4589
|
|
|
4590
|
+
// src/state/Atom.ts
|
|
4591
|
+
function createAtom(initial) {
|
|
4592
|
+
let value = initial;
|
|
4593
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4594
|
+
return {
|
|
4595
|
+
get() {
|
|
4596
|
+
return value;
|
|
4597
|
+
},
|
|
4598
|
+
set(next) {
|
|
4599
|
+
if (Object.is(value, next)) return;
|
|
4600
|
+
value = next;
|
|
4601
|
+
for (const fn of listeners) fn(value);
|
|
4602
|
+
},
|
|
4603
|
+
subscribe(listener) {
|
|
4604
|
+
listeners.add(listener);
|
|
4605
|
+
return () => {
|
|
4606
|
+
listeners.delete(listener);
|
|
4607
|
+
};
|
|
4608
|
+
}
|
|
4609
|
+
};
|
|
4610
|
+
}
|
|
4611
|
+
__name(createAtom, "createAtom");
|
|
4612
|
+
|
|
4613
|
+
// src/state/Store.ts
|
|
4614
|
+
function createStore(initial) {
|
|
4615
|
+
let snapshot = { ...initial };
|
|
4616
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
4617
|
+
return {
|
|
4618
|
+
get() {
|
|
4619
|
+
return snapshot;
|
|
4620
|
+
},
|
|
4621
|
+
set(partial) {
|
|
4622
|
+
let changed = false;
|
|
4623
|
+
for (const key of Object.keys(partial)) {
|
|
4624
|
+
if (!Object.is(snapshot[key], partial[key])) {
|
|
4625
|
+
changed = true;
|
|
4626
|
+
break;
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
if (!changed) return;
|
|
4630
|
+
snapshot = { ...snapshot, ...partial };
|
|
4631
|
+
for (const fn of listeners) fn();
|
|
4632
|
+
},
|
|
4633
|
+
subscribe(listener) {
|
|
4634
|
+
listeners.add(listener);
|
|
4635
|
+
return () => {
|
|
4636
|
+
listeners.delete(listener);
|
|
4637
|
+
};
|
|
4638
|
+
}
|
|
4639
|
+
};
|
|
4640
|
+
}
|
|
4641
|
+
__name(createStore, "createStore");
|
|
4642
|
+
|
|
4643
|
+
// src/state/codecs.ts
|
|
4644
|
+
function jsonCodec() {
|
|
4645
|
+
return {
|
|
4646
|
+
encode: /* @__PURE__ */ __name((value) => value, "encode"),
|
|
4647
|
+
decode: /* @__PURE__ */ __name((raw) => raw, "decode")
|
|
4648
|
+
};
|
|
4649
|
+
}
|
|
4650
|
+
__name(jsonCodec, "jsonCodec");
|
|
4651
|
+
function setCodec() {
|
|
4652
|
+
return {
|
|
4653
|
+
encode: /* @__PURE__ */ __name((value) => Array.from(value), "encode"),
|
|
4654
|
+
decode: /* @__PURE__ */ __name((raw) => {
|
|
4655
|
+
if (!Array.isArray(raw)) {
|
|
4656
|
+
throw new Error("setCodec.decode: expected an array");
|
|
4657
|
+
}
|
|
4658
|
+
return new Set(raw);
|
|
4659
|
+
}, "decode")
|
|
4660
|
+
};
|
|
4661
|
+
}
|
|
4662
|
+
__name(setCodec, "setCodec");
|
|
4663
|
+
function mapCodec() {
|
|
4664
|
+
return {
|
|
4665
|
+
encode: /* @__PURE__ */ __name((value) => Array.from(value.entries()), "encode"),
|
|
4666
|
+
decode: /* @__PURE__ */ __name((raw) => {
|
|
4667
|
+
if (!Array.isArray(raw)) {
|
|
4668
|
+
throw new Error("mapCodec.decode: expected an array of entries");
|
|
4669
|
+
}
|
|
4670
|
+
return new Map(raw);
|
|
4671
|
+
}, "decode")
|
|
4672
|
+
};
|
|
4673
|
+
}
|
|
4674
|
+
__name(mapCodec, "mapCodec");
|
|
4675
|
+
function dateCodec() {
|
|
4676
|
+
return {
|
|
4677
|
+
encode: /* @__PURE__ */ __name((value) => value.toISOString(), "encode"),
|
|
4678
|
+
decode: /* @__PURE__ */ __name((raw) => {
|
|
4679
|
+
if (typeof raw !== "string") {
|
|
4680
|
+
throw new Error("dateCodec.decode: expected an ISO string");
|
|
4681
|
+
}
|
|
4682
|
+
const d = new Date(raw);
|
|
4683
|
+
if (Number.isNaN(d.getTime())) {
|
|
4684
|
+
throw new Error(`dateCodec.decode: invalid ISO string ${JSON.stringify(raw)}`);
|
|
4685
|
+
}
|
|
4686
|
+
return d;
|
|
4687
|
+
}, "decode")
|
|
4688
|
+
};
|
|
4689
|
+
}
|
|
4690
|
+
__name(dateCodec, "dateCodec");
|
|
4691
|
+
|
|
4692
|
+
// src/state/persistent.ts
|
|
4693
|
+
var registry3 = /* @__PURE__ */ new Map();
|
|
4694
|
+
function register(entry) {
|
|
4695
|
+
registry3.set(entry.id, entry);
|
|
4696
|
+
}
|
|
4697
|
+
__name(register, "register");
|
|
4698
|
+
function _resetAllStoresForTesting() {
|
|
4699
|
+
for (const entry of registry3.values()) entry.reset();
|
|
4700
|
+
}
|
|
4701
|
+
__name(_resetAllStoresForTesting, "_resetAllStoresForTesting");
|
|
4702
|
+
function _clearStoreRegistryForTesting() {
|
|
4703
|
+
registry3.clear();
|
|
4704
|
+
}
|
|
4705
|
+
__name(_clearStoreRegistryForTesting, "_clearStoreRegistryForTesting");
|
|
4706
|
+
var StoreVersionTooNewError = class extends Error {
|
|
4707
|
+
static {
|
|
4708
|
+
__name(this, "StoreVersionTooNewError");
|
|
4709
|
+
}
|
|
4710
|
+
storeId;
|
|
4711
|
+
storedVersion;
|
|
4712
|
+
currentVersion;
|
|
4713
|
+
constructor(storeId, storedVersion, currentVersion) {
|
|
4714
|
+
super(
|
|
4715
|
+
`Store "${storeId}" was saved at version ${storedVersion}, but this build is at version ${currentVersion}. Cannot downgrade.`
|
|
4716
|
+
);
|
|
4717
|
+
this.name = "StoreVersionTooNewError";
|
|
4718
|
+
this.storeId = storeId;
|
|
4719
|
+
this.storedVersion = storedVersion;
|
|
4720
|
+
this.currentVersion = currentVersion;
|
|
4721
|
+
}
|
|
4722
|
+
};
|
|
4723
|
+
var StoreMigrationMissingError = class extends Error {
|
|
4724
|
+
static {
|
|
4725
|
+
__name(this, "StoreMigrationMissingError");
|
|
4726
|
+
}
|
|
4727
|
+
storeId;
|
|
4728
|
+
storedVersion;
|
|
4729
|
+
currentVersion;
|
|
4730
|
+
constructor(storeId, storedVersion, currentVersion) {
|
|
4731
|
+
super(
|
|
4732
|
+
`Store "${storeId}" needs migration from version ${storedVersion} to ${currentVersion}, but no migrate() was provided.`
|
|
4733
|
+
);
|
|
4734
|
+
this.name = "StoreMigrationMissingError";
|
|
4735
|
+
this.storeId = storeId;
|
|
4736
|
+
this.storedVersion = storedVersion;
|
|
4737
|
+
this.currentVersion = currentVersion;
|
|
4738
|
+
}
|
|
4739
|
+
};
|
|
4740
|
+
function defineStore(id, opts) {
|
|
4741
|
+
const version = opts.version ?? 1;
|
|
4742
|
+
const codec = opts.codec ?? jsonCodec();
|
|
4743
|
+
const defaults = opts.defaults;
|
|
4744
|
+
const inner = createStore(defaults());
|
|
4745
|
+
const replaceAll = /* @__PURE__ */ __name((next) => {
|
|
4746
|
+
inner.set({ ...next });
|
|
4747
|
+
}, "replaceAll");
|
|
4748
|
+
const store = {
|
|
4749
|
+
id,
|
|
4750
|
+
version,
|
|
4751
|
+
get: inner.get,
|
|
4752
|
+
set: inner.set,
|
|
4753
|
+
subscribe: inner.subscribe,
|
|
4754
|
+
reset() {
|
|
4755
|
+
replaceAll(defaults());
|
|
4756
|
+
},
|
|
4757
|
+
serialize() {
|
|
4758
|
+
return { version, data: codec.encode(inner.get()) };
|
|
4759
|
+
},
|
|
4760
|
+
hydrate(payload) {
|
|
4761
|
+
if (payload.version > version) {
|
|
4762
|
+
throw new StoreVersionTooNewError(id, payload.version, version);
|
|
4763
|
+
}
|
|
4764
|
+
let next;
|
|
4765
|
+
if (payload.version < version) {
|
|
4766
|
+
if (!opts.migrate) {
|
|
4767
|
+
throw new StoreMigrationMissingError(id, payload.version, version);
|
|
4768
|
+
}
|
|
4769
|
+
next = opts.migrate(payload.data, payload.version);
|
|
4770
|
+
} else {
|
|
4771
|
+
next = codec.decode(payload.data);
|
|
4772
|
+
}
|
|
4773
|
+
replaceAll(next);
|
|
4774
|
+
}
|
|
4775
|
+
};
|
|
4776
|
+
register({ id, reset: /* @__PURE__ */ __name(() => store.reset(), "reset") });
|
|
4777
|
+
return store;
|
|
4778
|
+
}
|
|
4779
|
+
__name(defineStore, "defineStore");
|
|
4780
|
+
function defineSet(id, opts) {
|
|
4781
|
+
const version = opts?.version ?? 1;
|
|
4782
|
+
const defaults = /* @__PURE__ */ __name(() => new Set(opts?.defaults?.() ?? []), "defaults");
|
|
4783
|
+
const codec = setCodec();
|
|
4784
|
+
const atom = createAtom(defaults());
|
|
4785
|
+
const replace = /* @__PURE__ */ __name((next) => {
|
|
4786
|
+
atom.set(next);
|
|
4787
|
+
}, "replace");
|
|
4788
|
+
const store = {
|
|
4789
|
+
id,
|
|
4790
|
+
version,
|
|
4791
|
+
has(key) {
|
|
4792
|
+
return atom.get().has(key);
|
|
4793
|
+
},
|
|
4794
|
+
add(key) {
|
|
4795
|
+
const current = atom.get();
|
|
4796
|
+
if (current.has(key)) return;
|
|
4797
|
+
const next = new Set(current);
|
|
4798
|
+
next.add(key);
|
|
4799
|
+
replace(next);
|
|
4800
|
+
},
|
|
4801
|
+
remove(key) {
|
|
4802
|
+
const current = atom.get();
|
|
4803
|
+
if (!current.has(key)) return;
|
|
4804
|
+
const next = new Set(current);
|
|
4805
|
+
next.delete(key);
|
|
4806
|
+
replace(next);
|
|
4807
|
+
},
|
|
4808
|
+
clear() {
|
|
4809
|
+
if (atom.get().size === 0) return;
|
|
4810
|
+
replace(/* @__PURE__ */ new Set());
|
|
4811
|
+
},
|
|
4812
|
+
size() {
|
|
4813
|
+
return atom.get().size;
|
|
4814
|
+
},
|
|
4815
|
+
values() {
|
|
4816
|
+
return atom.get().values();
|
|
4817
|
+
},
|
|
4818
|
+
subscribe(listener) {
|
|
4819
|
+
return atom.subscribe(() => listener());
|
|
4820
|
+
},
|
|
4821
|
+
reset() {
|
|
4822
|
+
replace(defaults());
|
|
4823
|
+
},
|
|
4824
|
+
serialize() {
|
|
4825
|
+
return { version, data: codec.encode(atom.get()) };
|
|
4826
|
+
},
|
|
4827
|
+
hydrate(payload) {
|
|
4828
|
+
if (payload.version > version) {
|
|
4829
|
+
throw new StoreVersionTooNewError(id, payload.version, version);
|
|
4830
|
+
}
|
|
4831
|
+
if (payload.version < version) {
|
|
4832
|
+
if (!opts?.migrate) {
|
|
4833
|
+
throw new StoreMigrationMissingError(id, payload.version, version);
|
|
4834
|
+
}
|
|
4835
|
+
replace(opts.migrate(payload.data, payload.version));
|
|
4836
|
+
return;
|
|
4837
|
+
}
|
|
4838
|
+
replace(codec.decode(payload.data));
|
|
4839
|
+
}
|
|
4840
|
+
};
|
|
4841
|
+
register({ id, reset: /* @__PURE__ */ __name(() => store.reset(), "reset") });
|
|
4842
|
+
return store;
|
|
4843
|
+
}
|
|
4844
|
+
__name(defineSet, "defineSet");
|
|
4845
|
+
function defineMap(id, opts) {
|
|
4846
|
+
const version = opts?.version ?? 1;
|
|
4847
|
+
const defaults = /* @__PURE__ */ __name(() => new Map(opts?.defaults?.() ?? []), "defaults");
|
|
4848
|
+
const codec = mapCodec();
|
|
4849
|
+
const atom = createAtom(defaults());
|
|
4850
|
+
const replace = /* @__PURE__ */ __name((next) => {
|
|
4851
|
+
atom.set(next);
|
|
4852
|
+
}, "replace");
|
|
4853
|
+
const store = {
|
|
4854
|
+
id,
|
|
4855
|
+
version,
|
|
4856
|
+
has(key) {
|
|
4857
|
+
return atom.get().has(key);
|
|
4858
|
+
},
|
|
4859
|
+
get(key) {
|
|
4860
|
+
return atom.get().get(key);
|
|
4861
|
+
},
|
|
4862
|
+
set(key, value) {
|
|
4863
|
+
const current = atom.get();
|
|
4864
|
+
if (current.has(key) && Object.is(current.get(key), value)) return;
|
|
4865
|
+
const next = new Map(current);
|
|
4866
|
+
next.set(key, value);
|
|
4867
|
+
replace(next);
|
|
4868
|
+
},
|
|
4869
|
+
remove(key) {
|
|
4870
|
+
const current = atom.get();
|
|
4871
|
+
if (!current.has(key)) return;
|
|
4872
|
+
const next = new Map(current);
|
|
4873
|
+
next.delete(key);
|
|
4874
|
+
replace(next);
|
|
4875
|
+
},
|
|
4876
|
+
clear() {
|
|
4877
|
+
if (atom.get().size === 0) return;
|
|
4878
|
+
replace(/* @__PURE__ */ new Map());
|
|
4879
|
+
},
|
|
4880
|
+
size() {
|
|
4881
|
+
return atom.get().size;
|
|
4882
|
+
},
|
|
4883
|
+
entries() {
|
|
4884
|
+
return atom.get().entries();
|
|
4885
|
+
},
|
|
4886
|
+
subscribe(listener) {
|
|
4887
|
+
return atom.subscribe(() => listener());
|
|
4888
|
+
},
|
|
4889
|
+
reset() {
|
|
4890
|
+
replace(defaults());
|
|
4891
|
+
},
|
|
4892
|
+
serialize() {
|
|
4893
|
+
return { version, data: codec.encode(atom.get()) };
|
|
4894
|
+
},
|
|
4895
|
+
hydrate(payload) {
|
|
4896
|
+
if (payload.version > version) {
|
|
4897
|
+
throw new StoreVersionTooNewError(id, payload.version, version);
|
|
4898
|
+
}
|
|
4899
|
+
if (payload.version < version) {
|
|
4900
|
+
if (!opts?.migrate) {
|
|
4901
|
+
throw new StoreMigrationMissingError(id, payload.version, version);
|
|
4902
|
+
}
|
|
4903
|
+
replace(opts.migrate(payload.data, payload.version));
|
|
4904
|
+
return;
|
|
4905
|
+
}
|
|
4906
|
+
replace(codec.decode(payload.data));
|
|
4907
|
+
}
|
|
4908
|
+
};
|
|
4909
|
+
register({ id, reset: /* @__PURE__ */ __name(() => store.reset(), "reset") });
|
|
4910
|
+
return store;
|
|
4911
|
+
}
|
|
4912
|
+
__name(defineMap, "defineMap");
|
|
4913
|
+
function defineCounter(id, opts) {
|
|
4914
|
+
const version = opts?.version ?? 1;
|
|
4915
|
+
const defaults = /* @__PURE__ */ __name(() => opts?.defaults?.() ?? 0, "defaults");
|
|
4916
|
+
const atom = createAtom(defaults());
|
|
4917
|
+
const store = {
|
|
4918
|
+
id,
|
|
4919
|
+
version,
|
|
4920
|
+
value() {
|
|
4921
|
+
return atom.get();
|
|
4922
|
+
},
|
|
4923
|
+
set(n) {
|
|
4924
|
+
atom.set(n);
|
|
4925
|
+
},
|
|
4926
|
+
increment(by = 1) {
|
|
4927
|
+
atom.set(atom.get() + by);
|
|
4928
|
+
},
|
|
4929
|
+
decrement(by = 1) {
|
|
4930
|
+
atom.set(atom.get() - by);
|
|
4931
|
+
},
|
|
4932
|
+
subscribe(listener) {
|
|
4933
|
+
return atom.subscribe(() => listener());
|
|
4934
|
+
},
|
|
4935
|
+
reset() {
|
|
4936
|
+
atom.set(defaults());
|
|
4937
|
+
},
|
|
4938
|
+
serialize() {
|
|
4939
|
+
return { version, data: atom.get() };
|
|
4940
|
+
},
|
|
4941
|
+
hydrate(payload) {
|
|
4942
|
+
if (payload.version > version) {
|
|
4943
|
+
throw new StoreVersionTooNewError(id, payload.version, version);
|
|
4944
|
+
}
|
|
4945
|
+
if (payload.version < version) {
|
|
4946
|
+
if (!opts?.migrate) {
|
|
4947
|
+
throw new StoreMigrationMissingError(id, payload.version, version);
|
|
4948
|
+
}
|
|
4949
|
+
const migrated = opts.migrate(payload.data, payload.version);
|
|
4950
|
+
if (typeof migrated !== "number") {
|
|
4951
|
+
throw new Error(
|
|
4952
|
+
`defineCounter "${id}".hydrate: migrate returned non-number ${typeof migrated}`
|
|
4953
|
+
);
|
|
4954
|
+
}
|
|
4955
|
+
atom.set(migrated);
|
|
4956
|
+
return;
|
|
4957
|
+
}
|
|
4958
|
+
if (typeof payload.data !== "number") {
|
|
4959
|
+
throw new Error(
|
|
4960
|
+
`defineCounter "${id}".hydrate: expected number, got ${typeof payload.data}`
|
|
4961
|
+
);
|
|
4962
|
+
}
|
|
4963
|
+
atom.set(payload.data);
|
|
4964
|
+
}
|
|
4965
|
+
};
|
|
4966
|
+
register({ id, reset: /* @__PURE__ */ __name(() => store.reset(), "reset") });
|
|
4967
|
+
return store;
|
|
4968
|
+
}
|
|
4969
|
+
__name(defineCounter, "defineCounter");
|
|
4970
|
+
|
|
4474
4971
|
// src/index.ts
|
|
4475
4972
|
var VERSION = "0.0.0";
|
|
4476
4973
|
export {
|
|
@@ -4519,6 +5016,8 @@ export {
|
|
|
4519
5016
|
Sequence,
|
|
4520
5017
|
SerializableRegistry,
|
|
4521
5018
|
ServiceKey,
|
|
5019
|
+
StoreMigrationMissingError,
|
|
5020
|
+
StoreVersionTooNewError,
|
|
4522
5021
|
System,
|
|
4523
5022
|
SystemScheduler,
|
|
4524
5023
|
SystemSchedulerKey,
|
|
@@ -4528,16 +5027,25 @@ export {
|
|
|
4528
5027
|
Tween,
|
|
4529
5028
|
VERSION,
|
|
4530
5029
|
Vec2,
|
|
5030
|
+
_clearStoreRegistryForTesting,
|
|
5031
|
+
_resetAllStoresForTesting,
|
|
4531
5032
|
_resetEntityIdCounter,
|
|
4532
5033
|
advanceFrames,
|
|
5034
|
+
createAtom,
|
|
4533
5035
|
createDefaultRandomSeed,
|
|
4534
5036
|
createKeyframeTrack,
|
|
4535
5037
|
createMockEntity,
|
|
4536
5038
|
createMockScene,
|
|
4537
5039
|
createRandomService,
|
|
5040
|
+
createStore,
|
|
4538
5041
|
createTestEngine,
|
|
5042
|
+
dateCodec,
|
|
4539
5043
|
defineBlueprint,
|
|
5044
|
+
defineCounter,
|
|
4540
5045
|
defineEvent,
|
|
5046
|
+
defineMap,
|
|
5047
|
+
defineSet,
|
|
5048
|
+
defineStore,
|
|
4541
5049
|
defineTrait,
|
|
4542
5050
|
easeInOutQuad,
|
|
4543
5051
|
easeInQuad,
|
|
@@ -4550,13 +5058,16 @@ export {
|
|
|
4550
5058
|
interpolate,
|
|
4551
5059
|
isPointerConsumeContainer,
|
|
4552
5060
|
isSerializable,
|
|
5061
|
+
jsonCodec,
|
|
4553
5062
|
makeEntityScopedQueue,
|
|
4554
5063
|
makeGlobalScopedQueue,
|
|
4555
5064
|
makeSceneScopedQueue,
|
|
5065
|
+
mapCodec,
|
|
4556
5066
|
markPointerConsumeContainer,
|
|
4557
5067
|
normalizeSeed,
|
|
4558
5068
|
resolveTransition,
|
|
4559
5069
|
serializable,
|
|
5070
|
+
setCodec,
|
|
4560
5071
|
trait,
|
|
4561
5072
|
unmarkPointerConsumeContainer
|
|
4562
5073
|
};
|