@bleedingdev/modern-js-renderer-octane 0.0.0-stage → 3.9.3-ultramodern.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/LICENSE +21 -0
  2. package/bin/octane-tsc.mjs +4 -0
  3. package/dist/cjs/bootstrap.js +68 -0
  4. package/dist/cjs/client.js +421 -0
  5. package/dist/cjs/entry-application.js +88 -0
  6. package/dist/cjs/entry-client.js +95 -0
  7. package/dist/cjs/entry-server.js +135 -0
  8. package/dist/cjs/federation-context.js +72 -0
  9. package/dist/cjs/federation.js +205 -0
  10. package/dist/cjs/i18n/I18nProvider.js +59 -0
  11. package/dist/cjs/i18n/LocalizedLink.js +80 -0
  12. package/dist/cjs/i18n/context.js +41 -0
  13. package/dist/cjs/i18n/index.js +83 -0
  14. package/dist/cjs/i18n/languageSync.js +99 -0
  15. package/dist/cjs/i18n/types.js +18 -0
  16. package/dist/cjs/i18n/useI18n.js +110 -0
  17. package/dist/cjs/i18n-external-snapshot.js +645 -0
  18. package/dist/cjs/index.js +46 -0
  19. package/dist/cjs/manifest.js +167 -0
  20. package/dist/cjs/plugin/compiler.js +122 -0
  21. package/dist/cjs/plugin/create.js +266 -0
  22. package/dist/cjs/plugin/index.js +151 -0
  23. package/dist/cjs/plugin/profile.js +91 -0
  24. package/dist/cjs/plugin/source.js +56 -0
  25. package/dist/cjs/router-client.js +139 -0
  26. package/dist/cjs/router-external-snapshot.js +291 -0
  27. package/dist/cjs/router-handler.js +171 -0
  28. package/dist/cjs/router-server-cleanup.js +46 -0
  29. package/dist/cjs/router-server-snapshot.js +405 -0
  30. package/dist/cjs/router-server.js +100 -0
  31. package/dist/cjs/router-snapshot.js +270 -0
  32. package/dist/cjs/router.js +218 -0
  33. package/dist/cjs/routes.js +190 -0
  34. package/dist/cjs/server.js +245 -0
  35. package/dist/cjs/typecheck.js +615 -0
  36. package/dist/cjs/worker-federation-context.js +63 -0
  37. package/dist/cjs/worker-federation-contexts.js +97 -0
  38. package/dist/cjs/worker-federation.js +97 -0
  39. package/dist/esm/bootstrap.mjs +24 -0
  40. package/dist/esm/client.mjs +377 -0
  41. package/dist/esm/entry-application.mjs +44 -0
  42. package/dist/esm/entry-client.mjs +57 -0
  43. package/dist/esm/entry-server.mjs +91 -0
  44. package/dist/esm/federation-context.mjs +25 -0
  45. package/dist/esm/federation.mjs +167 -0
  46. package/dist/esm/i18n/I18nProvider.mjs +21 -0
  47. package/dist/esm/i18n/LocalizedLink.mjs +42 -0
  48. package/dist/esm/i18n/context.mjs +3 -0
  49. package/dist/esm/i18n/index.mjs +8 -0
  50. package/dist/esm/i18n/languageSync.mjs +61 -0
  51. package/dist/esm/i18n/types.mjs +0 -0
  52. package/dist/esm/i18n/useI18n.mjs +72 -0
  53. package/dist/esm/i18n-external-snapshot.mjs +576 -0
  54. package/dist/esm/index.mjs +8 -0
  55. package/dist/esm/manifest.mjs +117 -0
  56. package/dist/esm/router-client.mjs +98 -0
  57. package/dist/esm/router-external-snapshot.mjs +244 -0
  58. package/dist/esm/router-handler.mjs +133 -0
  59. package/dist/esm/router-server-cleanup.mjs +8 -0
  60. package/dist/esm/router-server-snapshot.mjs +367 -0
  61. package/dist/esm/router-server.mjs +11 -0
  62. package/dist/esm/router-snapshot.mjs +199 -0
  63. package/dist/esm/router.mjs +94 -0
  64. package/dist/esm/routes.mjs +134 -0
  65. package/dist/esm/server.mjs +204 -0
  66. package/dist/esm/worker-federation-context.mjs +19 -0
  67. package/dist/esm/worker-federation-contexts.mjs +47 -0
  68. package/dist/esm/worker-federation.mjs +59 -0
  69. package/dist/esm-node/bootstrap.mjs +24 -0
  70. package/dist/esm-node/manifest.mjs +117 -0
  71. package/dist/esm-node/plugin/compiler.mjs +67 -0
  72. package/dist/esm-node/plugin/create.mjs +228 -0
  73. package/dist/esm-node/plugin/index.mjs +103 -0
  74. package/dist/esm-node/plugin/profile.mjs +53 -0
  75. package/dist/esm-node/plugin/source.mjs +7 -0
  76. package/dist/esm-node/typecheck.mjs +560 -0
  77. package/dist/types/bootstrap.d.ts +10 -0
  78. package/dist/types/client.d.ts +40 -0
  79. package/dist/types/entry-application.d.ts +19 -0
  80. package/dist/types/entry-client.d.ts +10 -0
  81. package/dist/types/entry-server.d.ts +14 -0
  82. package/dist/types/federation-context.d.ts +28 -0
  83. package/dist/types/federation.d.ts +20 -0
  84. package/dist/types/i18n/I18nProvider.d.ts +8 -0
  85. package/dist/types/i18n/LocalizedLink.d.ts +14 -0
  86. package/dist/types/i18n/context.d.ts +9 -0
  87. package/dist/types/i18n/index.d.ts +9 -0
  88. package/dist/types/i18n/languageSync.d.ts +26 -0
  89. package/dist/types/i18n/types.d.ts +34 -0
  90. package/dist/types/i18n/useI18n.d.ts +21 -0
  91. package/dist/types/i18n-external-snapshot.d.ts +43 -0
  92. package/dist/types/index.d.ts +9 -0
  93. package/dist/types/manifest.d.ts +34 -0
  94. package/dist/types/plugin/compiler-manifest.d.cts +10 -0
  95. package/dist/types/plugin/compiler.d.ts +5 -0
  96. package/dist/types/plugin/create.d.ts +23 -0
  97. package/dist/types/plugin/index.d.ts +3 -0
  98. package/dist/types/plugin/profile.d.ts +2 -0
  99. package/dist/types/plugin/source.d.ts +1 -0
  100. package/dist/types/plugin/svg-component-template.d.cts +6 -0
  101. package/dist/types/router-client.d.ts +12 -0
  102. package/dist/types/router-external-snapshot.d.ts +10 -0
  103. package/dist/types/router-handler.d.ts +13 -0
  104. package/dist/types/router-server-cleanup.d.ts +3 -0
  105. package/dist/types/router-server-snapshot.d.ts +15 -0
  106. package/dist/types/router-server.d.ts +11 -0
  107. package/dist/types/router-snapshot.d.ts +14 -0
  108. package/dist/types/router.d.ts +30 -0
  109. package/dist/types/routes.d.ts +20 -0
  110. package/dist/types/server.d.ts +47 -0
  111. package/dist/types/typecheck.d.ts +31 -0
  112. package/dist/types/worker-federation-context.d.ts +34 -0
  113. package/dist/types/worker-federation-contexts.d.ts +25 -0
  114. package/dist/types/worker-federation.d.ts +20 -0
  115. package/package.json +278 -4
  116. package/src/bootstrap.ts +60 -0
  117. package/src/client.ts +568 -0
  118. package/src/entry-application.ts +76 -0
  119. package/src/entry-client.ts +90 -0
  120. package/src/entry-server.ts +153 -0
  121. package/src/federation-context.ts +53 -0
  122. package/src/federation.ts +307 -0
  123. package/src/i18n/I18nProvider.ts +47 -0
  124. package/src/i18n/LocalizedLink.ts +86 -0
  125. package/src/i18n/context.ts +12 -0
  126. package/src/i18n/index.ts +31 -0
  127. package/src/i18n/languageSync.ts +132 -0
  128. package/src/i18n/types.ts +36 -0
  129. package/src/i18n/useI18n.ts +119 -0
  130. package/src/i18n-external-snapshot.ts +803 -0
  131. package/src/index.ts +10 -0
  132. package/src/manifest.ts +253 -0
  133. package/src/plugin/compiler-manifest.cjs +204 -0
  134. package/src/plugin/compiler.ts +104 -0
  135. package/src/plugin/create.ts +273 -0
  136. package/src/plugin/index.ts +107 -0
  137. package/src/plugin/profile.ts +50 -0
  138. package/src/plugin/source.ts +16 -0
  139. package/src/plugin/svg-component-template.cjs +17 -0
  140. package/src/router-client.ts +144 -0
  141. package/src/router-external-snapshot.ts +363 -0
  142. package/src/router-handler.ts +185 -0
  143. package/src/router-server-cleanup.ts +11 -0
  144. package/src/router-server-snapshot.ts +564 -0
  145. package/src/router-server.ts +21 -0
  146. package/src/router-snapshot.ts +251 -0
  147. package/src/router.ts +192 -0
  148. package/src/routes.ts +274 -0
  149. package/src/server.ts +340 -0
  150. package/src/typecheck.ts +723 -0
  151. package/src/worker-federation-context.ts +51 -0
  152. package/src/worker-federation-contexts.ts +91 -0
  153. package/src/worker-federation.ts +120 -0
  154. package/README.md +0 -3
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ OCTANE_WORKER_CONTEXT_KEYS: ()=>OCTANE_WORKER_CONTEXT_KEYS,
32
+ getOctaneWorkerRouterRewrite: ()=>getOctaneWorkerRouterRewrite,
33
+ registerOctaneWorkerContext: ()=>registerOctaneWorkerContext,
34
+ registerOctaneWorkerRouterRewrite: ()=>registerOctaneWorkerRouterRewrite,
35
+ useOctaneWorkerContextKeys: ()=>useOctaneWorkerContextKeys
36
+ });
37
+ const external_octane_namespaceObject = require("octane");
38
+ const OCTANE_WORKER_CONTEXT_KEYS = Object.freeze({
39
+ router: 'ultramodern.octane.router-context.v1',
40
+ match: 'ultramodern.octane.match-context.v1',
41
+ i18n: 'ultramodern.octane.i18n-context.v1'
42
+ });
43
+ const builtinKeys = Object.values(OCTANE_WORKER_CONTEXT_KEYS);
44
+ const contexts = new Map();
45
+ function registerOctaneWorkerContext(context, codec) {
46
+ const { key, isProvided } = codec;
47
+ if (!builtinKeys.includes(key) || 'function' != typeof isProvided) throw new TypeError('Invalid Octane Worker builtin context codec');
48
+ const unregister = (0, external_octane_namespaceObject.registerExternalSnapshotContext)(context, codec);
49
+ const hasProvider = ()=>isProvided((0, external_octane_namespaceObject.useContext)(context));
50
+ contexts.set(key, hasProvider);
51
+ return ()=>{
52
+ if (contexts.get(key) !== hasProvider) return;
53
+ unregister();
54
+ contexts.delete(key);
55
+ };
56
+ }
57
+ function useOctaneWorkerContextKeys(explicit = []) {
58
+ const selected = [];
59
+ for (const key of builtinKeys){
60
+ const hasProvider = contexts.get(key);
61
+ if (hasProvider?.() && !explicit.includes(key)) selected.push(key);
62
+ }
63
+ return [
64
+ ...selected,
65
+ ...explicit
66
+ ];
67
+ }
68
+ let routerRewrite;
69
+ function registerOctaneWorkerRouterRewrite(codec) {
70
+ if (routerRewrite || 'function' != typeof codec.capture || 'function' != typeof codec.restore) throw new TypeError('Invalid or duplicate Octane Worker router rewrite codec');
71
+ const captured = Object.freeze({
72
+ capture: codec.capture,
73
+ restore: codec.restore
74
+ });
75
+ routerRewrite = captured;
76
+ return ()=>{
77
+ if (routerRewrite === captured) routerRewrite = void 0;
78
+ };
79
+ }
80
+ function getOctaneWorkerRouterRewrite() {
81
+ return routerRewrite;
82
+ }
83
+ exports.OCTANE_WORKER_CONTEXT_KEYS = __webpack_exports__.OCTANE_WORKER_CONTEXT_KEYS;
84
+ exports.getOctaneWorkerRouterRewrite = __webpack_exports__.getOctaneWorkerRouterRewrite;
85
+ exports.registerOctaneWorkerContext = __webpack_exports__.registerOctaneWorkerContext;
86
+ exports.registerOctaneWorkerRouterRewrite = __webpack_exports__.registerOctaneWorkerRouterRewrite;
87
+ exports.useOctaneWorkerContextKeys = __webpack_exports__.useOctaneWorkerContextKeys;
88
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
89
+ "OCTANE_WORKER_CONTEXT_KEYS",
90
+ "getOctaneWorkerRouterRewrite",
91
+ "registerOctaneWorkerContext",
92
+ "registerOctaneWorkerRouterRewrite",
93
+ "useOctaneWorkerContextKeys"
94
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
95
+ Object.defineProperty(exports, '__esModule', {
96
+ value: true
97
+ });
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ createNativeWorkerFederationRuntime: ()=>createNativeWorkerFederationRuntime
32
+ });
33
+ const worker_federation_namespaceObject = require("@modern-js/renderer-core/worker-federation");
34
+ const server_namespaceObject = require("octane/server");
35
+ const external_federation_context_js_namespaceObject = require("./federation-context.js");
36
+ const external_worker_federation_context_js_namespaceObject = require("./worker-federation-context.js");
37
+ function isNativeWorkerComponent(value) {
38
+ return 'function' == typeof value;
39
+ }
40
+ function createNativeWorkerFederationRuntime(options, compiler) {
41
+ const { resources } = options;
42
+ const bindings = options.bindings;
43
+ const transport = resources.workerFederationServices?.length ? (0, worker_federation_namespaceObject.createWorkerFederationTransport)({
44
+ admitRendererContract: compiler.admitRendererContract,
45
+ services: resources.workerFederationServices.map((service)=>{
46
+ const binding = bindings && Reflect.get(bindings, service.binding);
47
+ if (!binding || 'object' != typeof binding && 'function' != typeof binding || !('fetch' in binding) || 'function' != typeof binding.fetch) throw new Error(`Native Worker federation requires service binding ${service.binding}.`);
48
+ return {
49
+ ...service,
50
+ fetch: binding.fetch.bind(binding)
51
+ };
52
+ })
53
+ }) : void 0;
54
+ let handle;
55
+ if (resources.workerFederation) {
56
+ if (!compiler.registry || !resources.workerFederationManifestUrl) throw new Error('Native Worker federation requires its compiled expose registry and pinned manifest URL.');
57
+ handle = compiler.registry.initialize({
58
+ publication: resources.workerFederation.worker,
59
+ manifestUrl: resources.workerFederationManifestUrl,
60
+ admitRendererContract: compiler.admitRendererContract,
61
+ admitNativeRequest (payload, { admitted, signal }) {
62
+ const initializeContexts = transport ? (provide, request)=>{
63
+ provide(external_federation_context_js_namespaceObject.FederationContext, (0, external_federation_context_js_namespaceObject.createFederationScope)(void 0, true, request.nonce));
64
+ provide(external_worker_federation_context_js_namespaceObject.WorkerFederationContext, {
65
+ transport,
66
+ locale: admitted.locale,
67
+ signal
68
+ });
69
+ } : void 0;
70
+ return (0, server_namespaceObject.prepareExternalSnapshotRequest)(payload, {
71
+ authority: admitted.coordinate.native,
72
+ signal,
73
+ ...initializeContexts ? {
74
+ initializeContexts
75
+ } : {}
76
+ });
77
+ },
78
+ releaseNativeRequest: server_namespaceObject.releasePreparedExternalSnapshotRequest,
79
+ async renderNativeSnapshot (module, request, { admitted }) {
80
+ const component = module && 'object' == typeof module && 'default' in module ? module.default : void 0;
81
+ if (!isNativeWorkerComponent(component)) throw new TypeError(`Native Worker expose ${admitted.expose} requires a default Octane component.`);
82
+ return (0, server_namespaceObject.serializeExternalSnapshot)(await (0, server_namespaceObject.renderExternalSnapshot)(component, request));
83
+ }
84
+ });
85
+ }
86
+ return {
87
+ transport,
88
+ handleRequest: handle ?? (()=>Promise.resolve(void 0))
89
+ };
90
+ }
91
+ exports.createNativeWorkerFederationRuntime = __webpack_exports__.createNativeWorkerFederationRuntime;
92
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
93
+ "createNativeWorkerFederationRuntime"
94
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
95
+ Object.defineProperty(exports, '__esModule', {
96
+ value: true
97
+ });
@@ -0,0 +1,24 @@
1
+ import { readDocumentBootstrap } from "@modern-js/renderer-core/document";
2
+ import { readRendererIdentity } from "@modern-js/renderer-core/identity";
3
+ function assertNativeHydrationBuildId(value) {
4
+ if ('string' != typeof value || 0 === value.trim().length) throw new Error('An Octane document requires its native client compilation identity.');
5
+ }
6
+ function assertOctaneIdentity(identity) {
7
+ readRendererIdentity(identity, identity);
8
+ if ('octane' !== identity.renderer) throw new Error('An Octane application requires an Octane renderer identity.');
9
+ }
10
+ function readOctaneDocumentBootstrap(document, expectedIdentity, expectedNativeHydrationBuildId) {
11
+ assertOctaneIdentity(expectedIdentity);
12
+ const { identity, documentId, hydrating, nativeHydrationBuildId } = readDocumentBootstrap(document, expectedIdentity, [
13
+ 'nativeHydrationBuildId'
14
+ ]);
15
+ assertNativeHydrationBuildId(nativeHydrationBuildId);
16
+ if (void 0 !== expectedNativeHydrationBuildId && nativeHydrationBuildId !== expectedNativeHydrationBuildId) throw new Error('Octane hydration bytes belong to a different native client compilation.');
17
+ return Object.freeze({
18
+ identity,
19
+ documentId,
20
+ hydrating,
21
+ nativeHydrationBuildId
22
+ });
23
+ }
24
+ export { assertNativeHydrationBuildId, assertOctaneIdentity, readOctaneDocumentBootstrap };
@@ -0,0 +1,377 @@
1
+ import { assertRendererIdentity } from "@modern-js/renderer-core/identity";
2
+ import { createRoot, hydrateRoot } from "octane";
3
+ import { bootstrapStreamedSignalHydration } from "octane/hydration/streamed-signals";
4
+ import { assertNativeHydrationBuildId, assertOctaneIdentity, readOctaneDocumentBootstrap } from "./bootstrap.mjs";
5
+ import { FederationApplication, createFederationScope } from "./federation-context.mjs";
6
+ import { WorkerFederationApplication } from "./worker-federation-context.mjs";
7
+ const roots = new WeakMap();
8
+ const documents = new WeakMap();
9
+ const moduleResources = new WeakMap();
10
+ function claimModuleResources(application) {
11
+ const dispose = application.dispose;
12
+ if (!dispose) return ()=>{};
13
+ let resources = moduleResources.get(dispose);
14
+ if (resources?.retired) throw new Error('A retired Octane application requires a fresh module resource instance.');
15
+ if (!resources) {
16
+ resources = {
17
+ users: 0,
18
+ retired: false
19
+ };
20
+ moduleResources.set(dispose, resources);
21
+ }
22
+ resources.users++;
23
+ let released = false;
24
+ return ()=>{
25
+ if (released) return;
26
+ released = true;
27
+ resources.users--;
28
+ if (0 === resources.users && !resources.retired) {
29
+ resources.retired = true;
30
+ dispose();
31
+ }
32
+ };
33
+ }
34
+ function retireAbandonedModule(application) {
35
+ if (application.dispose && moduleResources.get(application.dispose)?.users) return;
36
+ if (application.dispose && moduleResources.get(application.dispose)?.retired) return;
37
+ claimModuleResources(application)();
38
+ }
39
+ function observeRootErrors(options) {
40
+ let failed = false;
41
+ let failure;
42
+ let handle;
43
+ return {
44
+ options: {
45
+ ...options,
46
+ onUncaughtError (error) {
47
+ if (failed) return;
48
+ failed = true;
49
+ failure = error;
50
+ if (handle) {
51
+ const failedHandle = handle;
52
+ queueMicrotask(()=>{
53
+ try {
54
+ failedHandle.dispose();
55
+ } catch (cleanupError) {
56
+ failure = new AggregateError([
57
+ error,
58
+ cleanupError
59
+ ], 'Octane rendering and cleanup failed.');
60
+ }
61
+ if (options?.onUncaughtError) options.onUncaughtError(failure);
62
+ else throw failure;
63
+ });
64
+ }
65
+ }
66
+ },
67
+ attach (next) {
68
+ handle = next;
69
+ },
70
+ assertInitialRender () {
71
+ if (failed) {
72
+ options?.onUncaughtError?.(failure);
73
+ throw failure;
74
+ }
75
+ }
76
+ };
77
+ }
78
+ function claimRoot(container) {
79
+ if (9 === container.nodeType) throw new Error('An Octane application requires a subtree root in its framework-owned document.');
80
+ if (roots.has(container)) throw new Error('An Octane application already owns this root container.');
81
+ const owner = Symbol('Octane root owner');
82
+ roots.set(container, owner);
83
+ return ()=>{
84
+ if (roots.get(container) === owner) roots.delete(container);
85
+ };
86
+ }
87
+ function cleanupResources(cleanups) {
88
+ const errors = [];
89
+ for (const cleanup of cleanups)try {
90
+ cleanup();
91
+ } catch (error) {
92
+ errors.push(error);
93
+ }
94
+ if (errors.length) throw new AggregateError(errors, 'Octane application cleanup failed.');
95
+ }
96
+ function reportCleanupError(input, error) {
97
+ if (input.options?.onUncaughtError) input.options.onUncaughtError(error);
98
+ else queueMicrotask(()=>{
99
+ throw error;
100
+ });
101
+ }
102
+ function loadApplication(input, abandon) {
103
+ const acquire = (application)=>{
104
+ try {
105
+ validateModule(application);
106
+ } catch (error) {
107
+ if (application && 'function' == typeof application.dispose) retireAbandonedModule(application);
108
+ throw error;
109
+ }
110
+ return {
111
+ application,
112
+ releaseModule: claimModuleResources(application)
113
+ };
114
+ };
115
+ const { signal } = input;
116
+ if (!signal) return input.load().then(acquire);
117
+ return new Promise((resolve, reject)=>{
118
+ let settled = false;
119
+ let abandoned = false;
120
+ const onAbort = ()=>{
121
+ if (settled) return;
122
+ settled = true;
123
+ abandoned = true;
124
+ signal.removeEventListener('abort', onAbort);
125
+ try {
126
+ abandon();
127
+ reject(signal.reason);
128
+ } catch (cleanupError) {
129
+ reject(new AggregateError([
130
+ signal.reason,
131
+ cleanupError
132
+ ], 'Octane startup cancellation failed.'));
133
+ }
134
+ };
135
+ signal.addEventListener('abort', onAbort, {
136
+ once: true
137
+ });
138
+ if (signal.aborted) return void onAbort();
139
+ let loading;
140
+ try {
141
+ loading = input.load();
142
+ } catch (error) {
143
+ settled = true;
144
+ signal.removeEventListener('abort', onAbort);
145
+ reject(error);
146
+ return;
147
+ }
148
+ loading.then((application)=>{
149
+ if (abandoned) return void queueMicrotask(()=>{
150
+ try {
151
+ retireAbandonedModule(application);
152
+ } catch (error) {
153
+ reportCleanupError(input, error);
154
+ }
155
+ });
156
+ settled = true;
157
+ signal.removeEventListener('abort', onAbort);
158
+ try {
159
+ resolve(acquire(application));
160
+ } catch (error) {
161
+ reject(error);
162
+ }
163
+ }, (error)=>{
164
+ if (settled) return;
165
+ settled = true;
166
+ signal.removeEventListener('abort', onAbort);
167
+ reject(error);
168
+ });
169
+ });
170
+ }
171
+ function validateModule(application) {
172
+ if (!application || 'function' != typeof application.default) throw new TypeError('An Octane application module must default-export a native component.');
173
+ if (void 0 !== application.dispose && 'function' != typeof application.dispose) throw new TypeError('An Octane application disposer must be a function.');
174
+ }
175
+ function createHandle(input) {
176
+ let releaseModule = input.releaseModule;
177
+ let disposed = false;
178
+ const handle = {
179
+ root: input.root,
180
+ identity: Object.freeze({
181
+ ...input.identity
182
+ }),
183
+ update (next) {
184
+ if (disposed) throw new Error('Cannot update a disposed Octane application.');
185
+ validateModule(next);
186
+ const previousRelease = releaseModule;
187
+ const nextRelease = claimModuleResources(next);
188
+ releaseModule = nextRelease;
189
+ try {
190
+ input.workerFederation ? input.root.render(WorkerFederationApplication, {
191
+ scope: input.workerFederation,
192
+ federation: input.federation,
193
+ application: next
194
+ }) : input.federation ? input.root.render(FederationApplication, {
195
+ scope: input.federation,
196
+ application: next
197
+ }) : input.root.render(next.default, next.props);
198
+ previousRelease();
199
+ } catch (error) {
200
+ cleanupResources([
201
+ previousRelease,
202
+ ()=>handle.dispose()
203
+ ]);
204
+ throw error;
205
+ }
206
+ },
207
+ dispose () {
208
+ if (disposed) return;
209
+ disposed = true;
210
+ input.signal?.removeEventListener('abort', onAbort);
211
+ cleanupResources([
212
+ ()=>input.retireWorkerFederation?.(),
213
+ ()=>input.root.unmount(),
214
+ ()=>releaseModule(),
215
+ ()=>input.bridge?.dispose(),
216
+ input.release
217
+ ]);
218
+ }
219
+ };
220
+ function onAbort() {
221
+ queueMicrotask(()=>{
222
+ try {
223
+ handle.dispose();
224
+ } catch (error) {
225
+ input.onCleanupError?.(error);
226
+ }
227
+ });
228
+ }
229
+ input.signal?.addEventListener('abort', onAbort, {
230
+ once: true
231
+ });
232
+ return handle;
233
+ }
234
+ async function startApplication(input, release, hydration) {
235
+ const errors = observeRootErrors(input.options);
236
+ const workerController = input.workerFederation ? new AbortController() : void 0;
237
+ let workerFederation;
238
+ const retireWorkerFederation = ()=>cleanupResources([
239
+ ()=>workerController?.abort(new DOMException('The Worker federation document was disposed', 'AbortError')),
240
+ ()=>workerFederation?.transport.dispose()
241
+ ]);
242
+ let bridge;
243
+ let root;
244
+ let releaseModule;
245
+ let handle;
246
+ let cleaned = false;
247
+ const cleanup = ()=>{
248
+ if (handle) return void handle.dispose();
249
+ if (cleaned) return;
250
+ cleaned = true;
251
+ cleanupResources([
252
+ retireWorkerFederation,
253
+ ()=>root?.unmount(),
254
+ ()=>releaseModule?.(),
255
+ ()=>bridge?.dispose(),
256
+ release
257
+ ]);
258
+ };
259
+ try {
260
+ if (input.workerFederation && workerController) {
261
+ const signal = AbortSignal.any([
262
+ workerController.signal,
263
+ ...input.signal ? [
264
+ input.signal
265
+ ] : []
266
+ ]);
267
+ const scope = 'function' == typeof input.workerFederation ? input.workerFederation(signal) : input.workerFederation;
268
+ workerFederation = {
269
+ ...scope,
270
+ signal: scope.signal ? AbortSignal.any([
271
+ signal,
272
+ scope.signal
273
+ ]) : signal
274
+ };
275
+ }
276
+ if (workerFederation && !hydration && !input.documentId) throw new Error('Worker federation requires the trusted document identity before application loading');
277
+ const federation = input.federation || workerFederation ? createFederationScope(input.federation, false) : void 0;
278
+ if (hydration) {
279
+ const { document, documentId } = hydration;
280
+ bridge = bootstrapStreamedSignalHydration({
281
+ buildId: input.nativeHydrationBuildId,
282
+ documentId,
283
+ ...null === document.defaultView ? {} : {
284
+ target: document.defaultView
285
+ }
286
+ });
287
+ }
288
+ const loaded = await loadApplication(input, cleanup);
289
+ const application = loaded.application;
290
+ releaseModule = loaded.releaseModule;
291
+ input.signal?.throwIfAborted();
292
+ if (bridge) root = hydrateRoot(input.container, workerFederation ? WorkerFederationApplication : federation ? FederationApplication : application.default, workerFederation ? {
293
+ scope: workerFederation,
294
+ federation,
295
+ application
296
+ } : federation ? {
297
+ scope: federation,
298
+ application
299
+ } : application.props, {
300
+ ...errors.options,
301
+ signalOwner: bridge.signalOwner,
302
+ externalSnapshots: {
303
+ documentId: hydration.documentId
304
+ }
305
+ });
306
+ else {
307
+ root = createRoot(input.container, {
308
+ ...errors.options,
309
+ ...input.documentId ? {
310
+ externalSnapshots: {
311
+ documentId: input.documentId
312
+ }
313
+ } : {}
314
+ });
315
+ workerFederation ? root.render(WorkerFederationApplication, {
316
+ scope: workerFederation,
317
+ federation,
318
+ application
319
+ }) : federation ? root.render(FederationApplication, {
320
+ scope: federation,
321
+ application
322
+ }) : root.render(application.default, application.props);
323
+ }
324
+ errors.assertInitialRender();
325
+ input.signal?.throwIfAborted();
326
+ handle = createHandle({
327
+ root,
328
+ identity: input.identity,
329
+ releaseModule,
330
+ release,
331
+ bridge,
332
+ federation,
333
+ workerFederation,
334
+ retireWorkerFederation,
335
+ ...void 0 === input.signal ? {} : {
336
+ signal: input.signal
337
+ },
338
+ onCleanupError: (error)=>reportCleanupError(input, error)
339
+ });
340
+ errors.attach(handle);
341
+ return handle;
342
+ } catch (error) {
343
+ cleanup();
344
+ throw error;
345
+ }
346
+ }
347
+ async function mountOctaneApplication(input) {
348
+ assertOctaneIdentity(input.identity);
349
+ assertNativeHydrationBuildId(input.nativeHydrationBuildId);
350
+ input.signal?.throwIfAborted();
351
+ return startApplication(input, claimRoot(input.container));
352
+ }
353
+ async function hydrateOctaneApplication(input) {
354
+ assertOctaneIdentity(input.identity);
355
+ assertNativeHydrationBuildId(input.nativeHydrationBuildId);
356
+ assertNativeHydrationBuildId(input.documentNativeHydrationBuildId);
357
+ if (input.nativeHydrationBuildId !== input.documentNativeHydrationBuildId) throw new Error('Octane hydration bytes belong to a different native client compilation.');
358
+ assertRendererIdentity(input.documentIdentity, input.identity);
359
+ input.signal?.throwIfAborted();
360
+ if ('string' != typeof input.documentId || 0 === input.documentId.trim().length) throw new Error('Octane hydration requires a nonempty document identity.');
361
+ const document = input.container.ownerDocument;
362
+ if (!document) throw new Error('An Octane hydration root requires a document.');
363
+ if (document !== globalThis.document) throw new Error('Octane hydration requires a root in the active browser document.');
364
+ if (documents.has(document)) throw new Error('An Octane signal bridge already owns this document.');
365
+ const releaseRoot = claimRoot(input.container);
366
+ const documentOwner = Symbol(input.documentId);
367
+ documents.set(document, documentOwner);
368
+ const release = ()=>{
369
+ releaseRoot();
370
+ if (documents.get(document) === documentOwner) documents.delete(document);
371
+ };
372
+ return startApplication(input, release, {
373
+ document,
374
+ documentId: input.documentId
375
+ });
376
+ }
377
+ export { hydrateOctaneApplication, mountOctaneApplication, readOctaneDocumentBootstrap };
@@ -0,0 +1,44 @@
1
+ import { createMemoryHistory, createRouter } from "@octanejs/tanstack-router";
2
+ import { createElement } from "octane";
3
+ import { I18nProvider } from "./i18n/I18nProvider.mjs";
4
+ import { associateOctaneFileRouteSnapshot } from "./router-external-snapshot.mjs";
5
+ import { createFileSystemRouteTree } from "./routes.mjs";
6
+ function componentView(component, i18n) {
7
+ const App = component;
8
+ if (!i18n) return App;
9
+ return ()=>createElement(I18nProvider, {
10
+ instance: i18n.instance,
11
+ languages: i18n.languages,
12
+ localisedUrls: i18n.localisedUrls,
13
+ children: createElement(App)
14
+ });
15
+ }
16
+ const octaneRouterFactory = {
17
+ routeTree: (routes, modules, options)=>createFileSystemRouteTree(routes, modules, options),
18
+ router: ({ location, ...options })=>{
19
+ const router = createRouter({
20
+ ...options,
21
+ ...location ? {
22
+ origin: location.origin,
23
+ history: createMemoryHistory({
24
+ initialEntries: [
25
+ location.href
26
+ ]
27
+ })
28
+ } : {}
29
+ });
30
+ associateOctaneFileRouteSnapshot(router);
31
+ return router;
32
+ }
33
+ };
34
+ function localizedRouterRoot(Root) {
35
+ return ({ router, i18n })=>createElement(I18nProvider, {
36
+ instance: i18n.instance,
37
+ languages: i18n.languages,
38
+ localisedUrls: i18n.localisedUrls,
39
+ children: createElement(Root, {
40
+ router
41
+ })
42
+ });
43
+ }
44
+ export { componentView, localizedRouterRoot, octaneRouterFactory };