@forgeax/engine-host 0.1.27 → 0.1.29
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/README.md +9 -0
- package/dist/__tests__/startup.test.d.ts +2 -0
- package/dist/__tests__/startup.test.d.ts.map +1 -0
- package/dist/backend.d.ts +7 -1
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.mjs +56 -16
- package/dist/backend.mjs.map +1 -1
- package/dist/frontend.d.ts.map +1 -1
- package/dist/frontend.mjs +34 -11
- package/dist/frontend.mjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +70 -29
- package/dist/index.mjs.map +1 -1
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.mjs.map +1 -1
- package/dist/startup.d.ts +18 -0
- package/dist/startup.d.ts.map +1 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.mjs +3 -1
- package/dist/transport.mjs.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/host.test.ts +109 -0
- package/src/__tests__/startup.test.ts +27 -0
- package/src/backend.ts +42 -17
- package/src/frontend.ts +11 -11
- package/src/index.ts +1 -0
- package/src/protocol.ts +6 -1
- package/src/startup.ts +43 -0
- package/src/transport.ts +2 -0
package/README.md
CHANGED
|
@@ -30,3 +30,12 @@ capability: requests fail, `connected` becomes false, and the frontend status
|
|
|
30
30
|
becomes `failed` with a transport error. Consumer plugins own their domain
|
|
31
31
|
resources through Cordis effects; the host owns only its transport and Loader
|
|
32
32
|
lifetime.
|
|
33
|
+
|
|
34
|
+
Embedding owners can observe accepted frontend reports with
|
|
35
|
+
`backend.subscribeActivationReports(listener)`; the returned disposer removes
|
|
36
|
+
only that listener and preserves `onActivationReport`. A staged consumer may
|
|
37
|
+
call `backend.update(input, { bootstrap: true })` to replace the one bootstrap
|
|
38
|
+
revision admitted alongside the current assembly. Later updates retain that
|
|
39
|
+
bootstrap revision for reconnects; arbitrary stale revisions still fail. The
|
|
40
|
+
owner must serialize assembly updates and keep backend Entries in the input
|
|
41
|
+
when changing the frontend projection.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/startup.test.ts"],"names":[],"mappings":""}
|
package/dist/backend.d.ts
CHANGED
|
@@ -31,7 +31,13 @@ export interface BackendHost {
|
|
|
31
31
|
readonly transport: HostTransportServer;
|
|
32
32
|
readonly ownedContext: boolean;
|
|
33
33
|
/** Reconcile backend Entries and publish the matching frontend assembly atomically. */
|
|
34
|
-
update(input: HostAssemblyInput | readonly GamePluginEntry[]
|
|
34
|
+
update(input: HostAssemblyInput | readonly GamePluginEntry[],
|
|
35
|
+
/** Replace the one admitted bootstrap revision for staged frontend reconnects. */
|
|
36
|
+
options?: {
|
|
37
|
+
readonly bootstrap?: boolean;
|
|
38
|
+
}): Promise<HostAssembly>;
|
|
39
|
+
/** Observe accepted reports without replacing the owning host's callback. */
|
|
40
|
+
subscribeActivationReports(listener: (report: HostActivationReport) => void | Promise<void>): () => void;
|
|
35
41
|
dispose(): Promise<void>;
|
|
36
42
|
}
|
|
37
43
|
/**
|
package/dist/backend.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EAGpB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,4BAA4B,EACjC,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,iBAAiB,EACjB,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EAGpB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AAExB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CACnE;AAED,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,iFAAiF;IACjF,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtF;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,wBAAwB,CAAC;IAC5C,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC;IACxC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,uFAAuF;IACvF,MAAM,CACJ,KAAK,EAAE,iBAAiB,GAAG,SAAS,eAAe,EAAE;IACrD,kFAAkF;IAClF,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GACzC,OAAO,CAAC,YAAY,CAAC,CAAC;IACzB,6EAA6E;IAC7E,0BAA0B,CACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC/D,MAAM,IAAI,CAAC;IACd,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAwFD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,CAqM9F;AAED,YAAY,EAAE,4BAA4B,EAAE,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
|
package/dist/backend.mjs
CHANGED
|
@@ -350,6 +350,30 @@ function modulesFromCatalog(catalog, realm, version = "static") {
|
|
|
350
350
|
...record.digest === void 0 ? {} : { digest: record.digest }
|
|
351
351
|
}));
|
|
352
352
|
}
|
|
353
|
+
async function createHostStartup(options = {}) {
|
|
354
|
+
const context = options.context ?? new Context();
|
|
355
|
+
const ownedContext = options.context === void 0;
|
|
356
|
+
const fibers = [];
|
|
357
|
+
let disposed = false;
|
|
358
|
+
try {
|
|
359
|
+
for (const plugin of options.startupPlugins ?? []) fibers.push(await context.plugin(plugin));
|
|
360
|
+
} catch (error) {
|
|
361
|
+
for (const fiber of fibers.reverse()) await fiber.dispose();
|
|
362
|
+
if (ownedContext) await context.fiber.dispose();
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
context,
|
|
367
|
+
ownedContext,
|
|
368
|
+
fibers,
|
|
369
|
+
async dispose() {
|
|
370
|
+
if (disposed) return;
|
|
371
|
+
disposed = true;
|
|
372
|
+
for (const fiber of [...fibers].reverse()) await fiber.dispose();
|
|
373
|
+
if (ownedContext) await context.fiber.dispose();
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
}
|
|
353
377
|
|
|
354
378
|
// src/transport.ts
|
|
355
379
|
var HOST_ASSEMBLY_SERVICE = "host/assembly.get";
|
|
@@ -650,7 +674,6 @@ function assertBackendCatalogIdentity(catalog, modules) {
|
|
|
650
674
|
}
|
|
651
675
|
async function createBackendHost(options = {}) {
|
|
652
676
|
const context = options.context ?? new Context();
|
|
653
|
-
const ownedContext = options.context === void 0;
|
|
654
677
|
const realm = options.realm ?? "engine";
|
|
655
678
|
const catalog = options.catalog;
|
|
656
679
|
const pairedBackendEntries = options.pairs?.flatMap((pair) => pair.backend === void 0 ? [] : [pair.backend.entry]) ?? [];
|
|
@@ -666,27 +689,31 @@ async function createBackendHost(options = {}) {
|
|
|
666
689
|
});
|
|
667
690
|
const checkedInitial = validateHostAssembly(initialAssembly);
|
|
668
691
|
if (!checkedInitial.ok) {
|
|
669
|
-
if (
|
|
692
|
+
if (options.context === void 0) await context.fiber.dispose();
|
|
670
693
|
throw checkedInitial.error;
|
|
671
694
|
}
|
|
672
695
|
const backendModules = options.pairs === void 0 ? modules : options.pairs.flatMap((pair) => pair.backend === void 0 ? [] : [pair.backend.module]);
|
|
673
696
|
assertBackendCatalogIdentity(catalog, backendModules);
|
|
674
697
|
const authority = authorityOf(checkedInitial.value);
|
|
675
698
|
const assembly = authority.authority;
|
|
676
|
-
|
|
699
|
+
let bootstrapRevision = checkedInitial.value.revision;
|
|
700
|
+
const activationListeners = /* @__PURE__ */ new Set();
|
|
677
701
|
const transport = options.transport ?? createHostTransport();
|
|
678
|
-
let
|
|
702
|
+
let startup;
|
|
679
703
|
let loaderFiber;
|
|
680
704
|
let loader;
|
|
681
705
|
let backendEntries = options.pairs === void 0 ? options.entries ?? options.assembly?.entries ?? [] : pairedBackendEntries;
|
|
682
|
-
const startupFibers = [];
|
|
683
706
|
let unregisterAssemblyService;
|
|
684
707
|
let unregisterActivationService;
|
|
685
708
|
let unsubscribeAssembly;
|
|
686
709
|
try {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
710
|
+
startup = await createHostStartup({
|
|
711
|
+
context,
|
|
712
|
+
startupPlugins: [
|
|
713
|
+
hostFoundationPlugin(assembly, transport),
|
|
714
|
+
...options.startupPlugins ?? []
|
|
715
|
+
]
|
|
716
|
+
});
|
|
690
717
|
if (catalog !== void 0) {
|
|
691
718
|
const bootstrapped = await bootstrapCatalogLoader(context, catalog, realm, {
|
|
692
719
|
catalogDigest: checkedInitial.value.revision,
|
|
@@ -714,6 +741,7 @@ async function createBackendHost(options = {}) {
|
|
|
714
741
|
);
|
|
715
742
|
}
|
|
716
743
|
await options.onActivationReport?.(report);
|
|
744
|
+
for (const listener of activationListeners) await listener(report);
|
|
717
745
|
return { accepted: true };
|
|
718
746
|
}
|
|
719
747
|
);
|
|
@@ -725,9 +753,7 @@ async function createBackendHost(options = {}) {
|
|
|
725
753
|
unregisterAssemblyService?.();
|
|
726
754
|
unsubscribeAssembly?.();
|
|
727
755
|
await loaderFiber?.dispose();
|
|
728
|
-
|
|
729
|
-
await foundationFiber?.dispose();
|
|
730
|
-
if (ownedContext) await context.fiber.dispose();
|
|
756
|
+
await startup?.dispose();
|
|
731
757
|
throw error;
|
|
732
758
|
}
|
|
733
759
|
let disposed = false;
|
|
@@ -736,8 +762,22 @@ async function createBackendHost(options = {}) {
|
|
|
736
762
|
...loader === void 0 ? {} : { loader },
|
|
737
763
|
assembly,
|
|
738
764
|
transport,
|
|
739
|
-
ownedContext,
|
|
740
|
-
|
|
765
|
+
ownedContext: options.context === void 0,
|
|
766
|
+
subscribeActivationReports(listener) {
|
|
767
|
+
if (disposed) {
|
|
768
|
+
throw new HostAssemblyError(
|
|
769
|
+
"host-assembly-service-unavailable",
|
|
770
|
+
"the backend host to remain active while observing activation reports",
|
|
771
|
+
"Subscribe on an active host instance.",
|
|
772
|
+
{ service: HOST_ACTIVATION_REPORT_SERVICE }
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
activationListeners.add(listener);
|
|
776
|
+
return () => {
|
|
777
|
+
activationListeners.delete(listener);
|
|
778
|
+
};
|
|
779
|
+
},
|
|
780
|
+
async update(nextInput, updateOptions) {
|
|
741
781
|
if (disposed) {
|
|
742
782
|
throw new HostAssemblyError(
|
|
743
783
|
"host-assembly-service-unavailable",
|
|
@@ -774,19 +814,19 @@ async function createBackendHost(options = {}) {
|
|
|
774
814
|
await loader.await();
|
|
775
815
|
}
|
|
776
816
|
backendEntries = nextBackendEntries;
|
|
817
|
+
if (updateOptions?.bootstrap === true) bootstrapRevision = checkedCandidate.value.revision;
|
|
777
818
|
return authority.publish(effectiveInput);
|
|
778
819
|
},
|
|
779
820
|
async dispose() {
|
|
780
821
|
if (disposed) return;
|
|
781
822
|
disposed = true;
|
|
823
|
+
activationListeners.clear();
|
|
782
824
|
unsubscribeAssembly?.();
|
|
783
825
|
unregisterActivationService?.();
|
|
784
826
|
unregisterAssemblyService?.();
|
|
785
827
|
transport.close();
|
|
786
828
|
await loaderFiber?.dispose();
|
|
787
|
-
|
|
788
|
-
await foundationFiber?.dispose();
|
|
789
|
-
if (ownedContext) await context.fiber.dispose();
|
|
829
|
+
await startup?.dispose();
|
|
790
830
|
}
|
|
791
831
|
};
|
|
792
832
|
return host;
|