@bleedingdev/modern-js-renderer-octane 3.9.3-ultramodern.1 → 3.9.3-ultramodern.11

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 (100) hide show
  1. package/dist/cjs/client.js +56 -6
  2. package/dist/cjs/entry-application.js +7 -2
  3. package/dist/cjs/entry-client.js +3 -0
  4. package/dist/cjs/entry-server.js +13 -5
  5. package/dist/cjs/federation.js +108 -6
  6. package/dist/cjs/i18n/I18nProvider.js +6 -14
  7. package/dist/cjs/i18n/LocalizedLink.js +24 -33
  8. package/dist/cjs/i18n/index.js +0 -3
  9. package/dist/cjs/i18n-external-snapshot.js +645 -0
  10. package/dist/cjs/index.js +4 -4
  11. package/dist/cjs/manifest.js +2 -2
  12. package/dist/cjs/plugin/compiler.js +2 -5
  13. package/dist/cjs/plugin/create.js +27 -26
  14. package/dist/cjs/plugin/index.js +2 -2
  15. package/dist/cjs/plugin/profile.js +12 -10
  16. package/dist/cjs/router-client.js +1 -1
  17. package/dist/cjs/router-external-snapshot.js +291 -0
  18. package/dist/cjs/router-handler.js +11 -8
  19. package/dist/cjs/router-server.js +3 -11
  20. package/dist/cjs/router.js +1 -1
  21. package/dist/cjs/routes.js +20 -17
  22. package/dist/cjs/server.js +28 -7
  23. package/dist/cjs/worker-federation-context.js +63 -0
  24. package/dist/cjs/worker-federation-contexts.js +97 -0
  25. package/dist/cjs/worker-federation.js +97 -0
  26. package/dist/esm/client.mjs +56 -6
  27. package/dist/esm/entry-application.mjs +7 -2
  28. package/dist/esm/entry-client.mjs +3 -0
  29. package/dist/esm/entry-server.mjs +11 -6
  30. package/dist/esm/federation.mjs +110 -8
  31. package/dist/esm/i18n/I18nProvider.mjs +7 -15
  32. package/dist/esm/i18n/LocalizedLink.mjs +24 -30
  33. package/dist/esm/i18n/index.mjs +1 -1
  34. package/dist/esm/i18n-external-snapshot.mjs +576 -0
  35. package/dist/esm/index.mjs +4 -4
  36. package/dist/esm/manifest.mjs +2 -2
  37. package/dist/esm/router-client.mjs +1 -1
  38. package/dist/esm/router-external-snapshot.mjs +244 -0
  39. package/dist/esm/router-handler.mjs +11 -8
  40. package/dist/esm/router-server.mjs +0 -1
  41. package/dist/esm/router.mjs +2 -2
  42. package/dist/esm/routes.mjs +18 -18
  43. package/dist/esm/server.mjs +24 -3
  44. package/dist/esm/worker-federation-context.mjs +19 -0
  45. package/dist/esm/worker-federation-contexts.mjs +47 -0
  46. package/dist/esm/worker-federation.mjs +59 -0
  47. package/dist/esm-node/manifest.mjs +2 -2
  48. package/dist/esm-node/plugin/compiler.mjs +2 -5
  49. package/dist/esm-node/plugin/create.mjs +27 -26
  50. package/dist/esm-node/plugin/index.mjs +2 -2
  51. package/dist/esm-node/plugin/profile.mjs +12 -10
  52. package/dist/types/client.d.ts +5 -1
  53. package/dist/types/entry-client.d.ts +2 -0
  54. package/dist/types/entry-server.d.ts +4 -1
  55. package/dist/types/federation.d.ts +2 -0
  56. package/dist/types/i18n/LocalizedLink.d.ts +5 -32
  57. package/dist/types/i18n/context.d.ts +1 -1
  58. package/dist/types/i18n/index.d.ts +1 -1
  59. package/dist/types/i18n-external-snapshot.d.ts +43 -0
  60. package/dist/types/index.d.ts +4 -4
  61. package/dist/types/manifest.d.ts +2 -2
  62. package/dist/types/router-external-snapshot.d.ts +10 -0
  63. package/dist/types/router-server.d.ts +0 -2
  64. package/dist/types/routes.d.ts +2 -0
  65. package/dist/types/server.d.ts +6 -0
  66. package/dist/types/worker-federation-context.d.ts +34 -0
  67. package/dist/types/worker-federation-contexts.d.ts +25 -0
  68. package/dist/types/worker-federation.d.ts +20 -0
  69. package/package.json +84 -22
  70. package/src/client.ts +99 -16
  71. package/src/entry-application.ts +7 -3
  72. package/src/entry-client.ts +10 -0
  73. package/src/entry-server.ts +20 -9
  74. package/src/federation.ts +164 -15
  75. package/src/i18n/I18nProvider.ts +11 -20
  76. package/src/i18n/LocalizedLink.ts +46 -72
  77. package/src/i18n/context.ts +1 -1
  78. package/src/i18n/index.ts +1 -5
  79. package/src/i18n-external-snapshot.ts +803 -0
  80. package/src/index.ts +4 -4
  81. package/src/manifest.ts +2 -2
  82. package/src/plugin/compiler-manifest.cjs +27 -1
  83. package/src/plugin/compiler.ts +6 -14
  84. package/src/plugin/create.ts +27 -26
  85. package/src/plugin/index.ts +4 -2
  86. package/src/plugin/profile.ts +14 -10
  87. package/src/router-client.ts +1 -1
  88. package/src/router-external-snapshot.ts +363 -0
  89. package/src/router-handler.ts +11 -8
  90. package/src/router-server.ts +0 -2
  91. package/src/router.ts +2 -2
  92. package/src/routes.ts +37 -26
  93. package/src/server.ts +45 -5
  94. package/src/worker-federation-context.ts +51 -0
  95. package/src/worker-federation-contexts.ts +91 -0
  96. package/src/worker-federation.ts +120 -0
  97. package/dist/cjs/router-injection.js +0 -139
  98. package/dist/esm/router-injection.mjs +0 -101
  99. package/dist/types/router-injection.d.ts +0 -8
  100. package/src/router-injection.ts +0 -145
