@cosystem/core 0.0.2 → 1.0.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.d.mts +113 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +791 -68
- package/dist/index.mjs.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +6 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { create, createReactiveTracker } from "coaction";
|
|
1
|
+
import { computed as computed$1, create, createReactiveTracker } from "coaction";
|
|
2
2
|
//#region src/errors.ts
|
|
3
3
|
var CosystemError = class extends Error {
|
|
4
4
|
constructor(message) {
|
|
@@ -184,7 +184,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
184
184
|
if (record === void 0) return;
|
|
185
185
|
const context = this.createResolutionContext("sync");
|
|
186
186
|
const value = this.resolveRecord(record, context);
|
|
187
|
-
if (isPromiseLike(value)) throw new AsyncProviderInSyncResolutionError(record.tokenName);
|
|
187
|
+
if (isPromiseLike$1(value)) throw new AsyncProviderInSyncResolutionError(record.tokenName);
|
|
188
188
|
return value;
|
|
189
189
|
}
|
|
190
190
|
getAll(token) {
|
|
@@ -192,7 +192,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
192
192
|
const context = this.createResolutionContext("sync");
|
|
193
193
|
return records.map((record) => {
|
|
194
194
|
const value = this.resolveRecord(record, context);
|
|
195
|
-
if (isPromiseLike(value)) throw new AsyncProviderInSyncResolutionError(record.tokenName);
|
|
195
|
+
if (isPromiseLike$1(value)) throw new AsyncProviderInSyncResolutionError(record.tokenName);
|
|
196
196
|
return value;
|
|
197
197
|
});
|
|
198
198
|
}
|
|
@@ -227,7 +227,13 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
227
227
|
const deps = options.deps ?? target.inject ?? [];
|
|
228
228
|
const context = this.createResolutionContext("sync");
|
|
229
229
|
const values = this.resolveDependencies(deps, context);
|
|
230
|
-
if (isPromiseLike(values)) throw new AsyncProviderInSyncResolutionError(target.name);
|
|
230
|
+
if (isPromiseLike$1(values)) throw new AsyncProviderInSyncResolutionError(target.name);
|
|
231
|
+
return Reflect.construct(target, values);
|
|
232
|
+
}
|
|
233
|
+
async buildAsync(target, options = {}) {
|
|
234
|
+
const deps = options.deps ?? target.inject ?? [];
|
|
235
|
+
const context = this.createResolutionContext("async");
|
|
236
|
+
const values = await this.resolveDependencies(deps, context);
|
|
231
237
|
return Reflect.construct(target, values);
|
|
232
238
|
}
|
|
233
239
|
freeze() {
|
|
@@ -301,7 +307,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
301
307
|
};
|
|
302
308
|
try {
|
|
303
309
|
const value = this.createValue(record, context);
|
|
304
|
-
if (isPromiseLike(value)) {
|
|
310
|
+
if (isPromiseLike$1(value)) {
|
|
305
311
|
if (context.mode === "sync") throw new AsyncProviderInSyncResolutionError(record.tokenName);
|
|
306
312
|
return Promise.resolve(value).then(finalize, fail);
|
|
307
313
|
}
|
|
@@ -315,14 +321,14 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
315
321
|
case "class": {
|
|
316
322
|
const provider = record.provider;
|
|
317
323
|
const deps = this.resolveDependencies(record.deps, context);
|
|
318
|
-
if (isPromiseLike(deps)) return Promise.resolve(deps).then((values) => Reflect.construct(provider.useClass, values));
|
|
324
|
+
if (isPromiseLike$1(deps)) return Promise.resolve(deps).then((values) => Reflect.construct(provider.useClass, values));
|
|
319
325
|
return Reflect.construct(provider.useClass, deps);
|
|
320
326
|
}
|
|
321
327
|
case "value": return record.provider.useValue;
|
|
322
328
|
case "factory": {
|
|
323
329
|
const provider = record.provider;
|
|
324
330
|
const deps = this.resolveDependencies(record.deps, context);
|
|
325
|
-
if (isPromiseLike(deps)) return Promise.resolve(deps).then((values) => runWithInjectContext(context, () => provider.useFactory(...values)));
|
|
331
|
+
if (isPromiseLike$1(deps)) return Promise.resolve(deps).then((values) => runWithInjectContext(context, () => provider.useFactory(...values)));
|
|
326
332
|
return runWithInjectContext(context, () => provider.useFactory(...deps));
|
|
327
333
|
}
|
|
328
334
|
case "existing": return this.resolveDependency(record.provider.useExisting, context);
|
|
@@ -333,7 +339,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
333
339
|
const asyncValues = [];
|
|
334
340
|
for (const [index, dep] of deps.entries()) {
|
|
335
341
|
const value = this.resolveDependency(dep, context);
|
|
336
|
-
if (isPromiseLike(value)) asyncValues.push(Promise.resolve(value).then((resolved) => {
|
|
342
|
+
if (isPromiseLike$1(value)) asyncValues.push(Promise.resolve(value).then((resolved) => {
|
|
337
343
|
values[index] = resolved;
|
|
338
344
|
return resolved;
|
|
339
345
|
}));
|
|
@@ -362,7 +368,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
362
368
|
}
|
|
363
369
|
resolveAllRecords(records, context) {
|
|
364
370
|
const values = records.map((record) => this.resolveRecord(record, context));
|
|
365
|
-
if (values.some(isPromiseLike)) return Promise.all(values);
|
|
371
|
+
if (values.some(isPromiseLike$1)) return Promise.all(values);
|
|
366
372
|
return values;
|
|
367
373
|
}
|
|
368
374
|
getCached(record, context) {
|
|
@@ -415,7 +421,7 @@ var RuntimeContainer = class RuntimeContainer {
|
|
|
415
421
|
function isDependencyObject(dep) {
|
|
416
422
|
return typeof dep === "object" && dep !== null && "token" in dep;
|
|
417
423
|
}
|
|
418
|
-
function isPromiseLike(value) {
|
|
424
|
+
function isPromiseLike$1(value) {
|
|
419
425
|
return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
420
426
|
}
|
|
421
427
|
function isLifetimeLeak(parentScope, childScope) {
|
|
@@ -442,6 +448,47 @@ async function disposeValue(value, record) {
|
|
|
442
448
|
if (typeof maybeDisposable.destroy === "function") await maybeDisposable.destroy();
|
|
443
449
|
}
|
|
444
450
|
//#endregion
|
|
451
|
+
//#region src/lazyModule.ts
|
|
452
|
+
function lazyModule(load) {
|
|
453
|
+
return {
|
|
454
|
+
kind: "lazyModule",
|
|
455
|
+
load
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function isLazyModule(input) {
|
|
459
|
+
return typeof input === "object" && input !== null && "kind" in input && input.kind === "lazyModule" && "load" in input && typeof input.load === "function";
|
|
460
|
+
}
|
|
461
|
+
function normalizeLazyModuleProviders(input) {
|
|
462
|
+
if (isProviderInput(input)) return [input];
|
|
463
|
+
if (Array.isArray(input)) {
|
|
464
|
+
assertProviderArray(input);
|
|
465
|
+
return input;
|
|
466
|
+
}
|
|
467
|
+
if (typeof input === "object" && input !== null) {
|
|
468
|
+
const exports = input;
|
|
469
|
+
const providers = [];
|
|
470
|
+
if (exports.providers !== void 0) {
|
|
471
|
+
assertProviderArray(exports.providers);
|
|
472
|
+
providers.push(...exports.providers);
|
|
473
|
+
}
|
|
474
|
+
if (exports.default !== void 0) if (Array.isArray(exports.default)) {
|
|
475
|
+
assertProviderArray(exports.default);
|
|
476
|
+
providers.push(...exports.default);
|
|
477
|
+
} else if (isProviderInput(exports.default)) providers.push(exports.default);
|
|
478
|
+
else throw new CosystemError("Lazy module default export must be a provider or provider array.");
|
|
479
|
+
if (providers.length > 0) return providers;
|
|
480
|
+
}
|
|
481
|
+
throw new CosystemError("Lazy module loader must return a provider, provider array, or module exports with providers/default.");
|
|
482
|
+
}
|
|
483
|
+
function assertProviderArray(values) {
|
|
484
|
+
if (values.every(isProviderInput)) return;
|
|
485
|
+
throw new CosystemError("Lazy module provider arrays may only contain provider entries.");
|
|
486
|
+
}
|
|
487
|
+
function isProviderInput(value) {
|
|
488
|
+
if (typeof value === "function") return true;
|
|
489
|
+
return typeof value === "object" && value !== null && "provide" in value && ("useClass" in value || "useValue" in value || "useFactory" in value || "useExisting" in value);
|
|
490
|
+
}
|
|
491
|
+
//#endregion
|
|
445
492
|
//#region src/metadata.ts
|
|
446
493
|
const moduleMetadata = /* @__PURE__ */ new WeakMap();
|
|
447
494
|
const moduleMetadataKey = Symbol.for("@cosystem/core/moduleMetadata");
|
|
@@ -452,8 +499,9 @@ function defineModule(target, options = {}, context) {
|
|
|
452
499
|
applyModuleOptions(metadata, options);
|
|
453
500
|
addProperties(metadata.state, options.state);
|
|
454
501
|
addProperties(metadata.actions, options.actions);
|
|
455
|
-
writeContextMetadata(context, metadata);
|
|
456
502
|
addProperties(metadata.computed, options.computed);
|
|
503
|
+
addProperties(metadata.effects, options.effects);
|
|
504
|
+
writeContextMetadata(context, metadata);
|
|
457
505
|
return target;
|
|
458
506
|
}
|
|
459
507
|
function getModuleMetadata(target) {
|
|
@@ -473,6 +521,9 @@ function addModuleAction(target, property) {
|
|
|
473
521
|
function addModuleComputed(target, property) {
|
|
474
522
|
ensureModuleMetadata(target).computed.add(property);
|
|
475
523
|
}
|
|
524
|
+
function addModuleEffect(target, property) {
|
|
525
|
+
ensureModuleMetadata(target).effects.add(property);
|
|
526
|
+
}
|
|
476
527
|
function applyModuleOptions(metadata, options) {
|
|
477
528
|
if (options.name !== void 0) metadata.name = options.name;
|
|
478
529
|
if (options.deps !== void 0) metadata.deps = options.deps;
|
|
@@ -485,7 +536,8 @@ function ensureModuleMetadata(target) {
|
|
|
485
536
|
kind: "module",
|
|
486
537
|
state: /* @__PURE__ */ new Set(),
|
|
487
538
|
actions: /* @__PURE__ */ new Set(),
|
|
488
|
-
computed: /* @__PURE__ */ new Set()
|
|
539
|
+
computed: /* @__PURE__ */ new Set(),
|
|
540
|
+
effects: /* @__PURE__ */ new Set()
|
|
489
541
|
};
|
|
490
542
|
moduleMetadata.set(target, metadata);
|
|
491
543
|
return metadata;
|
|
@@ -506,7 +558,8 @@ function createModuleMetadata() {
|
|
|
506
558
|
kind: "module",
|
|
507
559
|
state: /* @__PURE__ */ new Set(),
|
|
508
560
|
actions: /* @__PURE__ */ new Set(),
|
|
509
|
-
computed: /* @__PURE__ */ new Set()
|
|
561
|
+
computed: /* @__PURE__ */ new Set(),
|
|
562
|
+
effects: /* @__PURE__ */ new Set()
|
|
510
563
|
};
|
|
511
564
|
}
|
|
512
565
|
function readContextMetadata(context) {
|
|
@@ -530,9 +583,10 @@ function mergeModuleMetadata(target, source) {
|
|
|
530
583
|
addProperties(target.state, [...source.state]);
|
|
531
584
|
addProperties(target.actions, [...source.actions]);
|
|
532
585
|
addProperties(target.computed, [...source.computed]);
|
|
586
|
+
addProperties(target.effects, [...source.effects]);
|
|
533
587
|
}
|
|
534
588
|
function isModuleMetadata(value) {
|
|
535
|
-
return typeof value === "object" && value !== null && value.kind === "module" && value instanceof Object && value.state instanceof Set && value.actions instanceof Set && value.computed instanceof Set;
|
|
589
|
+
return typeof value === "object" && value !== null && value.kind === "module" && value instanceof Object && value.state instanceof Set && value.actions instanceof Set && value.computed instanceof Set && value.effects instanceof Set;
|
|
536
590
|
}
|
|
537
591
|
//#endregion
|
|
538
592
|
//#region src/app.ts
|
|
@@ -541,22 +595,37 @@ const appContainerMap = /* @__PURE__ */ new WeakMap();
|
|
|
541
595
|
function createApp(options = {}) {
|
|
542
596
|
return createAppInternal(options);
|
|
543
597
|
}
|
|
598
|
+
function runInAction(module, callback, options) {
|
|
599
|
+
const metadata = getRuntimeModuleMetadata(module);
|
|
600
|
+
if (metadata === void 0) throw new CosystemError("runInAction() target is not a CoSystem module instance.");
|
|
601
|
+
return metadata.app.runInAction(module, callback, options);
|
|
602
|
+
}
|
|
544
603
|
function createAppInternal(options = {}) {
|
|
545
604
|
const parent = isApp(options.parent) ? getAppContainer(options.parent) : options.parent;
|
|
546
605
|
const container = parent === void 0 ? createContainer() : createContainer({ parent });
|
|
547
606
|
const moduleTokens = [];
|
|
607
|
+
const lazyModules = [];
|
|
548
608
|
for (const provider of options.providers ?? []) {
|
|
609
|
+
if (isLazyModule(provider)) {
|
|
610
|
+
lazyModules.push(provider);
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
549
613
|
const normalized = normalizeAppProvider(provider);
|
|
550
614
|
container.provide(normalized.provider);
|
|
551
615
|
if (normalized.moduleToken !== void 0) moduleTokens.push(normalized.moduleToken);
|
|
552
616
|
}
|
|
553
|
-
for (const override of options.overrides ?? [])
|
|
617
|
+
for (const override of options.overrides ?? []) {
|
|
618
|
+
const normalized = normalizeAppProvider(override);
|
|
619
|
+
if (normalized.moduleToken !== void 0 && !moduleTokens.some((moduleToken) => moduleToken === normalized.moduleToken)) throw new CosystemError(`Cannot add ${tokenName(normalized.moduleToken)} as a new CoSystem module through overrides.`);
|
|
620
|
+
container.override(normalized.provider);
|
|
621
|
+
}
|
|
554
622
|
container.freeze();
|
|
555
623
|
const modules = instantiateModules(container, moduleTokens);
|
|
556
624
|
const store = create(createRootState(modules), createStoreOptions(options.engine, shouldEnablePatches(options)));
|
|
557
625
|
const app = new RuntimeApp({
|
|
558
626
|
container,
|
|
559
627
|
devOptions: options.devOptions ?? {},
|
|
628
|
+
lazyModules,
|
|
560
629
|
modules,
|
|
561
630
|
plugins: options.plugins ?? [],
|
|
562
631
|
state: { version: 0 },
|
|
@@ -565,6 +634,7 @@ function createAppInternal(options = {}) {
|
|
|
565
634
|
});
|
|
566
635
|
app.bindModules();
|
|
567
636
|
app.attachRuntimeMetadata();
|
|
637
|
+
instantiateEagerProviders(container);
|
|
568
638
|
app.runModuleCreatedHooks();
|
|
569
639
|
app.init();
|
|
570
640
|
appContainerMap.set(app, container);
|
|
@@ -576,16 +646,22 @@ var RuntimeApp = class {
|
|
|
576
646
|
#container;
|
|
577
647
|
devOptions;
|
|
578
648
|
modules;
|
|
649
|
+
pendingLazyModules;
|
|
579
650
|
moduleByToken = /* @__PURE__ */ new Map();
|
|
580
651
|
moduleByName = /* @__PURE__ */ new Map();
|
|
581
652
|
plugins;
|
|
582
653
|
testInspector;
|
|
654
|
+
effectDisposers = [];
|
|
655
|
+
pendingEffects = /* @__PURE__ */ new Set();
|
|
656
|
+
loadedLazyModules = /* @__PURE__ */ new WeakMap();
|
|
657
|
+
dynamicScopes = [];
|
|
583
658
|
initPromise = Promise.resolve();
|
|
584
659
|
isStarted = false;
|
|
585
660
|
isDisposed = false;
|
|
586
661
|
constructor(options) {
|
|
587
662
|
this.#container = options.container;
|
|
588
663
|
this.devOptions = options.devOptions;
|
|
664
|
+
this.pendingLazyModules = [...options.lazyModules];
|
|
589
665
|
this.modules = options.modules;
|
|
590
666
|
this.plugins = options.plugins;
|
|
591
667
|
this.state = options.state;
|
|
@@ -602,23 +678,28 @@ var RuntimeApp = class {
|
|
|
602
678
|
this.testInspector?.recordState(state);
|
|
603
679
|
this.emitStateChange({ state });
|
|
604
680
|
});
|
|
681
|
+
this.testInspector?.setFlushEffects(() => this.flushEffects());
|
|
605
682
|
}
|
|
606
683
|
get started() {
|
|
607
684
|
return this.isStarted;
|
|
608
685
|
}
|
|
609
686
|
get(token) {
|
|
687
|
+
const moduleBinding = this.moduleByToken.get(token);
|
|
688
|
+
if (moduleBinding !== void 0) return moduleBinding.instance;
|
|
610
689
|
return this.#container.get(token);
|
|
611
690
|
}
|
|
612
691
|
getAsync(token) {
|
|
692
|
+
const moduleBinding = this.moduleByToken.get(token);
|
|
693
|
+
if (moduleBinding !== void 0) return Promise.resolve(moduleBinding.instance);
|
|
613
694
|
return this.#container.getAsync(token);
|
|
614
695
|
}
|
|
615
696
|
getAll(token) {
|
|
616
697
|
return this.#container.getAll(token);
|
|
617
698
|
}
|
|
618
699
|
getModule(token) {
|
|
619
|
-
const
|
|
620
|
-
if (
|
|
621
|
-
return
|
|
700
|
+
const moduleBinding = this.moduleByToken.get(token);
|
|
701
|
+
if (moduleBinding === void 0) throw new CosystemError(`${tokenName(token)} is not a CoSystem module.`);
|
|
702
|
+
return moduleBinding.instance;
|
|
622
703
|
}
|
|
623
704
|
getModuleByName(name) {
|
|
624
705
|
const moduleBinding = this.moduleByName.get(name);
|
|
@@ -645,6 +726,10 @@ var RuntimeApp = class {
|
|
|
645
726
|
tracker.dispose();
|
|
646
727
|
};
|
|
647
728
|
}
|
|
729
|
+
runInAction(module, callback, options = {}) {
|
|
730
|
+
const moduleBinding = this.resolveModuleBinding(module);
|
|
731
|
+
return this.runActionCallback(moduleBinding, options.name ?? "runInAction", options.args ?? [], callback);
|
|
732
|
+
}
|
|
648
733
|
async start() {
|
|
649
734
|
if (this.isStarted) return;
|
|
650
735
|
await this.initPromise;
|
|
@@ -670,7 +755,10 @@ var RuntimeApp = class {
|
|
|
670
755
|
if (this.isDisposed) return;
|
|
671
756
|
await this.stop();
|
|
672
757
|
try {
|
|
758
|
+
this.stopEffects();
|
|
759
|
+
await this.waitForPendingEffects();
|
|
673
760
|
await this.runLifecycle("onDispose", true);
|
|
761
|
+
for (const scope of this.dynamicScopes.toReversed()) await scope.dispose();
|
|
674
762
|
await Promise.all(this.plugins.map((plugin) => plugin.dispose?.()));
|
|
675
763
|
await this.#container.dispose();
|
|
676
764
|
this.store.destroy();
|
|
@@ -683,15 +771,59 @@ var RuntimeApp = class {
|
|
|
683
771
|
createScope(options) {
|
|
684
772
|
return { container: this.#container.createScope(options) };
|
|
685
773
|
}
|
|
686
|
-
|
|
687
|
-
|
|
774
|
+
async load(module) {
|
|
775
|
+
if (module === void 0) {
|
|
776
|
+
const modules = this.pendingLazyModules.splice(0);
|
|
777
|
+
const results = [];
|
|
778
|
+
for (const pendingModule of modules) results.push(await this.load(pendingModule));
|
|
779
|
+
return results;
|
|
780
|
+
}
|
|
781
|
+
const existing = this.loadedLazyModules.get(module);
|
|
782
|
+
if (existing !== void 0) return existing;
|
|
783
|
+
if (this.isDisposed) throw new CosystemError("Cannot load a lazy module after app disposal.");
|
|
784
|
+
await this.initPromise;
|
|
785
|
+
try {
|
|
786
|
+
const providers = normalizeLazyModuleProviders(await module.load());
|
|
787
|
+
const scopeContainer = this.#container.createScope();
|
|
788
|
+
const moduleTokens = [];
|
|
789
|
+
for (const provider of providers) {
|
|
790
|
+
const normalized = normalizeAppProvider(provider);
|
|
791
|
+
scopeContainer.provide(normalized.provider);
|
|
792
|
+
if (normalized.moduleToken !== void 0) moduleTokens.push(normalized.moduleToken);
|
|
793
|
+
}
|
|
794
|
+
scopeContainer.freeze();
|
|
795
|
+
const loadedModules = instantiateModules(scopeContainer, moduleTokens, false);
|
|
796
|
+
this.assertNewModules(loadedModules);
|
|
797
|
+
this.installModuleState(loadedModules);
|
|
798
|
+
this.registerModules(loadedModules);
|
|
799
|
+
this.bindModules(loadedModules);
|
|
800
|
+
this.attachRuntimeMetadata(loadedModules);
|
|
801
|
+
instantiateEagerProviders(scopeContainer);
|
|
802
|
+
this.dynamicScopes.push(scopeContainer);
|
|
803
|
+
this.runModuleCreatedHooks(loadedModules);
|
|
804
|
+
await this.runLifecycle("onInit", false, loadedModules);
|
|
805
|
+
this.startEffects(loadedModules);
|
|
806
|
+
if (this.isStarted) await this.runLifecycle("onStart", false, loadedModules);
|
|
807
|
+
const result = {
|
|
808
|
+
modules: loadedModules.map(toModuleCreatedEvent),
|
|
809
|
+
scope: { container: scopeContainer }
|
|
810
|
+
};
|
|
811
|
+
this.loadedLazyModules.set(module, result);
|
|
812
|
+
return result;
|
|
813
|
+
} catch (error) {
|
|
814
|
+
this.emitError(error, { phase: "load" });
|
|
815
|
+
throw error;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
bindModules(modules = this.modules) {
|
|
819
|
+
for (const moduleBinding of modules) {
|
|
688
820
|
this.bindState(moduleBinding);
|
|
689
821
|
this.bindComputed(moduleBinding);
|
|
690
822
|
this.bindActions(moduleBinding);
|
|
691
823
|
}
|
|
692
824
|
}
|
|
693
|
-
attachRuntimeMetadata() {
|
|
694
|
-
for (const moduleBinding of
|
|
825
|
+
attachRuntimeMetadata(modules = this.modules) {
|
|
826
|
+
for (const moduleBinding of modules) Object.defineProperty(moduleBinding.instance, runtimeModuleMetadataKey, {
|
|
695
827
|
configurable: false,
|
|
696
828
|
enumerable: false,
|
|
697
829
|
value: {
|
|
@@ -701,13 +833,9 @@ var RuntimeApp = class {
|
|
|
701
833
|
}
|
|
702
834
|
});
|
|
703
835
|
}
|
|
704
|
-
runModuleCreatedHooks() {
|
|
705
|
-
for (const moduleBinding of
|
|
706
|
-
const event =
|
|
707
|
-
name: moduleBinding.name,
|
|
708
|
-
token: moduleBinding.token,
|
|
709
|
-
instance: moduleBinding.instance
|
|
710
|
-
};
|
|
836
|
+
runModuleCreatedHooks(modules = this.modules) {
|
|
837
|
+
for (const moduleBinding of modules) {
|
|
838
|
+
const event = toModuleCreatedEvent(moduleBinding);
|
|
711
839
|
for (const plugin of this.plugins) plugin.onModuleCreated?.(event);
|
|
712
840
|
}
|
|
713
841
|
}
|
|
@@ -716,6 +844,7 @@ var RuntimeApp = class {
|
|
|
716
844
|
try {
|
|
717
845
|
await Promise.all(this.plugins.map((plugin) => this.runWithAppInjectContext(() => plugin.setup?.(this))));
|
|
718
846
|
await this.runLifecycle("onInit");
|
|
847
|
+
this.startEffects();
|
|
719
848
|
} catch (error) {
|
|
720
849
|
this.emitError(error, { phase: "init" });
|
|
721
850
|
throw error;
|
|
@@ -743,15 +872,21 @@ var RuntimeApp = class {
|
|
|
743
872
|
bindComputed(moduleBinding) {
|
|
744
873
|
for (const property of moduleBinding.metadata.computed) {
|
|
745
874
|
const getter = getGetter(moduleBinding.instance, property);
|
|
875
|
+
const accessor = computed$1(() => getter.call(moduleBinding.instance));
|
|
746
876
|
moduleBinding.originalComputed.set(property, getter);
|
|
877
|
+
moduleBinding.computedAccessors.set(property, accessor);
|
|
747
878
|
Object.defineProperty(moduleBinding.instance, property, {
|
|
748
879
|
configurable: true,
|
|
749
880
|
enumerable: true,
|
|
750
|
-
get: () =>
|
|
881
|
+
get: () => {
|
|
882
|
+
if (moduleBinding.activeDraft !== void 0 || !moduleBinding.reactiveSlice) return getter.call(moduleBinding.instance);
|
|
883
|
+
return accessor();
|
|
884
|
+
}
|
|
751
885
|
});
|
|
752
886
|
}
|
|
753
887
|
}
|
|
754
888
|
readModuleState(moduleBinding, property) {
|
|
889
|
+
if (!moduleBinding.reactiveSlice) return this.store.getPureState()[moduleBinding.name]?.[property];
|
|
755
890
|
return this.store.getState()[moduleBinding.name]?.[property];
|
|
756
891
|
}
|
|
757
892
|
writeModuleState(moduleBinding, property, value) {
|
|
@@ -760,6 +895,18 @@ var RuntimeApp = class {
|
|
|
760
895
|
return;
|
|
761
896
|
}
|
|
762
897
|
if (this.devOptions.strictActions === true && moduleBinding.actionDepth === 0) throw new CosystemError(`Cannot write ${moduleBinding.name}.${String(property)} outside an action.`);
|
|
898
|
+
if (!moduleBinding.reactiveSlice) {
|
|
899
|
+
const state = this.store.getPureState();
|
|
900
|
+
const slice = state[moduleBinding.name] ?? {};
|
|
901
|
+
this.store.setState({
|
|
902
|
+
...state,
|
|
903
|
+
[moduleBinding.name]: {
|
|
904
|
+
...slice,
|
|
905
|
+
[property]: value
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
763
910
|
this.store.setState((draft) => {
|
|
764
911
|
draft[moduleBinding.name] ??= {};
|
|
765
912
|
draft[moduleBinding.name][property] = value;
|
|
@@ -768,6 +915,9 @@ var RuntimeApp = class {
|
|
|
768
915
|
runAction(moduleBinding, property, args) {
|
|
769
916
|
const action = moduleBinding.originalActions.get(property);
|
|
770
917
|
if (action === void 0) throw new CosystemError(`${moduleBinding.name}.${String(property)} is not an action.`);
|
|
918
|
+
return this.runActionCallback(moduleBinding, property, args, () => action.apply(moduleBinding.instance, [...args]));
|
|
919
|
+
}
|
|
920
|
+
runActionCallback(moduleBinding, property, args, callback) {
|
|
771
921
|
const event = {
|
|
772
922
|
args,
|
|
773
923
|
method: String(property),
|
|
@@ -779,22 +929,76 @@ var RuntimeApp = class {
|
|
|
779
929
|
let error;
|
|
780
930
|
try {
|
|
781
931
|
moduleBinding.actionDepth += 1;
|
|
782
|
-
this.store.setState((draft) => {
|
|
932
|
+
if (moduleBinding.reactiveSlice) this.store.setState((draft) => {
|
|
783
933
|
const previousDraft = moduleBinding.activeDraft;
|
|
784
934
|
moduleBinding.activeDraft = draft[moduleBinding.name] ?? {};
|
|
785
935
|
draft[moduleBinding.name] = moduleBinding.activeDraft;
|
|
786
936
|
try {
|
|
787
|
-
result =
|
|
937
|
+
result = callback();
|
|
788
938
|
} finally {
|
|
789
939
|
moduleBinding.activeDraft = previousDraft;
|
|
790
940
|
}
|
|
791
941
|
});
|
|
942
|
+
else {
|
|
943
|
+
const state = this.store.getPureState();
|
|
944
|
+
const slice = state[moduleBinding.name];
|
|
945
|
+
const previousDraft = moduleBinding.activeDraft;
|
|
946
|
+
moduleBinding.activeDraft = slice === void 0 ? {} : { ...slice };
|
|
947
|
+
try {
|
|
948
|
+
result = callback();
|
|
949
|
+
this.store.setState({
|
|
950
|
+
...state,
|
|
951
|
+
[moduleBinding.name]: moduleBinding.activeDraft
|
|
952
|
+
});
|
|
953
|
+
} finally {
|
|
954
|
+
moduleBinding.activeDraft = previousDraft;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
792
957
|
} catch (caught) {
|
|
793
958
|
error = caught;
|
|
794
959
|
this.emitError(caught, { phase: "action" });
|
|
795
960
|
} finally {
|
|
796
961
|
moduleBinding.actionDepth -= 1;
|
|
797
962
|
}
|
|
963
|
+
if (error !== void 0) {
|
|
964
|
+
this.finishAction(event, error);
|
|
965
|
+
throw error;
|
|
966
|
+
}
|
|
967
|
+
if (isPromiseLike(result)) return Promise.resolve(result).then((value) => {
|
|
968
|
+
this.finishAction(event);
|
|
969
|
+
return value;
|
|
970
|
+
}, (caught) => {
|
|
971
|
+
this.emitError(caught, { phase: "action" });
|
|
972
|
+
this.finishAction(event, caught);
|
|
973
|
+
throw caught;
|
|
974
|
+
});
|
|
975
|
+
this.finishAction(event);
|
|
976
|
+
return result;
|
|
977
|
+
}
|
|
978
|
+
resolveModuleBinding(target) {
|
|
979
|
+
if (typeof target === "object" && target !== null) {
|
|
980
|
+
const metadata = getRuntimeModuleMetadata(target);
|
|
981
|
+
if (metadata !== void 0) {
|
|
982
|
+
if (metadata.app !== this) throw new CosystemError("runInAction() target belongs to another CoSystem app.");
|
|
983
|
+
const moduleBinding = this.moduleByToken.get(metadata.token);
|
|
984
|
+
if (moduleBinding !== void 0) return moduleBinding;
|
|
985
|
+
}
|
|
986
|
+
if (isTokenObject(target)) {
|
|
987
|
+
const moduleBinding = this.moduleByToken.get(target);
|
|
988
|
+
if (moduleBinding !== void 0) return moduleBinding;
|
|
989
|
+
}
|
|
990
|
+
throw new CosystemError("runInAction() target is not a CoSystem module.");
|
|
991
|
+
}
|
|
992
|
+
if (typeof target === "string") {
|
|
993
|
+
const moduleBinding = this.moduleByName.get(target) ?? this.moduleByToken.get(target);
|
|
994
|
+
if (moduleBinding !== void 0) return moduleBinding;
|
|
995
|
+
throw new CosystemError(`${target} is not a CoSystem module.`);
|
|
996
|
+
}
|
|
997
|
+
const moduleBinding = this.moduleByToken.get(target);
|
|
998
|
+
if (moduleBinding !== void 0) return moduleBinding;
|
|
999
|
+
throw new CosystemError(`${tokenName(target)} is not a CoSystem module.`);
|
|
1000
|
+
}
|
|
1001
|
+
finishAction(event, error) {
|
|
798
1002
|
const endedEvent = {
|
|
799
1003
|
...event,
|
|
800
1004
|
endedAt: Date.now(),
|
|
@@ -802,16 +1006,64 @@ var RuntimeApp = class {
|
|
|
802
1006
|
};
|
|
803
1007
|
this.testInspector?.recordAction(endedEvent);
|
|
804
1008
|
this.emitActionEnd(endedEvent);
|
|
805
|
-
if (error !== void 0) throw error;
|
|
806
|
-
return result;
|
|
807
1009
|
}
|
|
808
|
-
async runLifecycle(method, reverse = false) {
|
|
809
|
-
const
|
|
810
|
-
for (const moduleBinding of
|
|
1010
|
+
async runLifecycle(method, reverse = false, modules = this.modules) {
|
|
1011
|
+
const orderedModules = reverse ? modules.toReversed() : modules;
|
|
1012
|
+
for (const moduleBinding of orderedModules) {
|
|
811
1013
|
const lifecycle = moduleBinding.instance;
|
|
812
1014
|
await this.runWithAppInjectContext(() => lifecycle[method]?.());
|
|
813
1015
|
}
|
|
814
1016
|
}
|
|
1017
|
+
startEffects(modules = this.modules) {
|
|
1018
|
+
for (const moduleBinding of modules) for (const property of moduleBinding.metadata.effects) this.startEffect(moduleBinding, property);
|
|
1019
|
+
}
|
|
1020
|
+
startEffect(moduleBinding, property) {
|
|
1021
|
+
const method = getMethod(moduleBinding.instance, property);
|
|
1022
|
+
const tracker = createReactiveTracker();
|
|
1023
|
+
let disposed = false;
|
|
1024
|
+
const run = () => {
|
|
1025
|
+
if (disposed) return;
|
|
1026
|
+
try {
|
|
1027
|
+
tracker.track(() => this.runEffect(moduleBinding, property, method));
|
|
1028
|
+
} catch (error) {
|
|
1029
|
+
this.emitError(error, { phase: "effect" });
|
|
1030
|
+
throw error;
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
const unsubscribe = tracker.subscribe(() => {
|
|
1034
|
+
try {
|
|
1035
|
+
run();
|
|
1036
|
+
} catch {}
|
|
1037
|
+
});
|
|
1038
|
+
run();
|
|
1039
|
+
this.effectDisposers.push(() => {
|
|
1040
|
+
disposed = true;
|
|
1041
|
+
unsubscribe();
|
|
1042
|
+
tracker.dispose();
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
runEffect(moduleBinding, property, method) {
|
|
1046
|
+
const result = this.runWithAppInjectContext(() => method.call(moduleBinding.instance));
|
|
1047
|
+
if (!isPromiseLike(result)) return;
|
|
1048
|
+
const pending = Promise.resolve(result).then(() => void 0).catch((error) => {
|
|
1049
|
+
this.emitError(error, { phase: `effect:${moduleBinding.name}.${String(property)}` });
|
|
1050
|
+
throw error;
|
|
1051
|
+
}).finally(() => {
|
|
1052
|
+
this.pendingEffects.delete(pending);
|
|
1053
|
+
});
|
|
1054
|
+
this.pendingEffects.add(pending);
|
|
1055
|
+
pending.catch(() => void 0);
|
|
1056
|
+
}
|
|
1057
|
+
stopEffects() {
|
|
1058
|
+
for (const dispose of this.effectDisposers.splice(0).toReversed()) dispose();
|
|
1059
|
+
}
|
|
1060
|
+
async flushEffects() {
|
|
1061
|
+
await this.initPromise;
|
|
1062
|
+
await this.waitForPendingEffects();
|
|
1063
|
+
}
|
|
1064
|
+
async waitForPendingEffects() {
|
|
1065
|
+
while (this.pendingEffects.size > 0) await Promise.all(this.pendingEffects);
|
|
1066
|
+
}
|
|
815
1067
|
emitActionStart(event) {
|
|
816
1068
|
for (const plugin of this.plugins) plugin.onActionStart?.(event);
|
|
817
1069
|
}
|
|
@@ -853,6 +1105,27 @@ var RuntimeApp = class {
|
|
|
853
1105
|
patches
|
|
854
1106
|
});
|
|
855
1107
|
}
|
|
1108
|
+
assertNewModules(modules) {
|
|
1109
|
+
for (const moduleBinding of modules) {
|
|
1110
|
+
if (this.moduleByToken.has(moduleBinding.token)) throw new DuplicateProviderError(tokenName(moduleBinding.token));
|
|
1111
|
+
if (this.moduleByName.has(moduleBinding.name)) throw new DuplicateProviderError(moduleBinding.name);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
installModuleState(modules) {
|
|
1115
|
+
if (modules.length === 0) return;
|
|
1116
|
+
const rootState = createRootState(modules);
|
|
1117
|
+
this.store.setState({
|
|
1118
|
+
...this.store.getPureState(),
|
|
1119
|
+
...rootState
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
registerModules(modules) {
|
|
1123
|
+
for (const moduleBinding of modules) {
|
|
1124
|
+
this.modules.push(moduleBinding);
|
|
1125
|
+
this.moduleByToken.set(moduleBinding.token, moduleBinding);
|
|
1126
|
+
this.moduleByName.set(moduleBinding.name, moduleBinding);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
856
1129
|
};
|
|
857
1130
|
function normalizeAppProvider(provider) {
|
|
858
1131
|
if (typeof provider === "function") {
|
|
@@ -900,7 +1173,7 @@ function mergeModuleClassProviderOptions(provider, metadata) {
|
|
|
900
1173
|
..."scope" in provider || metadata.scope === void 0 ? {} : { scope: metadata.scope }
|
|
901
1174
|
};
|
|
902
1175
|
}
|
|
903
|
-
function instantiateModules(container, moduleTokens) {
|
|
1176
|
+
function instantiateModules(container, moduleTokens, reactiveSlice = true) {
|
|
904
1177
|
const modules = [];
|
|
905
1178
|
for (const moduleToken of moduleTokens) {
|
|
906
1179
|
const instance = container.get(moduleToken);
|
|
@@ -911,16 +1184,36 @@ function instantiateModules(container, moduleTokens) {
|
|
|
911
1184
|
modules.push({
|
|
912
1185
|
actionDepth: 0,
|
|
913
1186
|
activeDraft: void 0,
|
|
1187
|
+
computedAccessors: /* @__PURE__ */ new Map(),
|
|
914
1188
|
instance,
|
|
915
1189
|
metadata,
|
|
916
1190
|
name,
|
|
917
1191
|
originalActions: /* @__PURE__ */ new Map(),
|
|
918
1192
|
originalComputed: /* @__PURE__ */ new Map(),
|
|
1193
|
+
reactiveSlice,
|
|
919
1194
|
token: moduleToken
|
|
920
1195
|
});
|
|
921
1196
|
}
|
|
922
1197
|
return modules;
|
|
923
1198
|
}
|
|
1199
|
+
function toModuleCreatedEvent(moduleBinding) {
|
|
1200
|
+
return {
|
|
1201
|
+
instance: moduleBinding.instance,
|
|
1202
|
+
name: moduleBinding.name,
|
|
1203
|
+
token: moduleBinding.token
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
function instantiateEagerProviders(container) {
|
|
1207
|
+
const internalContainer = container;
|
|
1208
|
+
for (const [token, records] of internalContainer.records) {
|
|
1209
|
+
if (!records.some((record) => record.eager)) continue;
|
|
1210
|
+
if (records.some((record) => record.multi)) {
|
|
1211
|
+
container.getAll(token);
|
|
1212
|
+
continue;
|
|
1213
|
+
}
|
|
1214
|
+
container.get(token);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
924
1217
|
function createRootState(modules) {
|
|
925
1218
|
const rootState = {};
|
|
926
1219
|
for (const moduleBinding of modules) {
|
|
@@ -944,6 +1237,12 @@ function getGetter(instance, property) {
|
|
|
944
1237
|
if (descriptor?.get === void 0) throw new CosystemError(`${String(property)} is not a getter.`);
|
|
945
1238
|
return descriptor.get;
|
|
946
1239
|
}
|
|
1240
|
+
function getRuntimeModuleMetadata(module) {
|
|
1241
|
+
return module[runtimeModuleMetadataKey];
|
|
1242
|
+
}
|
|
1243
|
+
function isTokenObject(value) {
|
|
1244
|
+
return "id" in value && typeof value.id === "symbol";
|
|
1245
|
+
}
|
|
947
1246
|
function getDescriptor(instance, property) {
|
|
948
1247
|
let current = instance;
|
|
949
1248
|
while (current !== null) {
|
|
@@ -955,6 +1254,9 @@ function getDescriptor(instance, property) {
|
|
|
955
1254
|
function isApp(value) {
|
|
956
1255
|
return typeof value === "object" && value !== null && "get" in value && "start" in value && "dispose" in value;
|
|
957
1256
|
}
|
|
1257
|
+
function isPromiseLike(value) {
|
|
1258
|
+
return (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof value.then === "function";
|
|
1259
|
+
}
|
|
958
1260
|
function getAppContainer(app) {
|
|
959
1261
|
const container = appContainerMap.get(app);
|
|
960
1262
|
if (container === void 0) throw new CosystemError("Parent app was not created by CoSystem.");
|
|
@@ -989,6 +1291,13 @@ function computed(_value, context) {
|
|
|
989
1291
|
addModuleComputed(this.constructor, context.name);
|
|
990
1292
|
});
|
|
991
1293
|
}
|
|
1294
|
+
function effect(_value, context) {
|
|
1295
|
+
if (context.kind !== "method") throw new TypeError("@effect only supports method decorators.");
|
|
1296
|
+
ensureContextModuleMetadata(context)?.effects.add(context.name);
|
|
1297
|
+
context.addInitializer(function initializeEffect() {
|
|
1298
|
+
addModuleEffect(this.constructor, context.name);
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
992
1301
|
//#endregion
|
|
993
1302
|
//#region src/loggerPlugin.ts
|
|
994
1303
|
function createLoggerPlugin(options = {}) {
|
|
@@ -1032,9 +1341,13 @@ function testApp(options = {}) {
|
|
|
1032
1341
|
if (autoStart === true) return app.start().then(() => app);
|
|
1033
1342
|
return app;
|
|
1034
1343
|
}
|
|
1344
|
+
function defaultFlushEffects() {
|
|
1345
|
+
return Promise.resolve();
|
|
1346
|
+
}
|
|
1035
1347
|
function createTestInspector() {
|
|
1036
1348
|
const actions = [];
|
|
1037
1349
|
const patches = [];
|
|
1350
|
+
let flushEffects = defaultFlushEffects;
|
|
1038
1351
|
let lastState;
|
|
1039
1352
|
return {
|
|
1040
1353
|
clearActions() {
|
|
@@ -1044,7 +1357,7 @@ function createTestInspector() {
|
|
|
1044
1357
|
patches.length = 0;
|
|
1045
1358
|
},
|
|
1046
1359
|
flushEffects() {
|
|
1047
|
-
return
|
|
1360
|
+
return flushEffects();
|
|
1048
1361
|
},
|
|
1049
1362
|
getActions() {
|
|
1050
1363
|
return actions;
|
|
@@ -1063,17 +1376,25 @@ function createTestInspector() {
|
|
|
1063
1376
|
},
|
|
1064
1377
|
recordState(state) {
|
|
1065
1378
|
lastState = state;
|
|
1379
|
+
},
|
|
1380
|
+
setFlushEffects(callback) {
|
|
1381
|
+
flushEffects = callback;
|
|
1066
1382
|
}
|
|
1067
1383
|
};
|
|
1068
1384
|
}
|
|
1069
1385
|
//#endregion
|
|
1070
1386
|
//#region src/worker.ts
|
|
1071
1387
|
function createWorkerApp(options) {
|
|
1072
|
-
const { transport, ...appOptions } = options;
|
|
1388
|
+
const { stateSections, sync = "snapshot", transport, ...appOptions } = options;
|
|
1389
|
+
let stateSyncVersion = 0;
|
|
1390
|
+
let publishPatches = false;
|
|
1073
1391
|
const patchPlugin = {
|
|
1074
1392
|
name: "cosystem:worker-patches",
|
|
1075
1393
|
onPatch(event) {
|
|
1076
|
-
|
|
1394
|
+
if (publishPatches) {
|
|
1395
|
+
const version = stateSections === void 0 ? app.state.version : stateSyncVersion + 1;
|
|
1396
|
+
if (publishState(app, transport, event.patches, sync, stateSections, version)) stateSyncVersion = version;
|
|
1397
|
+
}
|
|
1077
1398
|
}
|
|
1078
1399
|
};
|
|
1079
1400
|
const app = createApp({
|
|
@@ -1084,45 +1405,45 @@ function createWorkerApp(options) {
|
|
|
1084
1405
|
},
|
|
1085
1406
|
plugins: [...appOptions.plugins ?? [], patchPlugin]
|
|
1086
1407
|
});
|
|
1408
|
+
const ready = app.start().then(() => {
|
|
1409
|
+
publishPatches = true;
|
|
1410
|
+
transport.post({ type: "ready" });
|
|
1411
|
+
const version = stateSections === void 0 ? app.state.version : stateSyncVersion;
|
|
1412
|
+
if (publishState(app, transport, [], "snapshot", stateSections, version)) stateSyncVersion = version;
|
|
1413
|
+
});
|
|
1087
1414
|
const unsubscribeTransport = transport.subscribe((message) => {
|
|
1088
1415
|
if (message.type !== "call") return;
|
|
1089
|
-
handleCall(app, transport, message);
|
|
1416
|
+
handleCall(app, transport, message, ready);
|
|
1090
1417
|
});
|
|
1091
|
-
transport.post({ type: "ready" });
|
|
1092
|
-
publishState(app, transport);
|
|
1093
1418
|
return {
|
|
1094
1419
|
app,
|
|
1420
|
+
ready,
|
|
1095
1421
|
async dispose() {
|
|
1096
1422
|
unsubscribeTransport();
|
|
1423
|
+
await ready.catch(() => void 0);
|
|
1097
1424
|
await app.dispose();
|
|
1098
1425
|
}
|
|
1099
1426
|
};
|
|
1100
1427
|
}
|
|
1101
1428
|
function createWorkerClient(options) {
|
|
1102
|
-
const { transport } = options;
|
|
1429
|
+
const { onConflict, transport } = options;
|
|
1103
1430
|
const listeners = /* @__PURE__ */ new Set();
|
|
1431
|
+
const selectorWatchers = /* @__PURE__ */ new Set();
|
|
1104
1432
|
const pending = /* @__PURE__ */ new Map();
|
|
1105
1433
|
const state = { version: 0 };
|
|
1106
1434
|
let nextId = 1;
|
|
1107
1435
|
let snapshot;
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
}
|
|
1115
|
-
if (message.type !== "result") return;
|
|
1116
|
-
const entry = pending.get(message.id);
|
|
1117
|
-
if (entry === void 0) return;
|
|
1118
|
-
pending.delete(message.id);
|
|
1119
|
-
if (message.error !== void 0) {
|
|
1120
|
-
entry.reject(createRemoteError(message.error));
|
|
1121
|
-
return;
|
|
1122
|
-
}
|
|
1123
|
-
entry.resolve(message.value);
|
|
1436
|
+
let readySettled = false;
|
|
1437
|
+
let resolveReady;
|
|
1438
|
+
let rejectReady;
|
|
1439
|
+
const ready = new Promise((resolve, reject) => {
|
|
1440
|
+
resolveReady = resolve;
|
|
1441
|
+
rejectReady = reject;
|
|
1124
1442
|
});
|
|
1443
|
+
ready.catch(() => void 0);
|
|
1444
|
+
let unsubscribe = noop;
|
|
1125
1445
|
const client = {
|
|
1446
|
+
ready,
|
|
1126
1447
|
state,
|
|
1127
1448
|
call(module, method, ...args) {
|
|
1128
1449
|
const id = nextId;
|
|
@@ -1143,9 +1464,14 @@ function createWorkerClient(options) {
|
|
|
1143
1464
|
},
|
|
1144
1465
|
dispose() {
|
|
1145
1466
|
unsubscribe();
|
|
1467
|
+
if (!readySettled) {
|
|
1468
|
+
readySettled = true;
|
|
1469
|
+
rejectReady(new CosystemError("Worker client disposed before initial state."));
|
|
1470
|
+
}
|
|
1146
1471
|
for (const entry of pending.values()) entry.reject(new CosystemError("Worker client disposed before response."));
|
|
1147
1472
|
pending.clear();
|
|
1148
1473
|
listeners.clear();
|
|
1474
|
+
selectorWatchers.clear();
|
|
1149
1475
|
},
|
|
1150
1476
|
getState() {
|
|
1151
1477
|
return snapshot;
|
|
@@ -1156,22 +1482,256 @@ function createWorkerClient(options) {
|
|
|
1156
1482
|
return (...args) => client.call(name, property, ...args);
|
|
1157
1483
|
} });
|
|
1158
1484
|
},
|
|
1485
|
+
select(selector) {
|
|
1486
|
+
if (snapshot === void 0) throw new CosystemError("Worker client state is not ready.");
|
|
1487
|
+
return selector(snapshot, client);
|
|
1488
|
+
},
|
|
1159
1489
|
subscribe(listener) {
|
|
1160
1490
|
listeners.add(listener);
|
|
1161
1491
|
return () => {
|
|
1162
1492
|
listeners.delete(listener);
|
|
1163
1493
|
};
|
|
1494
|
+
},
|
|
1495
|
+
watch(selector, listener, watchOptions = {}) {
|
|
1496
|
+
const watcher = {
|
|
1497
|
+
equals: watchOptions.equals ?? Object.is,
|
|
1498
|
+
immediate: watchOptions.immediate ?? false,
|
|
1499
|
+
initialized: false,
|
|
1500
|
+
listener,
|
|
1501
|
+
previous: void 0,
|
|
1502
|
+
selector
|
|
1503
|
+
};
|
|
1504
|
+
if (snapshot !== void 0) {
|
|
1505
|
+
const value = selector(snapshot, client);
|
|
1506
|
+
watcher.initialized = true;
|
|
1507
|
+
watcher.previous = value;
|
|
1508
|
+
if (watcher.immediate) listener(value, value);
|
|
1509
|
+
}
|
|
1510
|
+
selectorWatchers.add(watcher);
|
|
1511
|
+
return () => {
|
|
1512
|
+
selectorWatchers.delete(watcher);
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
};
|
|
1516
|
+
const publishSelectorWatchers = () => {
|
|
1517
|
+
if (snapshot === void 0) return;
|
|
1518
|
+
for (const watcher of selectorWatchers) {
|
|
1519
|
+
const value = watcher.selector(snapshot, client);
|
|
1520
|
+
if (!watcher.initialized) {
|
|
1521
|
+
watcher.initialized = true;
|
|
1522
|
+
watcher.previous = value;
|
|
1523
|
+
if (watcher.immediate) watcher.listener(value, value);
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
const previous = watcher.previous;
|
|
1527
|
+
if (watcher.equals(value, previous)) continue;
|
|
1528
|
+
watcher.previous = value;
|
|
1529
|
+
watcher.listener(value, previous);
|
|
1164
1530
|
}
|
|
1165
1531
|
};
|
|
1532
|
+
unsubscribe = transport.subscribe((message) => {
|
|
1533
|
+
if (message.type === "state") {
|
|
1534
|
+
if (readySettled && message.version <= state.version) {
|
|
1535
|
+
reportWorkerConflict(onConflict, {
|
|
1536
|
+
currentVersion: state.version,
|
|
1537
|
+
incomingVersion: message.version,
|
|
1538
|
+
message,
|
|
1539
|
+
reason: "stale-message"
|
|
1540
|
+
});
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
const isPatchOnly = message.state === void 0 && message.sync === "patch";
|
|
1544
|
+
if (isPatchOnly && snapshot === void 0) {
|
|
1545
|
+
reportWorkerConflict(onConflict, {
|
|
1546
|
+
currentVersion: state.version,
|
|
1547
|
+
incomingVersion: message.version,
|
|
1548
|
+
message,
|
|
1549
|
+
reason: "missing-snapshot"
|
|
1550
|
+
});
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
if (isPatchOnly && readySettled && message.version !== state.version + 1) {
|
|
1554
|
+
reportWorkerConflict(onConflict, {
|
|
1555
|
+
currentVersion: state.version,
|
|
1556
|
+
incomingVersion: message.version,
|
|
1557
|
+
message,
|
|
1558
|
+
reason: "version-gap"
|
|
1559
|
+
});
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
try {
|
|
1563
|
+
snapshot = isPatchOnly ? applyWorkerPatches(snapshot, message.patches ?? []) : message.state;
|
|
1564
|
+
} catch (error) {
|
|
1565
|
+
reportWorkerConflict(onConflict, {
|
|
1566
|
+
currentVersion: state.version,
|
|
1567
|
+
error,
|
|
1568
|
+
incomingVersion: message.version,
|
|
1569
|
+
message,
|
|
1570
|
+
reason: "patch-apply-failed"
|
|
1571
|
+
});
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
state.version = message.version;
|
|
1575
|
+
if (!readySettled) {
|
|
1576
|
+
readySettled = true;
|
|
1577
|
+
resolveReady();
|
|
1578
|
+
}
|
|
1579
|
+
for (const listener of listeners) listener(message);
|
|
1580
|
+
publishSelectorWatchers();
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
if (message.type !== "result") return;
|
|
1584
|
+
const entry = pending.get(message.id);
|
|
1585
|
+
if (entry === void 0) return;
|
|
1586
|
+
pending.delete(message.id);
|
|
1587
|
+
if (message.error !== void 0) {
|
|
1588
|
+
entry.reject(createRemoteError(message.error));
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
entry.resolve(message.value);
|
|
1592
|
+
});
|
|
1166
1593
|
return client;
|
|
1167
1594
|
}
|
|
1595
|
+
function reportWorkerConflict(onConflict, event) {
|
|
1596
|
+
onConflict?.(event);
|
|
1597
|
+
}
|
|
1168
1598
|
function createMemoryWorkerTransportPair() {
|
|
1169
1599
|
const leftListeners = /* @__PURE__ */ new Set();
|
|
1170
1600
|
const rightListeners = /* @__PURE__ */ new Set();
|
|
1171
1601
|
return [createMemoryWorkerTransport(leftListeners, rightListeners), createMemoryWorkerTransport(rightListeners, leftListeners)];
|
|
1172
1602
|
}
|
|
1173
|
-
|
|
1603
|
+
function createPostMessageWorkerTransport(endpoint, options = {}) {
|
|
1604
|
+
const source = options.source ?? endpoint;
|
|
1605
|
+
const target = options.target ?? endpoint;
|
|
1606
|
+
return {
|
|
1607
|
+
post(message) {
|
|
1608
|
+
try {
|
|
1609
|
+
target.postMessage(message);
|
|
1610
|
+
} catch (error) {
|
|
1611
|
+
options.onError?.(error, message);
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
subscribe(listener) {
|
|
1615
|
+
const handleMessage = (event) => {
|
|
1616
|
+
if (!isWorkerMessage(event.data)) return;
|
|
1617
|
+
listener(event.data);
|
|
1618
|
+
};
|
|
1619
|
+
source.addEventListener("message", handleMessage);
|
|
1620
|
+
return () => {
|
|
1621
|
+
source.removeEventListener("message", handleMessage);
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
}
|
|
1626
|
+
function createBroadcastWorkerTransport(broadcast, options = {}) {
|
|
1627
|
+
const channel = options.channel ?? defaultBroadcastWorkerChannel;
|
|
1628
|
+
const peerId = options.peerId ?? createWorkerPeerId();
|
|
1629
|
+
const callRoutes = /* @__PURE__ */ new Map();
|
|
1630
|
+
let nextRoutedCallId = 1;
|
|
1631
|
+
return {
|
|
1632
|
+
post(message) {
|
|
1633
|
+
try {
|
|
1634
|
+
const routed = routeBroadcastWorkerMessage(message, callRoutes);
|
|
1635
|
+
const target = routed.target ?? getBroadcastWorkerTarget(message, options);
|
|
1636
|
+
const envelope = {
|
|
1637
|
+
channel,
|
|
1638
|
+
message: routed.message,
|
|
1639
|
+
source: peerId,
|
|
1640
|
+
type: "cosystem:worker",
|
|
1641
|
+
...target === void 0 ? {} : { target }
|
|
1642
|
+
};
|
|
1643
|
+
broadcast.postMessage(envelope);
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
options.onError?.(error, message);
|
|
1646
|
+
}
|
|
1647
|
+
},
|
|
1648
|
+
subscribe(listener) {
|
|
1649
|
+
const handleMessage = (event) => {
|
|
1650
|
+
const envelope = event.data;
|
|
1651
|
+
if (!isBroadcastWorkerMessageEnvelope(envelope) || envelope.channel !== channel || envelope.source === peerId || envelope.target !== void 0 && envelope.target !== peerId) return;
|
|
1652
|
+
if (envelope.message.type === "call") {
|
|
1653
|
+
const routedCallId = nextRoutedCallId;
|
|
1654
|
+
nextRoutedCallId += 1;
|
|
1655
|
+
callRoutes.set(routedCallId, {
|
|
1656
|
+
id: envelope.message.id,
|
|
1657
|
+
source: envelope.source
|
|
1658
|
+
});
|
|
1659
|
+
listener({
|
|
1660
|
+
...envelope.message,
|
|
1661
|
+
id: routedCallId
|
|
1662
|
+
});
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
listener(envelope.message);
|
|
1666
|
+
};
|
|
1667
|
+
broadcast.addEventListener("message", handleMessage);
|
|
1668
|
+
return () => {
|
|
1669
|
+
broadcast.removeEventListener("message", handleMessage);
|
|
1670
|
+
};
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
}
|
|
1674
|
+
function createMemoryBroadcastChannel(name = defaultBroadcastWorkerChannel) {
|
|
1675
|
+
return new MemoryBroadcastChannel(name);
|
|
1676
|
+
}
|
|
1677
|
+
function createDataTransportWorkerTransport(dataTransport, options = {}) {
|
|
1678
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1679
|
+
const disposers = [];
|
|
1680
|
+
let listening = false;
|
|
1681
|
+
const start = () => {
|
|
1682
|
+
if (listening) return;
|
|
1683
|
+
listening = true;
|
|
1684
|
+
for (const type of workerMessageTypes) {
|
|
1685
|
+
const dispose = dataTransport.listen(type, (message) => {
|
|
1686
|
+
if (!isWorkerMessage(message)) return;
|
|
1687
|
+
for (const listener of listeners) listener(message);
|
|
1688
|
+
});
|
|
1689
|
+
if (typeof dispose === "function") disposers.push(dispose);
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
const stop = () => {
|
|
1693
|
+
if (!listening) return;
|
|
1694
|
+
listening = false;
|
|
1695
|
+
for (const dispose of disposers.splice(0)) dispose();
|
|
1696
|
+
};
|
|
1697
|
+
return {
|
|
1698
|
+
post(message) {
|
|
1699
|
+
dataTransport.emit({
|
|
1700
|
+
name: message.type,
|
|
1701
|
+
respond: false
|
|
1702
|
+
}, message).catch((error) => {
|
|
1703
|
+
options.onError?.(error, message);
|
|
1704
|
+
});
|
|
1705
|
+
},
|
|
1706
|
+
subscribe(listener) {
|
|
1707
|
+
start();
|
|
1708
|
+
listeners.add(listener);
|
|
1709
|
+
return () => {
|
|
1710
|
+
listeners.delete(listener);
|
|
1711
|
+
if (listeners.size === 0) stop();
|
|
1712
|
+
};
|
|
1713
|
+
}
|
|
1714
|
+
};
|
|
1715
|
+
}
|
|
1716
|
+
function getBroadcastWorkerTarget(message, options) {
|
|
1717
|
+
return message.type === "call" ? options.targetPeerId : void 0;
|
|
1718
|
+
}
|
|
1719
|
+
function routeBroadcastWorkerMessage(message, callRoutes) {
|
|
1720
|
+
if (message.type !== "result") return { message };
|
|
1721
|
+
const route = callRoutes.get(message.id);
|
|
1722
|
+
if (route === void 0) return { message };
|
|
1723
|
+
callRoutes.delete(message.id);
|
|
1724
|
+
return {
|
|
1725
|
+
message: {
|
|
1726
|
+
...message,
|
|
1727
|
+
id: route.id
|
|
1728
|
+
},
|
|
1729
|
+
target: route.source
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1732
|
+
async function handleCall(app, transport, message, ready) {
|
|
1174
1733
|
try {
|
|
1734
|
+
await ready;
|
|
1175
1735
|
const module = app.getModuleByName(message.module);
|
|
1176
1736
|
const method = module[message.method];
|
|
1177
1737
|
if (typeof method !== "function") throw new CosystemError(`${message.module}.${message.method} is not callable.`);
|
|
@@ -1189,15 +1749,111 @@ async function handleCall(app, transport, message) {
|
|
|
1189
1749
|
});
|
|
1190
1750
|
}
|
|
1191
1751
|
}
|
|
1192
|
-
function publishState(app, transport, patches = []) {
|
|
1752
|
+
function publishState(app, transport, patches = [], mode = "snapshot", sections, version = app.state.version) {
|
|
1753
|
+
const filteredPatches = filterWorkerPatches(patches, sections);
|
|
1754
|
+
const isPatch = filteredPatches.length > 0;
|
|
1755
|
+
if (patches.length > 0 && filteredPatches.length === 0) return false;
|
|
1756
|
+
const state = filterWorkerState(app.store.getPureState(), sections);
|
|
1193
1757
|
const message = {
|
|
1194
|
-
|
|
1195
|
-
|
|
1758
|
+
...isPatch && mode === "patch" ? {} : { state },
|
|
1759
|
+
...sections === void 0 ? {} : { sections },
|
|
1760
|
+
sync: isPatch ? "patch" : "snapshot",
|
|
1196
1761
|
type: "state",
|
|
1197
|
-
version
|
|
1198
|
-
...
|
|
1762
|
+
version,
|
|
1763
|
+
...isPatch ? { patches: filteredPatches } : {}
|
|
1199
1764
|
};
|
|
1200
1765
|
transport.post(message);
|
|
1766
|
+
return true;
|
|
1767
|
+
}
|
|
1768
|
+
function filterWorkerState(state, sections) {
|
|
1769
|
+
if (sections === void 0 || !isRecord(state)) return state;
|
|
1770
|
+
const filtered = {};
|
|
1771
|
+
for (const section of sections) if (section in state) filtered[section] = state[section];
|
|
1772
|
+
return filtered;
|
|
1773
|
+
}
|
|
1774
|
+
function filterWorkerPatches(patches, sections) {
|
|
1775
|
+
if (sections === void 0) return patches;
|
|
1776
|
+
const sectionSet = new Set(sections);
|
|
1777
|
+
return patches.filter((patch) => {
|
|
1778
|
+
if (!isWorkerPatch(patch)) throw new CosystemError("Worker state patch is invalid.");
|
|
1779
|
+
const section = getWorkerPatchSection(patch);
|
|
1780
|
+
return section !== void 0 && sectionSet.has(String(section));
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
function getWorkerPatchSection(patch) {
|
|
1784
|
+
return normalizePatchPath(patch.path)[0];
|
|
1785
|
+
}
|
|
1786
|
+
function applyWorkerPatches(state, patches) {
|
|
1787
|
+
let next = state;
|
|
1788
|
+
for (const patch of patches) next = applyWorkerPatch(next, patch);
|
|
1789
|
+
return next;
|
|
1790
|
+
}
|
|
1791
|
+
function applyWorkerPatch(state, patch) {
|
|
1792
|
+
if (!isWorkerPatch(patch)) throw new CosystemError("Worker state patch is invalid.");
|
|
1793
|
+
const path = normalizePatchPath(patch.path);
|
|
1794
|
+
if (path.length === 0) {
|
|
1795
|
+
if (patch.op === "remove") return;
|
|
1796
|
+
return patch.value;
|
|
1797
|
+
}
|
|
1798
|
+
return applyPatchAtPath(state, path, patch);
|
|
1799
|
+
}
|
|
1800
|
+
function applyPatchAtPath(state, path, patch) {
|
|
1801
|
+
const [segment, ...rest] = path;
|
|
1802
|
+
if (segment === void 0) throw new CosystemError("Worker state patch path is invalid.");
|
|
1803
|
+
const container = clonePatchContainer(state, segment);
|
|
1804
|
+
if (rest.length === 0) {
|
|
1805
|
+
if (patch.op === "remove") {
|
|
1806
|
+
removePatchValue(container, segment);
|
|
1807
|
+
return container;
|
|
1808
|
+
}
|
|
1809
|
+
setPatchValue(container, segment, patch.value);
|
|
1810
|
+
return container;
|
|
1811
|
+
}
|
|
1812
|
+
setPatchValue(container, segment, applyPatchAtPath(getPatchValue(container, segment), rest, patch));
|
|
1813
|
+
return container;
|
|
1814
|
+
}
|
|
1815
|
+
function clonePatchContainer(state, nextSegment) {
|
|
1816
|
+
if (Array.isArray(state)) return [...state];
|
|
1817
|
+
if (isRecord(state)) return { ...state };
|
|
1818
|
+
return typeof nextSegment === "number" ? [] : {};
|
|
1819
|
+
}
|
|
1820
|
+
function getPatchValue(container, segment) {
|
|
1821
|
+
if (Array.isArray(container)) return container[toArrayIndex(segment)];
|
|
1822
|
+
return container[String(segment)];
|
|
1823
|
+
}
|
|
1824
|
+
function setPatchValue(container, segment, value) {
|
|
1825
|
+
if (Array.isArray(container)) {
|
|
1826
|
+
container[toArrayIndex(segment)] = value;
|
|
1827
|
+
return;
|
|
1828
|
+
}
|
|
1829
|
+
container[String(segment)] = value;
|
|
1830
|
+
}
|
|
1831
|
+
function removePatchValue(container, segment) {
|
|
1832
|
+
if (Array.isArray(container)) {
|
|
1833
|
+
container.splice(toArrayIndex(segment), 1);
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
delete container[String(segment)];
|
|
1837
|
+
}
|
|
1838
|
+
function toArrayIndex(segment) {
|
|
1839
|
+
if (typeof segment === "number") return segment;
|
|
1840
|
+
return Number(segment);
|
|
1841
|
+
}
|
|
1842
|
+
function normalizePatchPath(path) {
|
|
1843
|
+
if (Array.isArray(path)) return path.map((segment) => normalizePatchPathSegment(segment));
|
|
1844
|
+
if (typeof path === "string") {
|
|
1845
|
+
if (path === "" || path === "/") return [];
|
|
1846
|
+
return path.split("/").slice(1).map((segment) => normalizePatchPathSegment(segment.replaceAll("~1", "/").replaceAll("~0", "~")));
|
|
1847
|
+
}
|
|
1848
|
+
throw new CosystemError("Worker state patch path is invalid.");
|
|
1849
|
+
}
|
|
1850
|
+
function normalizePatchPathSegment(segment) {
|
|
1851
|
+
if (typeof segment === "number" || typeof segment === "string") return segment;
|
|
1852
|
+
throw new CosystemError("Worker state patch path segment is invalid.");
|
|
1853
|
+
}
|
|
1854
|
+
function isWorkerPatch(value) {
|
|
1855
|
+
if (!isRecord(value)) return false;
|
|
1856
|
+
return (value.op === "add" || value.op === "replace" || value.op === "remove") && (Array.isArray(value.path) || typeof value.path === "string");
|
|
1201
1857
|
}
|
|
1202
1858
|
function createMemoryWorkerTransport(inbox, outbox) {
|
|
1203
1859
|
return {
|
|
@@ -1212,6 +1868,72 @@ function createMemoryWorkerTransport(inbox, outbox) {
|
|
|
1212
1868
|
}
|
|
1213
1869
|
};
|
|
1214
1870
|
}
|
|
1871
|
+
const workerMessageTypes = [
|
|
1872
|
+
"call",
|
|
1873
|
+
"result",
|
|
1874
|
+
"state",
|
|
1875
|
+
"ready"
|
|
1876
|
+
];
|
|
1877
|
+
const defaultBroadcastWorkerChannel = "cosystem:worker";
|
|
1878
|
+
const memoryBroadcastChannels = /* @__PURE__ */ new Map();
|
|
1879
|
+
let nextWorkerPeerId = 1;
|
|
1880
|
+
var MemoryBroadcastChannel = class {
|
|
1881
|
+
name;
|
|
1882
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
1883
|
+
#closed = false;
|
|
1884
|
+
constructor(name) {
|
|
1885
|
+
this.name = name;
|
|
1886
|
+
let channels = memoryBroadcastChannels.get(name);
|
|
1887
|
+
if (channels === void 0) {
|
|
1888
|
+
channels = /* @__PURE__ */ new Set();
|
|
1889
|
+
memoryBroadcastChannels.set(name, channels);
|
|
1890
|
+
}
|
|
1891
|
+
channels.add(this);
|
|
1892
|
+
}
|
|
1893
|
+
postMessage(message) {
|
|
1894
|
+
if (this.#closed) return;
|
|
1895
|
+
const channels = memoryBroadcastChannels.get(this.name);
|
|
1896
|
+
if (channels === void 0) return;
|
|
1897
|
+
for (const channel of channels) {
|
|
1898
|
+
if (channel === this || channel.#closed) continue;
|
|
1899
|
+
channel.dispatch({ data: message });
|
|
1900
|
+
}
|
|
1901
|
+
}
|
|
1902
|
+
addEventListener(_type, listener) {
|
|
1903
|
+
if (!this.#closed) this.#listeners.add(listener);
|
|
1904
|
+
}
|
|
1905
|
+
removeEventListener(_type, listener) {
|
|
1906
|
+
this.#listeners.delete(listener);
|
|
1907
|
+
}
|
|
1908
|
+
close() {
|
|
1909
|
+
if (this.#closed) return;
|
|
1910
|
+
this.#closed = true;
|
|
1911
|
+
this.#listeners.clear();
|
|
1912
|
+
const channels = memoryBroadcastChannels.get(this.name);
|
|
1913
|
+
if (channels === void 0) return;
|
|
1914
|
+
channels.delete(this);
|
|
1915
|
+
if (channels.size === 0) memoryBroadcastChannels.delete(this.name);
|
|
1916
|
+
}
|
|
1917
|
+
dispatch(event) {
|
|
1918
|
+
for (const listener of this.#listeners) listener(event);
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
function createWorkerPeerId() {
|
|
1922
|
+
const id = nextWorkerPeerId;
|
|
1923
|
+
nextWorkerPeerId += 1;
|
|
1924
|
+
return `peer:${id}`;
|
|
1925
|
+
}
|
|
1926
|
+
function isWorkerMessage(message) {
|
|
1927
|
+
if (typeof message !== "object" || message === null || !("type" in message)) return false;
|
|
1928
|
+
return workerMessageTypes.includes(message.type);
|
|
1929
|
+
}
|
|
1930
|
+
function isBroadcastWorkerMessageEnvelope(message) {
|
|
1931
|
+
if (!isRecord(message)) return false;
|
|
1932
|
+
return message.type === "cosystem:worker" && typeof message.channel === "string" && typeof message.source === "string" && (message.target === void 0 || typeof message.target === "string") && isWorkerMessage(message.message);
|
|
1933
|
+
}
|
|
1934
|
+
function isRecord(value) {
|
|
1935
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1936
|
+
}
|
|
1215
1937
|
function serializeError(error) {
|
|
1216
1938
|
if (error instanceof Error) return {
|
|
1217
1939
|
message: error.message,
|
|
@@ -1229,7 +1951,8 @@ function createRemoteError(error) {
|
|
|
1229
1951
|
if (error.stack !== void 0) remoteError.stack = error.stack;
|
|
1230
1952
|
return remoteError;
|
|
1231
1953
|
}
|
|
1954
|
+
function noop() {}
|
|
1232
1955
|
//#endregion
|
|
1233
|
-
export { AmbiguousProviderError, AsyncProviderInSyncResolutionError, CircularDependencyError, CosystemError, DuplicateProviderError, FrozenContainerError, InjectContextError, LifetimeLeakError, MissingProviderError, action, computed, createApp, createContainer, createLoggerPlugin, createMemoryWorkerTransportPair, createWorkerApp, createWorkerClient, defineModule, getModuleMetadata, inject, module, provide, state, testApp, token, tokenName };
|
|
1956
|
+
export { AmbiguousProviderError, AsyncProviderInSyncResolutionError, CircularDependencyError, CosystemError, DuplicateProviderError, FrozenContainerError, InjectContextError, LifetimeLeakError, MissingProviderError, action, computed, createApp, createBroadcastWorkerTransport, createContainer, createDataTransportWorkerTransport, createLoggerPlugin, createMemoryBroadcastChannel, createMemoryWorkerTransportPair, createPostMessageWorkerTransport, createWorkerApp, createWorkerClient, defineModule, effect, getModuleMetadata, inject, lazyModule, module, provide, runInAction, state, testApp, token, tokenName };
|
|
1234
1957
|
|
|
1235
1958
|
//# sourceMappingURL=index.mjs.map
|