@@ -37,6 +37,7 @@ const external_octane_namespaceObject = require("octane");
37
37
  const streamed_signals_namespaceObject = require("octane/hydration/streamed-signals");
38
38
  const external_bootstrap_js_namespaceObject = require("./bootstrap.js");
39
39
  const external_federation_context_js_namespaceObject = require("./federation-context.js");
40
+ const external_worker_federation_context_js_namespaceObject = require("./worker-federation-context.js");
40
41
  const roots = new WeakMap();
41
42
  const documents = new WeakMap();
42
43
  const moduleResources = new WeakMap();
@@ -220,7 +221,11 @@ function createHandle(input) {
220
221
  const nextRelease = claimModuleResources(next);
221
222
  releaseModule = nextRelease;
222
223
  try {
223
- input.federation ? input.root.render(external_federation_context_js_namespaceObject.FederationApplication, {
224
+ input.workerFederation ? input.root.render(external_worker_federation_context_js_namespaceObject.WorkerFederationApplication, {
225
+ scope: input.workerFederation,
226
+ federation: input.federation,
227
+ application: next
228
+ }) : input.federation ? input.root.render(external_federation_context_js_namespaceObject.FederationApplication, {
224
229
  scope: input.federation,
225
230
  application: next
226
231
  }) : input.root.render(next.default, next.props);
@@ -238,6 +243,7 @@ function createHandle(input) {
238
243
  disposed = true;
239
244
  input.signal?.removeEventListener('abort', onAbort);
240
245
  cleanupResources([
246
+ ()=>input.retireWorkerFederation?.(),
241
247
  ()=>input.root.unmount(),
242
248
  ()=>releaseModule(),
243
249
  ()=>input.bridge?.dispose(),
@@ -261,6 +267,12 @@ function createHandle(input) {
261
267
  }
262
268
  async function startApplication(input, release, hydration) {
263
269
  const errors = observeRootErrors(input.options);
270
+ const workerController = input.workerFederation ? new AbortController() : void 0;
271
+ let workerFederation;
272
+ const retireWorkerFederation = ()=>cleanupResources([
273
+ ()=>workerController?.abort(new DOMException('The Worker federation document was disposed', 'AbortError')),
274
+ ()=>workerFederation?.transport.dispose()
275
+ ]);
264
276
  let bridge;
265
277
  let root;
266
278
  let releaseModule;
@@ -271,6 +283,7 @@ async function startApplication(input, release, hydration) {
271
283
  if (cleaned) return;
272
284
  cleaned = true;
273
285
  cleanupResources([
286
+ retireWorkerFederation,
274
287
  ()=>root?.unmount(),
275
288
  ()=>releaseModule?.(),
276
289
  ()=>bridge?.dispose(),
@@ -278,7 +291,24 @@ async function startApplication(input, release, hydration) {
278
291
  ]);
279
292
  };
280
293
  try {
281
- const federation = input.federation ? (0, external_federation_context_js_namespaceObject.createFederationScope)(input.federation, false) : void 0;
294
+ if (input.workerFederation && workerController) {
295
+ const signal = AbortSignal.any([
296
+ workerController.signal,
297
+ ...input.signal ? [
298
+ input.signal
299
+ ] : []
300
+ ]);
301
+ const scope = 'function' == typeof input.workerFederation ? input.workerFederation(signal) : input.workerFederation;
302
+ workerFederation = {
303
+ ...scope,
304
+ signal: scope.signal ? AbortSignal.any([
305
+ signal,
306
+ scope.signal
307
+ ]) : signal
308
+ };
309
+ }
310
+ if (workerFederation && !hydration && !input.documentId) throw new Error('Worker federation requires the trusted document identity before application loading');
311
+ const federation = input.federation || workerFederation ? (0, external_federation_context_js_namespaceObject.createFederationScope)(input.federation, false) : void 0;
282
312
  if (hydration) {
283
313
  const { document, documentId } = hydration;
284
314
  bridge = (0, streamed_signals_namespaceObject.bootstrapStreamedSignalHydration)({
@@ -293,16 +323,34 @@ async function startApplication(input, release, hydration) {
293
323
  const application = loaded.application;
294
324
  releaseModule = loaded.releaseModule;
295
325
  input.signal?.throwIfAborted();
296
- if (bridge) root = (0, external_octane_namespaceObject.hydrateRoot)(input.container, federation ? external_federation_context_js_namespaceObject.FederationApplication : application.default, federation ? {
326
+ if (bridge) root = (0, external_octane_namespaceObject.hydrateRoot)(input.container, workerFederation ? external_worker_federation_context_js_namespaceObject.WorkerFederationApplication : federation ? external_federation_context_js_namespaceObject.FederationApplication : application.default, workerFederation ? {
327
+ scope: workerFederation,
328
+ federation,
329
+ application
330
+ } : federation ? {
297
331
  scope: federation,
298
332
  application
299
333
  } : application.props, {
300
334
  ...errors.options,
301
- signalOwner: bridge.signalOwner
335
+ signalOwner: bridge.signalOwner,
336
+ externalSnapshots: {
337
+ documentId: hydration.documentId
338
+ }
302
339
  });
303
340
  else {
304
- root = (0, external_octane_namespaceObject.createRoot)(input.container, errors.options);
305
- federation ? root.render(external_federation_context_js_namespaceObject.FederationApplication, {
341
+ root = (0, external_octane_namespaceObject.createRoot)(input.container, {
342
+ ...errors.options,
343
+ ...input.documentId ? {
344
+ externalSnapshots: {
345
+ documentId: input.documentId
346
+ }
347
+ } : {}
348
+ });
349
+ workerFederation ? root.render(external_worker_federation_context_js_namespaceObject.WorkerFederationApplication, {
350
+ scope: workerFederation,
351
+ federation,
352
+ application
353
+ }) : federation ? root.render(external_federation_context_js_namespaceObject.FederationApplication, {
306
354
  scope: federation,
307
355
  application
308
356
  }) : root.render(application.default, application.props);
@@ -316,6 +364,8 @@ async function startApplication(input, release, hydration) {
316
364
  release,
317
365
  bridge,
318
366
  federation,
367
+ workerFederation,
368
+ retireWorkerFederation,
319
369
  ...void 0 === input.signal ? {} : {
320
370
  signal: input.signal
321
371
  },
@@ -35,6 +35,7 @@ __webpack_require__.d(__webpack_exports__, {
35
35
  const tanstack_router_namespaceObject = require("@octanejs/tanstack-router");
36
36
  const external_octane_namespaceObject = require("octane");
37
37
  const I18nProvider_js_namespaceObject = require("./i18n/I18nProvider.js");
38
+ const external_router_external_snapshot_js_namespaceObject = require("./router-external-snapshot.js");
38
39
  const external_routes_js_namespaceObject = require("./routes.js");
39
40
  function componentView(component, i18n) {
40
41
  const App = component;
@@ -48,7 +49,8 @@ function componentView(component, i18n) {
48
49
  }
49
50
  const octaneRouterFactory = {
50
51
  routeTree: (routes, modules, options)=>(0, external_routes_js_namespaceObject.createFileSystemRouteTree)(routes, modules, options),
51
- router: ({ location, ...options })=>(0, tanstack_router_namespaceObject.createRouter)({
52
+ router: ({ location, ...options })=>{
53
+ const router = (0, tanstack_router_namespaceObject.createRouter)({
52
54
  ...options,
53
55
  ...location ? {
54
56
  origin: location.origin,
@@ -58,7 +60,10 @@ const octaneRouterFactory = {
58
60
  ]
59
61
  })
60
62
  } : {}
61
- })
63
+ });
64
+ (0, external_router_external_snapshot_js_namespaceObject.associateOctaneFileRouteSnapshot)(router);
65
+ return router;
66
+ }
62
67
  };
63
68
  function localizedRouterRoot(Root) {
64
69
  return ({ router, i18n })=>(0, external_octane_namespaceObject.createElement)(I18nProvider_js_namespaceObject.I18nProvider, {
@@ -41,6 +41,7 @@ function startNativeClient(options) {
41
41
  (0, entry_client_namespaceObject.startNativeClientEntry)(options, {
42
42
  readBootstrap: (document, identity)=>(0, external_client_js_namespaceObject.readOctaneDocumentBootstrap)(document, identity, nativeHydrationBuildId),
43
43
  createRouter: (application, routerOptions)=>(0, router_namespaceObject.createNativeRouter)(application, routerOptions, external_entry_application_js_namespaceObject.octaneRouterFactory),
44
+ disposeRouter: (router)=>router.history.destroy(),
44
45
  async prepareRouter (router, hydrating, signal) {
45
46
  if (hydrating) await (0, external_router_client_js_namespaceObject.prepareOctaneRouterHydration)(router, {
46
47
  signal
@@ -53,6 +54,8 @@ function startNativeClient(options) {
53
54
  identity,
54
55
  nativeHydrationBuildId,
55
56
  federation: options.federation,
57
+ workerFederation: options.workerFederation,
58
+ documentId: bootstrap?.documentId,
56
59
  signal,
57
60
  load: async ()=>{
58
61
  const view = await load();
@@ -29,6 +29,7 @@ var __webpack_exports__ = {};
29
29
  __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
31
  createNativeServerEntry: ()=>createNativeServerEntry,
32
+ createNativeWorkerFederationRuntime: ()=>external_worker_federation_js_namespaceObject.createNativeWorkerFederationRuntime,
32
33
  withOctaneDocumentFields: ()=>withOctaneDocumentFields
33
34
  });
34
35
  const data_namespaceObject = require("@modern-js/renderer-core/data");
@@ -38,6 +39,7 @@ const external_entry_application_js_namespaceObject = require("./entry-applicati
38
39
  const external_manifest_js_namespaceObject = require("./manifest.js");
39
40
  const external_router_server_js_namespaceObject = require("./router-server.js");
40
41
  const external_server_js_namespaceObject = require("./server.js");
42
+ const external_worker_federation_js_namespaceObject = require("./worker-federation.js");
41
43
  const OCTANE_DOCUMENT_FIELDS = new Set([
42
44
  'content-language',
43
45
  'content-location',
@@ -67,13 +69,15 @@ function createNativeServerEntry(options) {
67
69
  session,
68
70
  document
69
71
  }),
70
- renderComponent: ({ session }, component, document, i18n)=>(0, external_server_js_namespaceObject.renderOctaneApplication)({
72
+ renderComponent: ({ session, workerFederation }, component, document, i18n)=>(0, external_server_js_namespaceObject.renderOctaneApplication)({
71
73
  session,
72
74
  App: (0, external_entry_application_js_namespaceObject.componentView)(component, i18n),
73
75
  document,
74
- federation: options.federation
76
+ federation: options.federation,
77
+ workerFederation,
78
+ workerFederationLocale: options.workerFederationLocale
75
79
  }),
76
- async renderRoutes ({ request, context: { session }, router, outcomes, document, forbiddenValues, i18n }) {
80
+ async renderRoutes ({ request, context: { session, workerFederation }, router, outcomes, document, forbiddenValues, i18n }) {
77
81
  const response = await (0, external_router_server_js_namespaceObject.createOctaneRequestHandler)({
78
82
  request,
79
83
  session,
@@ -83,7 +87,7 @@ function createNativeServerEntry(options) {
83
87
  }
84
88
  })(async ({ router, responseHeaders })=>{
85
89
  const metadata = (0, data_namespaceObject.mergeDataResponseMetadata)(outcomes, {
86
- status: router.state.statusCode ?? 200
90
+ status: (0, external_router_server_js_namespaceObject.getSsrStatus)(router)
87
91
  });
88
92
  const policy = (0, data_namespaceObject.dataMetadataToDocumentPolicy)({
89
93
  ...metadata,
@@ -106,7 +110,9 @@ function createNativeServerEntry(options) {
106
110
  },
107
111
  document,
108
112
  federation: options.federation,
109
- injection: (0, external_router_server_js_namespaceObject.createOctaneRouterInjection)(router, session)
113
+ workerFederation,
114
+ workerFederationLocale: options.workerFederationLocale,
115
+ router
110
116
  });
111
117
  return (0, external_router_server_js_namespaceObject.createSsrStreamResponse)(router, rendered);
112
118
  });
@@ -117,9 +123,11 @@ function createNativeServerEntry(options) {
117
123
  });
118
124
  }
119
125
  exports.createNativeServerEntry = __webpack_exports__.createNativeServerEntry;
126
+ exports.createNativeWorkerFederationRuntime = __webpack_exports__.createNativeWorkerFederationRuntime;
120
127
  exports.withOctaneDocumentFields = __webpack_exports__.withOctaneDocumentFields;
121
128
  for(var __rspack_i in __webpack_exports__)if (-1 === [
122
129
  "createNativeServerEntry",
130
+ "createNativeWorkerFederationRuntime",
123
131
  "withOctaneDocumentFields"
124
132
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
125
133
  Object.defineProperty(exports, '__esModule', {
@@ -33,6 +33,9 @@ __webpack_require__.d(__webpack_exports__, {
33
33
  const federation_namespaceObject = require("@modern-js/renderer-core/federation");
34
34
  const external_octane_namespaceObject = require("octane");
35
35
  const external_federation_context_js_namespaceObject = require("./federation-context.js");
36
+ const context_js_namespaceObject = require("./i18n/context.js");
37
+ const external_worker_federation_context_js_namespaceObject = require("./worker-federation-context.js");
38
+ const external_worker_federation_contexts_js_namespaceObject = require("./worker-federation-contexts.js");
36
39
  function withTimeout(promise, timeout, label) {
37
40
  if (void 0 === timeout) return promise;
38
41
  return new Promise((resolve, reject)=>{
@@ -47,6 +50,7 @@ function withTimeout(promise, timeout, label) {
47
50
  });
48
51
  });
49
52
  }
53
+ const publisherRegistrationEffectSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
50
54
  function federatedComponent(remote, options = {}) {
51
55
  if ('string' == typeof remote ? !/^[^/]+\/.+/u.test(remote) : 'function' != typeof remote) throw new TypeError("federatedComponent requires a remote id such as 'remote/Widget' or a loader");
52
56
  if (void 0 !== options.timeout && (!Number.isFinite(options.timeout) || options.timeout <= 0)) throw new TypeError('federatedComponent timeout must be a positive number of milliseconds');
@@ -56,19 +60,117 @@ function federatedComponent(remote, options = {}) {
56
60
  server: "u" < typeof document
57
61
  };
58
62
  const components = new WeakMap();
63
+ const workerOwners = new WeakMap();
59
64
  return (props)=>{
60
65
  const context = (0, external_octane_namespaceObject.useContext)(external_federation_context_js_namespaceObject.FederationContext) ?? standalone;
61
- let Remote = components.get(context);
66
+ const worker = (0, external_octane_namespaceObject.useContext)(external_worker_federation_context_js_namespaceObject.WorkerFederationContext);
67
+ const language = worker ? (0, external_octane_namespaceObject.useContext)(context_js_namespaceObject.I18nContext)?.language ?? worker.locale : void 0;
68
+ const contextKeys = worker ? (0, external_worker_federation_contexts_js_namespaceObject.useOctaneWorkerContextKeys)(options.contextKeys) : void 0;
69
+ let owner = context;
70
+ if (worker) {
71
+ let scopes = workerOwners.get(context);
72
+ if (!scopes) workerOwners.set(context, scopes = new WeakMap());
73
+ let variants = scopes.get(worker);
74
+ if (!variants) scopes.set(worker, variants = new Map());
75
+ const key = JSON.stringify([
76
+ context.server ? language : void 0,
77
+ contextKeys
78
+ ]);
79
+ let variant = variants.get(key);
80
+ if (!variant) variants.set(key, variant = {});
81
+ owner = variant;
82
+ }
83
+ let Remote = components.get(owner);
62
84
  if (!Remote) {
63
85
  Remote = (0, external_octane_namespaceObject.lazy)(async ()=>{
64
86
  try {
65
87
  if (context.server && !id) throw new Error('A federatedComponent loader renders in the browser only; use a remote id to server-render it');
66
- const module = await withTimeout(Promise.resolve().then(()=>id ? (0, federation_namespaceObject.loadFederatedModule)(context.instance, id) : remote()), options.timeout ?? (context.server ? 3000 : void 0), id ?? 'loader');
88
+ if (worker) {
89
+ if (!id || !language) throw new Error('Worker federation requires a remote id and the owning entry locale');
90
+ const separator = id.indexOf('/');
91
+ const remoteName = id.slice(0, separator);
92
+ const expose = `./${id.slice(separator + 1)}`;
93
+ const controller = new AbortController();
94
+ const signal = worker.signal ? AbortSignal.any([
95
+ worker.signal,
96
+ controller.signal
97
+ ]) : controller.signal;
98
+ const timeout = options.timeout ?? (context.server ? 3000 : void 0);
99
+ let admitted;
100
+ try {
101
+ admitted = await withTimeout(worker.transport.admit({
102
+ remote: remoteName,
103
+ expose,
104
+ locale: language,
105
+ signal
106
+ }), timeout, id);
107
+ } finally{
108
+ controller.abort();
109
+ }
110
+ const BrowserRemote = (0, external_octane_namespaceObject.lazy)(async ()=>{
111
+ const { module, assets } = await (0, federation_namespaceObject.loadFederatedModule)(context.instance, id);
112
+ if ('function' != typeof module?.default) throw new TypeError('A federated Octane module must default-export a native component');
113
+ const component = module.default;
114
+ const Loaded = (props, scope, extra)=>{
115
+ for (const href of assets?.css ?? [])(0, external_octane_namespaceObject.preinit)(href, {
116
+ as: 'style',
117
+ precedence: 'federated',
118
+ ...void 0 === context.nonce ? {} : {
119
+ nonce: context.nonce
120
+ }
121
+ });
122
+ return component(props, scope, extra);
123
+ };
124
+ return {
125
+ default: Loaded
126
+ };
127
+ });
128
+ const boundary = (0, external_octane_namespaceObject.externalSnapshotBoundary)({
129
+ authority: admitted.coordinate.native,
130
+ component: BrowserRemote,
131
+ contextKeys,
132
+ timeoutMs: timeout,
133
+ async snapshot (request, signal) {
134
+ const response = await worker.transport.request({
135
+ remote: remoteName,
136
+ expose,
137
+ locale: language,
138
+ payload: (0, external_octane_namespaceObject.serializeExternalSnapshotRequest)(request),
139
+ signal
140
+ });
141
+ return (0, external_octane_namespaceObject.decodeExternalSnapshot)(response.payload);
142
+ }
143
+ });
144
+ const Loaded = (props)=>{
145
+ for (const href of admitted.styles)(0, external_octane_namespaceObject.preinit)(href, {
146
+ as: 'style',
147
+ precedence: 'federated',
148
+ ...void 0 === context.nonce ? {} : {
149
+ nonce: context.nonce
150
+ }
151
+ });
152
+ return (0, external_octane_namespaceObject.createElement)(boundary, props);
153
+ };
154
+ return {
155
+ default: Loaded
156
+ };
157
+ }
158
+ const { module, assets } = await withTimeout(Promise.resolve().then(()=>id ? (0, federation_namespaceObject.loadFederatedModule)(context.instance, id) : remote().then((module)=>({
159
+ module,
160
+ assets: void 0
161
+ }))), options.timeout ?? (context.server ? 3000 : void 0), id ?? 'loader');
67
162
  if ('function' != typeof module?.default) throw new TypeError('A federated Octane module must default-export a native component');
68
- const assets = id && context.instance ? (0, federation_namespaceObject.remoteBrowserAssets)(context.instance, id) : void 0;
69
163
  if (context.server && !assets) throw new Error(`Cannot server-render ${id}: the host has no browser assets for this remote`);
70
- const component = module.default;
164
+ const component = (0, external_octane_namespaceObject.publisherBoundary)(module.default, {
165
+ publisherKey: id ?? 'ultramodern:browser-loader'
166
+ });
71
167
  const Loaded = (props)=>{
168
+ (0, external_octane_namespaceObject.useEffect)(()=>{
169
+ if (context.server || !id || !context.instance) return;
170
+ const register = Reflect.get(context.instance, Symbol.for('ultramodern.federation.browser-dev-boundary.v1'));
171
+ if ('function' != typeof register) return;
172
+ return register(id, module.default, component);
173
+ }, [], publisherRegistrationEffectSlot);
72
174
  for (const href of assets?.css ?? [])(0, external_octane_namespaceObject.preinit)(href, {
73
175
  as: 'style',
74
176
  precedence: 'federated',
@@ -82,11 +184,11 @@ function federatedComponent(remote, options = {}) {
82
184
  default: Loaded
83
185
  };
84
186
  } catch (error) {
85
- if (!context.server) components.delete(context);
187
+ if (!context.server) components.delete(owner);
86
188
  throw error;
87
189
  }
88
190
  });
89
- components.set(context, Remote);
191
+ components.set(owner, Remote);
90
192
  }
91
193
  return (0, external_octane_namespaceObject.createElement)(external_octane_namespaceObject.Suspense, {
92
194
  fallback: options.fallback,
@@ -32,21 +32,13 @@ __webpack_require__.d(__webpack_exports__, {
32
32
  });
33
33
  const external_octane_namespaceObject = require("octane");
34
34
  const external_context_js_namespaceObject = require("./context.js");
35
- const languageStateSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
36
- const languageSubscriptionSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
35
+ const languageStoreSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
37
36
  function I18nProvider(props) {
38
- const [language, setLanguage] = (0, external_octane_namespaceObject.useState)(()=>props.instance.language, languageStateSlot);
39
- (0, external_octane_namespaceObject.useEffect)(()=>{
40
- const instance = props.instance;
41
- setLanguage(instance.language);
42
- const handleLanguageChanged = (lng)=>setLanguage(lng);
43
- instance.on?.('languageChanged', handleLanguageChanged);
44
- return ()=>{
45
- instance.off?.('languageChanged', handleLanguageChanged);
46
- };
47
- }, [
48
- props.instance
49
- ], languageSubscriptionSlot);
37
+ const instance = props.instance;
38
+ const language = (0, external_octane_namespaceObject.useSyncExternalStore)((notify)=>{
39
+ instance.on?.('languageChanged', notify);
40
+ return ()=>instance.off?.('languageChanged', notify);
41
+ }, ()=>instance.language, ()=>instance.language, languageStoreSlot);
50
42
  const value = {
51
43
  instance: props.instance,
52
44
  languages: props.languages,
@@ -28,61 +28,52 @@ var __webpack_require__ = {};
28
28
  var __webpack_exports__ = {};
29
29
  __webpack_require__.r(__webpack_exports__);
30
30
  __webpack_require__.d(__webpack_exports__, {
31
- LocalizedLink: ()=>LocalizedLink,
32
- useIsLocalizedActive: ()=>useIsLocalizedActive
31
+ LocalizedLink: ()=>LocalizedLink
33
32
  });
34
33
  const paths_namespaceObject = require("@modern-js/i18n-runtime-extensions/paths");
35
34
  const external_octane_namespaceObject = require("octane");
36
35
  const external_router_js_namespaceObject = require("../router.js");
37
36
  const external_context_js_namespaceObject = require("./context.js");
38
- const locationSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
37
+ const targetLocationSlot = Symbol((0, external_octane_namespaceObject.hookSlots)(1));
39
38
  function LocalizedLink(props) {
40
39
  const context = (0, external_octane_namespaceObject.useContext)(external_context_js_namespaceObject.I18nContext);
41
40
  if (!context) throw new Error('[renderer-octane] LocalizedLink was used outside of an I18nProvider.');
42
41
  const router = (0, external_router_js_namespaceObject.useRouter)();
43
- const language = void 0 === props.language ? context.language : (0, paths_namespaceObject.configuredLanguage)(props.language, context.languages);
44
- const href = (0, paths_namespaceObject.localizePath)(props.to, language, {
42
+ const location = (0, external_router_js_namespaceObject.useLocation)(void 0, targetLocationSlot);
43
+ const { language: requestedLanguage, to, children, ...options } = props;
44
+ const language = void 0 === requestedLanguage ? context.language : (0, paths_namespaceObject.configuredLanguage)(requestedLanguage, context.languages);
45
+ const externalTarget = to.startsWith('//') || URL.canParse(to);
46
+ const pathname = externalTarget ? to : (0, paths_namespaceObject.localizePath)(router.buildLocation({
47
+ to,
48
+ from: options.from,
49
+ params: options.params,
50
+ unsafeRelative: options.unsafeRelative,
51
+ _fromLocation: location
52
+ }).pathname, language, {
45
53
  languages: [
46
54
  ...context.languages
47
55
  ],
48
56
  localisedUrls: context.localisedUrls
49
57
  });
50
- const crossLanguage = language !== context.language;
51
- const rewrite = Boolean(router.options.rewrite);
52
58
  return (0, external_octane_namespaceObject.createElement)(external_router_js_namespaceObject.Link, {
53
- to: rewrite ? props.to : href,
54
- ...rewrite && crossLanguage ? {
59
+ ...options,
60
+ to: router.options.rewrite ? to : pathname,
61
+ ...router.options.rewrite && !externalTarget ? {
55
62
  mask: {
56
- to: href
63
+ to: pathname,
64
+ inheritSearch: true,
65
+ hash: options.hash,
66
+ state: options.state
57
67
  }
58
68
  } : {},
59
- ...crossLanguage ? {
69
+ ...language === context.language ? {} : {
60
70
  hreflang: language
61
- } : {},
62
- class: props.class,
63
- activeProps: props.activeProps,
64
- inactiveProps: props.inactiveProps,
65
- activeOptions: props.activeOptions,
66
- replace: props.replace,
67
- preload: props.preload
68
- }, props.children);
69
- }
70
- function useIsLocalizedActive(canonicalTarget) {
71
- const context = (0, external_octane_namespaceObject.useContext)(external_context_js_namespaceObject.I18nContext);
72
- if (!context) throw new Error('[renderer-octane] useIsLocalizedActive was used outside of an I18nProvider.');
73
- const location = (0, external_router_js_namespaceObject.useLocation)(void 0, locationSlot);
74
- return (0, paths_namespaceObject.canonicalPath)(location.pathname, {
75
- languages: [
76
- ...context.languages
77
- ],
78
- localisedUrls: context.localisedUrls
79
- }) === canonicalTarget;
71
+ }
72
+ }, children);
80
73
  }
81
74
  exports.LocalizedLink = __webpack_exports__.LocalizedLink;
82
- exports.useIsLocalizedActive = __webpack_exports__.useIsLocalizedActive;
83
75
  for(var __rspack_i in __webpack_exports__)if (-1 === [
84
- "LocalizedLink",
85
- "useIsLocalizedActive"
76
+ "LocalizedLink"
86
77
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
87
78
  Object.defineProperty(exports, '__esModule', {
88
79
  value: true
@@ -40,7 +40,6 @@ __webpack_require__.d(__webpack_exports__, {
40
40
  readI18nSsrHandoff: ()=>ssrLanguageHandoff_namespaceObject.readI18nSsrHandoff,
41
41
  resolveRequestLanguage: ()=>request_language_namespaceObject.resolveRequestLanguage,
42
42
  useI18n: ()=>external_useI18n_js_namespaceObject.useI18n,
43
- useIsLocalizedActive: ()=>external_LocalizedLink_js_namespaceObject.useIsLocalizedActive,
44
43
  useLatestLanguageSync: ()=>external_languageSync_js_namespaceObject.useLatestLanguageSync
45
44
  });
46
45
  const request_language_namespaceObject = require("@modern-js/i18n-runtime-extensions/request-language");
@@ -63,7 +62,6 @@ exports.languageFromPathname = __webpack_exports__.languageFromPathname;
63
62
  exports.readI18nSsrHandoff = __webpack_exports__.readI18nSsrHandoff;
64
63
  exports.resolveRequestLanguage = __webpack_exports__.resolveRequestLanguage;
65
64
  exports.useI18n = __webpack_exports__.useI18n;
66
- exports.useIsLocalizedActive = __webpack_exports__.useIsLocalizedActive;
67
65
  exports.useLatestLanguageSync = __webpack_exports__.useLatestLanguageSync;
68
66
  for(var __rspack_i in __webpack_exports__)if (-1 === [
69
67
  "I18N_SSR_HANDOFF_ELEMENT_ID",
@@ -78,7 +76,6 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
78
76
  "readI18nSsrHandoff",
79
77
  "resolveRequestLanguage",
80
78
  "useI18n",
81
- "useIsLocalizedActive",
82
79
  "useLatestLanguageSync"
83
80
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
84
81
  Object.defineProperty(exports, '__esModule', {