@bleedingdev/modern-js-ultramodern-app-tools 3.9.3-ultramodern.8 → 3.9.3-ultramodern.9

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 (103) hide show
  1. package/dist/cjs/native-composition/config-metadata.js +75 -3
  2. package/dist/cjs/native-composition/module-federation-renderer-plugin.js +1 -1
  3. package/dist/cjs/native-composition/native-development.js +101 -7
  4. package/dist/cjs/native-composition/native-entry.js +84 -19
  5. package/dist/cjs/native-composition/native-federation-dev-assets.js +143 -10
  6. package/dist/cjs/native-composition/native-federation-dev-public-path.js +36 -0
  7. package/dist/cjs/native-composition/native-infrastructure.js +81 -1
  8. package/dist/cjs/native-composition/native-module-federation.js +109 -25
  9. package/dist/cjs/native-composition/native-routes.js +120 -5
  10. package/dist/cjs/native-composition/native-worker-context-profiles.js +112 -0
  11. package/dist/cjs/native-composition/native-worker-federation-config.js +215 -0
  12. package/dist/cjs/native-composition/native-worker-federation-policy.js +102 -0
  13. package/dist/cjs/native-composition/native-worker-federation.js +226 -0
  14. package/dist/cjs/native-composition/native-worker-publication.js +107 -0
  15. package/dist/cjs/native-composition/native-worker.js +37 -3
  16. package/dist/cjs/native-composition/renderer-installed-profile.js +61 -2
  17. package/dist/cjs/native-composition/renderer-selection.js +2 -1
  18. package/dist/cjs/native-composition/workspace-preset.js +19 -2
  19. package/dist/esm/native-composition/config-metadata.mjs +75 -3
  20. package/dist/esm/native-composition/module-federation-renderer-plugin.mjs +2 -2
  21. package/dist/esm/native-composition/native-development.mjs +102 -8
  22. package/dist/esm/native-composition/native-entry.mjs +85 -20
  23. package/dist/esm/native-composition/native-federation-dev-assets.mjs +124 -9
  24. package/dist/esm/native-composition/native-federation-dev-public-path.mjs +31 -1
  25. package/dist/esm/native-composition/native-infrastructure.mjs +81 -1
  26. package/dist/esm/native-composition/native-module-federation.mjs +108 -27
  27. package/dist/esm/native-composition/native-routes.mjs +110 -4
  28. package/dist/esm/native-composition/native-worker-context-profiles.mjs +63 -0
  29. package/dist/esm/native-composition/native-worker-federation-config.mjs +164 -0
  30. package/dist/esm/native-composition/native-worker-federation-policy.mjs +53 -0
  31. package/dist/esm/native-composition/native-worker-federation.mjs +166 -0
  32. package/dist/esm/native-composition/native-worker-publication.mjs +66 -0
  33. package/dist/esm/native-composition/native-worker.mjs +37 -3
  34. package/dist/esm/native-composition/renderer-installed-profile.mjs +54 -1
  35. package/dist/esm/native-composition/renderer-selection.mjs +2 -1
  36. package/dist/esm/native-composition/workspace-preset.mjs +19 -2
  37. package/dist/esm-node/native-composition/config-metadata.mjs +75 -3
  38. package/dist/esm-node/native-composition/module-federation-renderer-plugin.mjs +2 -2
  39. package/dist/esm-node/native-composition/native-development.mjs +102 -8
  40. package/dist/esm-node/native-composition/native-entry.mjs +85 -20
  41. package/dist/esm-node/native-composition/native-federation-dev-assets.mjs +124 -9
  42. package/dist/esm-node/native-composition/native-federation-dev-public-path.mjs +31 -1
  43. package/dist/esm-node/native-composition/native-infrastructure.mjs +81 -1
  44. package/dist/esm-node/native-composition/native-module-federation.mjs +108 -27
  45. package/dist/esm-node/native-composition/native-routes.mjs +110 -4
  46. package/dist/esm-node/native-composition/native-worker-context-profiles.mjs +64 -0
  47. package/dist/esm-node/native-composition/native-worker-federation-config.mjs +165 -0
  48. package/dist/esm-node/native-composition/native-worker-federation-policy.mjs +54 -0
  49. package/dist/esm-node/native-composition/native-worker-federation.mjs +167 -0
  50. package/dist/esm-node/native-composition/native-worker-publication.mjs +67 -0
  51. package/dist/esm-node/native-composition/native-worker.mjs +37 -3
  52. package/dist/esm-node/native-composition/renderer-installed-profile.mjs +54 -1
  53. package/dist/esm-node/native-composition/renderer-selection.mjs +2 -1
  54. package/dist/esm-node/native-composition/workspace-preset.mjs +19 -2
  55. package/dist/types/native-composition/config-metadata.d.ts +6 -0
  56. package/dist/types/native-composition/native-development.d.ts +6 -0
  57. package/dist/types/native-composition/native-entry.d.ts +1 -1
  58. package/dist/types/native-composition/native-federation-dev-assets.d.ts +26 -2
  59. package/dist/types/native-composition/native-federation-dev-public-path.d.ts +4 -0
  60. package/dist/types/native-composition/native-infrastructure.d.ts +10 -0
  61. package/dist/types/native-composition/native-module-federation.d.ts +8 -4
  62. package/dist/types/native-composition/native-routes.d.ts +11 -0
  63. package/dist/types/native-composition/native-worker-context-profiles.d.ts +2 -0
  64. package/dist/types/native-composition/native-worker-federation-config.d.ts +46 -0
  65. package/dist/types/native-composition/native-worker-federation-policy.d.ts +8 -0
  66. package/dist/types/native-composition/native-worker-federation.d.ts +57 -0
  67. package/dist/types/native-composition/native-worker-publication.d.ts +12 -0
  68. package/dist/types/native-composition/native-worker.d.ts +14 -1
  69. package/dist/types/native-composition/renderer-installed-profile.d.ts +6 -0
  70. package/dist/types-esm/native-composition/config-metadata.d.mts +6 -0
  71. package/dist/types-esm/native-composition/native-development.d.mts +6 -0
  72. package/dist/types-esm/native-composition/native-entry.d.mts +1 -1
  73. package/dist/types-esm/native-composition/native-federation-dev-assets.d.mts +26 -2
  74. package/dist/types-esm/native-composition/native-federation-dev-public-path.d.mts +4 -0
  75. package/dist/types-esm/native-composition/native-infrastructure.d.mts +10 -0
  76. package/dist/types-esm/native-composition/native-module-federation.d.mts +8 -4
  77. package/dist/types-esm/native-composition/native-routes.d.mts +11 -0
  78. package/dist/types-esm/native-composition/native-worker-context-profiles.d.mts +2 -0
  79. package/dist/types-esm/native-composition/native-worker-federation-config.d.mts +46 -0
  80. package/dist/types-esm/native-composition/native-worker-federation-policy.d.mts +8 -0
  81. package/dist/types-esm/native-composition/native-worker-federation.d.mts +57 -0
  82. package/dist/types-esm/native-composition/native-worker-publication.d.mts +12 -0
  83. package/dist/types-esm/native-composition/native-worker.d.mts +14 -1
  84. package/dist/types-esm/native-composition/renderer-installed-profile.d.mts +6 -0
  85. package/package.json +33 -32
  86. package/src/native-composition/config-metadata.ts +110 -11
  87. package/src/native-composition/module-federation-renderer-plugin.ts +6 -2
  88. package/src/native-composition/native-development.ts +187 -13
  89. package/src/native-composition/native-entry.ts +116 -21
  90. package/src/native-composition/native-federation-dev-assets.ts +237 -13
  91. package/src/native-composition/native-federation-dev-public-path.ts +69 -0
  92. package/src/native-composition/native-infrastructure.ts +164 -1
  93. package/src/native-composition/native-module-federation.ts +178 -55
  94. package/src/native-composition/native-routes.ts +167 -3
  95. package/src/native-composition/native-worker-context-profiles.ts +119 -0
  96. package/src/native-composition/native-worker-federation-config.ts +343 -0
  97. package/src/native-composition/native-worker-federation-policy.ts +119 -0
  98. package/src/native-composition/native-worker-federation.ts +401 -0
  99. package/src/native-composition/native-worker-publication.ts +151 -0
  100. package/src/native-composition/native-worker.ts +71 -3
  101. package/src/native-composition/renderer-installed-profile.ts +67 -0
  102. package/src/native-composition/renderer-selection.ts +3 -1
  103. package/src/native-composition/workspace-preset.ts +34 -4
@@ -47,8 +47,12 @@ const external_node_module_namespaceObject = require("node:module");
47
47
  const external_node_path_namespaceObject = require("node:path");
48
48
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
49
49
  const external_node_url_namespaceObject = require("node:url");
50
+ const cli_namespaceObject = require("@modern-js/plugin/cli");
50
51
  const core_namespaceObject = require("@rsbuild/core");
51
52
  const external_config_js_namespaceObject = require("./config.js");
53
+ const external_config_read_context_js_namespaceObject = require("./config-read-context.js");
54
+ const external_native_i18n_js_namespaceObject = require("./native-i18n.js");
55
+ const external_renderer_router_resolution_js_namespaceObject = require("./renderer-router-resolution.js");
52
56
  function inside(directory, file) {
53
57
  const relative = external_node_path_default().relative(directory, file);
54
58
  return '' !== relative && !relative.startsWith(`..${external_node_path_default().sep}`) && '..' !== relative && !external_node_path_default().isAbsolute(relative);
@@ -115,11 +119,76 @@ async function readUltramodernConfigMetadata(options) {
115
119
  appDirectory,
116
120
  configFile: options.configFile,
117
121
  env: options.env,
118
- command: options.command
122
+ command: options.analyzeServerRoutes ? 'metadata' : options.command
119
123
  });
124
+ const installedAppDirectory = options.stagedWorkspace && (appDirectory === external_node_path_default().resolve(options.stagedWorkspace.root) || inside(external_node_path_default().resolve(options.stagedWorkspace.root), appDirectory)) ? external_node_path_default().resolve(options.stagedWorkspace.originalRoot, external_node_path_default().relative(options.stagedWorkspace.root, appDirectory)) : appDirectory;
125
+ if (options.analyzeServerRoutes) {
126
+ const previousArgv = process.env.MODERN_ARGV;
127
+ process.env.MODERN_ARGV = 'node modern metadata';
128
+ const cli = (0, cli_namespaceObject.createCli)();
129
+ let cleanup;
130
+ try {
131
+ return await (0, external_config_read_context_js_namespaceObject.withEntryMetadataRead)(async ()=>{
132
+ const { appContext } = await cli.init({
133
+ cwd: appDirectory,
134
+ configFile: false,
135
+ config: loaded.config,
136
+ command: 'metadata',
137
+ internalPlugins: [
138
+ {
139
+ name: '@modern-js/ultramodern-route-metadata-context',
140
+ setup (api) {
141
+ api.updateAppContext({
142
+ configFile: loaded.configFile
143
+ });
144
+ cleanup = ()=>api.getHooks().onBeforeExit.call();
145
+ }
146
+ }
147
+ ]
148
+ });
149
+ const context = appContext.pluginAPI.getAppContext();
150
+ const entrypoints = context.entrypoints ?? [];
151
+ if (!entrypoints.length) throw new Error('UltraModern analyzed configuration has no application entries');
152
+ const entryBasePaths = {};
153
+ for (const entry of entrypoints){
154
+ const prefixes = [
155
+ ...new Set((context.serverRoutes ?? []).filter((route)=>route.entryName === entry.entryName && !route.isApi).map((route)=>route.urlPath))
156
+ ];
157
+ if (1 !== prefixes.length || 'string' != typeof prefixes[0]) throw new Error(`Native Worker federation entry ${entry.entryName} requires exactly one analyzed public route prefix.`);
158
+ entryBasePaths[entry.entryName] = prefixes[0];
159
+ }
160
+ const entries = entrypoints.map(({ entryName, isMainEntry })=>({
161
+ entryName,
162
+ isMainEntry
163
+ }));
164
+ const primary = entries.find((entry)=>entry.isMainEntry) ?? entries[0];
165
+ const renderer = loaded.config.renderer;
166
+ const routerBindings = await (0, external_renderer_router_resolution_js_namespaceObject.resolveEntrypointRouterBindings)(renderer, entrypoints, context.plugins.map((plugin)=>plugin.name), void 0, installedAppDirectory);
167
+ const i18n = (0, external_native_i18n_js_namespaceObject.findNativeI18nConfig)(loaded.config.plugins ?? []);
168
+ return {
169
+ renderer,
170
+ entries,
171
+ primaryEntryName: primary.entryName,
172
+ routerBindings,
173
+ entryBasePaths,
174
+ ...i18n ? {
175
+ i18n
176
+ } : {}
177
+ };
178
+ });
179
+ } finally{
180
+ try {
181
+ await cleanup?.();
182
+ } finally{
183
+ cli.dispose();
184
+ if (void 0 === previousArgv) delete process.env.MODERN_ARGV;
185
+ else process.env.MODERN_ARGV = previousArgv;
186
+ }
187
+ }
188
+ }
120
189
  const resolution = await (0, external_config_js_namespaceObject.resolveUltramodernEntryIdentities)({
121
190
  appDirectory,
122
- installedAppDirectory: options.stagedWorkspace && (appDirectory === external_node_path_default().resolve(options.stagedWorkspace.root) || inside(external_node_path_default().resolve(options.stagedWorkspace.root), appDirectory)) ? external_node_path_default().resolve(options.stagedWorkspace.originalRoot, external_node_path_default().relative(options.stagedWorkspace.root, appDirectory)) : appDirectory,
191
+ installedAppDirectory,
123
192
  config: loaded.config,
124
193
  command: options.command,
125
194
  configFile: loaded.configFile
@@ -150,7 +219,10 @@ function loadUltramodernConfigMetadata(options) {
150
219
  execArgv: [],
151
220
  env: {
152
221
  ...process.env,
153
- NODE_ENV: options.env
222
+ NODE_ENV: options.env,
223
+ ...options.analyzeServerRoutes ? {
224
+ MODERN_ARGV: 'node modern metadata'
225
+ } : {}
154
226
  },
155
227
  stdio: [
156
228
  'ignore',
@@ -83,7 +83,7 @@ function resolveRendererFederationCompatibility(renderer) {
83
83
  specifier: owners.package,
84
84
  filename: (0, external_node_module_namespaceObject.createRequire)(`${bootstrap.directory}/package.json`).resolve(owners.package)
85
85
  });
86
- const { protocolVersion, compiler, hydration, router } = metadata.profile;
86
+ const { protocolVersion, compiler, hydration, router } = (0, external_renderer_installed_profile_js_namespaceObject.projectInstalledFederationProfile)(metadata.profile, bootstrap);
87
87
  return (0, renderer_contract_namespaceObject.readRendererFederationCompatibility)({
88
88
  profile: {
89
89
  renderer,
@@ -56,6 +56,7 @@ const server_namespaceObject = require("@modern-js/renderer-core/server");
56
56
  const utils_namespaceObject = require("@modern-js/utils");
57
57
  const external_native_build_manifest_js_namespaceObject = require("./native-build-manifest.js");
58
58
  const external_native_federation_dev_assets_js_namespaceObject = require("./native-federation-dev-assets.js");
59
+ const external_native_federation_dev_public_path_js_namespaceObject = require("./native-federation-dev-public-path.js");
59
60
  const external_renderer_registration_js_namespaceObject = require("./renderer-registration.js");
60
61
  const allowsOrigin = (allowed, origin)=>Array.isArray(allowed) ? allowed.some((entry)=>allowsOrigin(entry, origin)) : allowed instanceof RegExp ? allowed.test(origin) : 'string' == typeof allowed ? allowed === origin : Boolean(allowed);
61
62
  async function applyDevServerHeaders(request, response, server) {
@@ -124,6 +125,15 @@ class NativeDevelopment {
124
125
  (0, identity_namespaceObject.assertRendererIdentity)(snapshot.manifest.rendererIdentity, identity);
125
126
  return snapshot;
126
127
  }
128
+ await this.waitForPublication(signal);
129
+ }
130
+ }
131
+ async waitForPublication(signal) {
132
+ for(;;){
133
+ signal.throwIfAborted();
134
+ if (this.closed) throw new Error('Native development compiler is closed');
135
+ if (this.failure) throw this.failure.error;
136
+ if (this.ready) return;
127
137
  await new Promise((resolve, reject)=>{
128
138
  const resumed = ()=>{
129
139
  signal.removeEventListener('abort', aborted);
@@ -150,11 +160,26 @@ class NativeDevelopment {
150
160
  if (!client?.compilation.hash || !server?.compilation.hash || !serverRoot) throw new Error('Native development requires completed client and server compilations');
151
161
  const session = this.options.getSessionIdentities();
152
162
  const entryNames = Object.keys(session.identities);
153
- const federationAssets = await (0, external_native_federation_dev_assets_js_namespaceObject.collectNativeFederationDevAssets)(server, entryNames, (name)=>emittedBytes(server, name));
163
+ const federationAssets = new Map([
164
+ ...await (0, external_native_federation_dev_assets_js_namespaceObject.collectNativeFederationDevAssets)(server, entryNames, (name)=>emittedBytes(server, name)),
165
+ ...await (0, external_native_federation_dev_assets_js_namespaceObject.collectNativeFederationDevAssets)(client, entryNames, (name)=>emittedBytes(client, name))
166
+ ]);
167
+ const federationGraph = (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevGraph)(client);
168
+ const federationRevision = federationAssets.size ? (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevRevision)(federationAssets) : void 0;
169
+ const retainedFederationAssets = (0, external_native_federation_dev_assets_js_namespaceObject.retainNativeFederationDevAssets)(this.retainedFederationAssets, new Map([
170
+ ...federationAssets
171
+ ].map(([url, asset])=>[
172
+ url,
173
+ {
174
+ ...asset,
175
+ revision: federationRevision,
176
+ graphManifest: federationGraph?.immutableManifest
177
+ }
178
+ ])));
154
179
  const publicPath = client.compilation.outputOptions.publicPath;
155
180
  const prefix = 'string' == typeof publicPath && 'auto' !== publicPath ? publicPath.endsWith('/') ? publicPath : `${publicPath}/` : '/';
156
181
  for (const asset of client.compilation.getAssets()){
157
- if (asset.info.hotModuleReplacement || this.mutableClientAssets.has(asset.name) || this.compilerArtifacts.isMutableDevelopmentAsset(asset.name, entryNames)) continue;
182
+ if (true !== asset.info.immutable || asset.info.hotModuleReplacement || this.mutableClientAssets.has(asset.name) || this.compilerArtifacts.isMutableDevelopmentAsset(asset.name, entryNames)) continue;
158
183
  const pathname = new URL(`${prefix}${asset.name}`, 'http://native-dev.invalid').pathname;
159
184
  if (!this.retained.has(pathname)) this.retained.set(pathname, {
160
185
  bytes: await emittedBytes(client, asset.name),
@@ -218,7 +243,10 @@ class NativeDevelopment {
218
243
  await promises_default().rename(temporary, manifestFile);
219
244
  return {
220
245
  entries,
221
- federationAssets
246
+ federationAssets,
247
+ federationGraph,
248
+ federationRevision,
249
+ retainedFederationAssets
222
250
  };
223
251
  }
224
252
  async close() {
@@ -228,6 +256,10 @@ class NativeDevelopment {
228
256
  this.notify();
229
257
  this.retained.clear();
230
258
  this.federationAssets = new Map();
259
+ this.federationRevision = void 0;
260
+ this.federationGraph = void 0;
261
+ this.federationCompilers.clear();
262
+ this.retainedFederationAssets = new Map();
231
263
  if (this.manifestFile) await promises_default().rm(this.manifestFile, {
232
264
  force: true
233
265
  });
@@ -241,6 +273,8 @@ class NativeDevelopment {
241
273
  this.closed = false;
242
274
  this.retained = new Map();
243
275
  this.federationAssets = new Map();
276
+ this.federationCompilers = new Set();
277
+ this.retainedFederationAssets = new Map();
244
278
  this.mutableClientAssets = new Set([
245
279
  'renderer-assets.json'
246
280
  ]);
@@ -279,16 +313,69 @@ class NativeDevelopment {
279
313
  config.mode = 'development';
280
314
  const previous = config.dev?.setupMiddlewares;
281
315
  const retain = (middlewares)=>{
282
- middlewares.unshift((request, response, next)=>{
316
+ const owner = this;
317
+ middlewares.unshift(function serve(request, response, next) {
318
+ if (owner.closed) return next();
283
319
  if ('GET' !== request.method && 'HEAD' !== request.method) return next();
284
320
  const pathname = URL.parse(request.url ?? '/', 'http://native-dev.invalid')?.pathname;
285
321
  const protocol = request.socket instanceof external_node_tls_namespaceObject.TLSSocket ? 'https:' : 'http:';
286
- const asset = (0, external_native_federation_dev_assets_js_namespaceObject.resolveNativeFederationDevAsset)(this.federationAssets, request.url ?? '/', `${protocol}//${request.headers.host}`) || pathname && this.retained.get(pathname);
322
+ const origin = `${protocol}//${request.headers.host}`;
323
+ if (!owner.federationGraph && [
324
+ ...owner.federationCompilers
325
+ ].some((compiler)=>{
326
+ const manifest = (0, external_native_federation_dev_assets_js_namespaceObject.nativeFederationDevManifest)(compiler);
327
+ return manifest && URL.parse(manifest)?.pathname === pathname;
328
+ })) {
329
+ const pending = new AbortController();
330
+ const aborted = ()=>pending.abort(new Error('Native manifest request closed'));
331
+ request.once('aborted', aborted);
332
+ response.once('close', aborted);
333
+ if (request.aborted || response.destroyed) aborted();
334
+ const cleanup = ()=>{
335
+ request.removeListener('aborted', aborted);
336
+ response.removeListener('close', aborted);
337
+ };
338
+ owner.waitForPublication(pending.signal).then(()=>{
339
+ cleanup();
340
+ if (pending.signal.aborted) return;
341
+ if (!owner.federationGraph) return next(new Error('Native browser manifest was not published'));
342
+ serve(request, response, next);
343
+ }, (error)=>{
344
+ cleanup();
345
+ if (!pending.signal.aborted) next(error);
346
+ });
347
+ return;
348
+ }
349
+ const hotUpdate = owner.federationGraph && (0, external_native_federation_dev_public_path_js_namespaceObject.nativeFederationDevHotUpdateTarget)(owner.federationGraph.publicPath, request.url ?? '/', origin);
350
+ if (hotUpdate) {
351
+ request.url = hotUpdate;
352
+ return next();
353
+ }
354
+ const federationAsset = (0, external_native_federation_dev_assets_js_namespaceObject.resolveNativeFederationDevAsset)(owner.federationAssets, request.url ?? '/', origin) ?? (owner.federationGraph && (0, external_native_federation_dev_assets_js_namespaceObject.resolveNativeFederationDevManifest)(owner.federationAssets, request.url ?? '/', owner.federationGraph.manifest));
355
+ const revision = owner.federationRevision;
356
+ const asset = federationAsset || pathname && owner.retained.get(pathname);
287
357
  if (!asset) return next();
288
358
  applyDevServerHeaders(request, response, api.getNormalizedConfig().server).then(()=>{
289
359
  response.setHeader('Content-Type', asset.contentType);
290
360
  response.setHeader('Content-Length', asset.bytes.length);
291
- response.setHeader('Cache-Control', 'no-store');
361
+ response.setHeader('Cache-Control', asset.immutable ? 'public, max-age=31536000, immutable' : 'no-store');
362
+ if (federationAsset) {
363
+ const graphManifest = asset.graphManifest ?? owner.federationGraph?.immutableManifest;
364
+ if (graphManifest) response.setHeader('Link', `<${graphManifest}>; rel="ultramodern-completed-graph"`);
365
+ const graphRevision = asset.revision ?? revision;
366
+ if (graphRevision) response.setHeader(external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER, graphRevision);
367
+ if (api.getNormalizedConfig().server.cors) {
368
+ const previous = response.getHeader('Access-Control-Expose-Headers');
369
+ const exposed = new Set([
370
+ ...Array.isArray(previous) ? previous : String(previous ?? '').split(','),
371
+ 'Link',
372
+ external_native_federation_dev_assets_js_namespaceObject.NATIVE_FEDERATION_DEV_REVISION_HEADER
373
+ ].map((value)=>value.trim()).filter(Boolean));
374
+ response.setHeader('Access-Control-Expose-Headers', [
375
+ ...exposed
376
+ ].join(','));
377
+ }
378
+ }
292
379
  response.end('HEAD' === request.method ? void 0 : asset.bytes);
293
380
  }, next);
294
381
  });
@@ -309,6 +396,7 @@ class NativeDevelopment {
309
396
  compiler
310
397
  ];
311
398
  for (const candidate of compilers){
399
+ this.federationCompilers.add(candidate);
312
400
  this.compilerVersions.set(candidate, 0);
313
401
  let runVersion = 0;
314
402
  const captureRun = ()=>{
@@ -343,7 +431,13 @@ class NativeDevelopment {
343
431
  try {
344
432
  const publication = await this.publish(stats);
345
433
  if (this.closed || epoch !== this.epoch) return;
346
- this.federationAssets = publication.federationAssets;
434
+ this.retainedFederationAssets = publication.retainedFederationAssets;
435
+ this.federationAssets = new Map([
436
+ ...publication.federationAssets,
437
+ ...this.retainedFederationAssets
438
+ ]);
439
+ this.federationRevision = publication.federationRevision;
440
+ this.federationGraph = publication.federationGraph;
347
441
  this.ready = publication.entries;
348
442
  this.failure = void 0;
349
443
  this.notify();
@@ -51,6 +51,8 @@ const external_native_federation_files_js_namespaceObject = require("./native-fe
51
51
  const external_native_i18n_js_namespaceObject = require("./native-i18n.js");
52
52
  const external_native_module_federation_js_namespaceObject = require("./native-module-federation.js");
53
53
  const external_native_routes_js_namespaceObject = require("./native-routes.js");
54
+ const external_native_worker_js_namespaceObject = require("./native-worker.js");
55
+ const external_native_worker_federation_js_namespaceObject = require("./native-worker-federation.js");
54
56
  const external_renderer_registration_js_namespaceObject = require("./renderer-registration.js");
55
57
  const entryRoutes = new WeakMap();
56
58
  function resolveNativeEntryIdentity(context, renderer) {
@@ -88,13 +90,18 @@ async function emitNativeEntryApplication(context, mode) {
88
90
  entryRoutes.set(context, discovery);
89
91
  }
90
92
  const routes = await discovery;
93
+ const sourceRequests = await (0, external_native_routes_js_namespaceObject.resolveNativeApplicationSourceRequests)(routes, context.profile.sourceExtensions, 'server' === mode ? 'node' : mode);
91
94
  if (context.i18n) (0, external_native_i18n_js_namespaceObject.validateNativeLocalisedUrls)(context.i18n, routes);
92
95
  sources[`app.${mode}.ts`] = (0, external_native_routes_js_namespaceObject.emitNativeApplicationModule)({
93
96
  routes,
94
- mode,
95
- basePath: context.basePath
97
+ mode: 'client' === mode ? 'client' : 'server',
98
+ basePath: context.basePath,
99
+ sourceRequests
96
100
  });
97
- } else sources[`app.${mode}.ts`] = `export { default } from ${JSON.stringify(source)};\n`;
101
+ } else {
102
+ const sourceRequest = await (0, external_native_routes_js_namespaceObject.resolveNativeApplicationSourceRequest)(source, context.profile.sourceExtensions, 'server' === mode ? 'node' : mode);
103
+ sources[`app.${mode}.ts`] = `export { default } from ${JSON.stringify(sourceRequest)};\n`;
104
+ }
98
105
  await writeNativeEntryModules(directory, sources);
99
106
  return {
100
107
  routed,
@@ -105,11 +112,36 @@ const NATIVE_APPLICATION_CLIENT_REQUEST = './app.client';
105
112
  function createNativeEntryStubGenerator(adapter) {
106
113
  const renderer = adapter.name;
107
114
  const extra = adapter.entryClient;
115
+ const serverSource = async (context, worker = false)=>{
116
+ const identity = resolveNativeEntryIdentity(context, renderer);
117
+ const { directory, routed } = await emitNativeEntryApplication(context, worker ? 'worker' : 'server');
118
+ const federated = Boolean(!worker && (0, external_native_federation_files_js_namespaceObject.findNativeFederationConfig)(context.appDirectory));
119
+ const server = `import { createNativeServerEntry } from ${JSON.stringify(adapter.runtime.entryServer)};
120
+ ${worker && !context.workerFederation?.plan ? workerContextStartup(context, routed) : ''}${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${federated ? nativeFederationDeclaration : ''}
121
+ export const { ${nativeServerHandlers.join(', ')} } = createNativeServerEntry({
122
+ identity: ${JSON.stringify(identity)},
123
+ app: () => import("./app.${worker ? 'worker' : 'server'}"),${worker && context.workerFederation ? `\n workerFederationLocale: ${JSON.stringify(context.i18n?.fallbackLanguage ?? 'default')},` : ''}${federated ? `\n federation: ${nativeServerFederationBinding},` : ''}${context.i18n ? '\n i18n,' : ''}
124
+ });
125
+ `;
126
+ if (!federated) return {
127
+ source: server,
128
+ directory,
129
+ routed
130
+ };
131
+ await writeNativeEntryModules(directory, {
132
+ 'handlers.server.ts': server
133
+ });
134
+ return {
135
+ source: federatedServerSource(identity),
136
+ directory,
137
+ routed
138
+ };
139
+ };
108
140
  return {
109
141
  async client (context) {
110
142
  const identity = resolveNativeEntryIdentity(context, renderer);
111
143
  const federated = Boolean((0, external_native_federation_files_js_namespaceObject.findNativeFederationConfig)(context.appDirectory));
112
- await emitNativeEntryApplication(context, 'client');
144
+ const { routed } = await emitNativeEntryApplication(context, 'client');
113
145
  const fields = {
114
146
  identity: JSON.stringify(identity),
115
147
  load: `() => import(${JSON.stringify(NATIVE_APPLICATION_CLIENT_REQUEST)})`,
@@ -120,34 +152,47 @@ function createNativeEntryStubGenerator(adapter) {
120
152
  ...federated ? {
121
153
  federation: nativeFederationBinding
122
154
  } : {},
155
+ ...context.workerFederation ? {
156
+ workerFederation: 'workerFederation'
157
+ } : {},
123
158
  ...extra?.fields
124
159
  };
125
160
  return `import { startNativeClient } from ${JSON.stringify(adapter.runtime.entryClient)};
126
- ${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${extra?.declarations ?? ''}${federated ? nativeFederationDeclaration : ''}
161
+ ${workerContextStartup(context, routed)}${context.workerFederation ? nativeWorkerClientTransportSource(context) : ''}${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${extra?.declarations ?? ''}${federated ? nativeFederationDeclaration : ''}
127
162
  startNativeClient({
128
163
  ${Object.entries(fields).map(([name, value])=>` ${name === value ? name : `${name}: ${value}`},`).join('\n')}
129
164
  });
130
165
  `;
131
166
  },
132
- async server (context) {
133
- const identity = resolveNativeEntryIdentity(context, renderer);
134
- const { directory } = await emitNativeEntryApplication(context, 'server');
135
- const federated = Boolean((0, external_native_federation_files_js_namespaceObject.findNativeFederationConfig)(context.appDirectory));
136
- const server = `import { createNativeServerEntry } from ${JSON.stringify(adapter.runtime.entryServer)};
137
- ${context.i18n ? 'import { i18n } from "./i18n";\n' : ''}${federated ? nativeFederationDeclaration : ''}
138
- export const { ${nativeServerHandlers.join(', ')} } = createNativeServerEntry({
139
- identity: ${JSON.stringify(identity)},
140
- app: () => import("./app.server"),${federated ? `\n federation: ${nativeServerFederationBinding},` : ''}${context.i18n ? '\n i18n,' : ''}
141
- });
142
- `;
143
- if (!federated) return server;
167
+ server: async (context)=>(await serverSource(context)).source,
168
+ async worker (context) {
169
+ const { source, directory, routed } = await serverSource(context, true);
170
+ const federation = context.workerFederation;
144
171
  await writeNativeEntryModules(directory, {
145
- 'handlers.server.ts': server
172
+ 'handlers.worker.ts': source,
173
+ ...federation?.plan ? {
174
+ 'federation.worker.ts': (0, external_native_worker_federation_js_namespaceObject.nativeWorkerFederationRegistrySource)(federation.plan, workerContextOptions(context, routed))
175
+ } : {}
146
176
  });
147
- return federatedServerSource(identity);
177
+ return (0, external_native_worker_js_namespaceObject.nativeWorkerEntrySource)('./handlers.worker', federation ? {
178
+ runtime: adapter.runtime.entryServer,
179
+ compatibility: federation.compatibility,
180
+ registry: federation.plan ? './federation.worker' : void 0
181
+ } : void 0);
148
182
  }
149
183
  };
150
184
  }
185
+ function workerContextOptions(context, routed) {
186
+ return 'octane' === context.renderer && context.workerFederation ? {
187
+ router: routed,
188
+ i18n: Boolean(context.i18n),
189
+ contextProfiles: context.workerFederation.contextProfiles
190
+ } : {};
191
+ }
192
+ function workerContextStartup(context, routed) {
193
+ const source = (0, external_native_worker_federation_js_namespaceObject.nativeWorkerContextStartupSource)(workerContextOptions(context, routed));
194
+ return source ? `${source}\n` : '';
195
+ }
151
196
  const nativeFederationBinding = '{ instance: () => __webpack_require__.federation.instance }';
152
197
  const nativeServerFederationBinding = `{ instance: () => __webpack_require__.federation.instance, hydrationModule: ${JSON.stringify(external_native_module_federation_js_namespaceObject.NATIVE_FEDERATION_HYDRATION_MODULE)} }`;
153
198
  const nativeFederationDeclaration = 'declare const __webpack_require__: { federation: { instance: import("@modern-js/renderer-core/federation").FederationInstance } };\n';
@@ -169,6 +214,26 @@ ${nativeServerHandlers.slice(1).map((name)=>`export async function ${name}(reque
169
214
  function createNativeEntryGenerator(renderer) {
170
215
  return createNativeEntryStubGenerator((0, external_renderer_registration_js_namespaceObject.resolveNativeRendererAdapter)(renderer));
171
216
  }
217
+ function nativeWorkerClientTransportSource(context) {
218
+ const federation = context.workerFederation;
219
+ return `import { createWorkerFederationTransport } from '@modern-js/renderer-core/worker-federation';
220
+ import { assertRendererFederationCompatibility, readRendererFederationContract } from '@modern-js/federation-runtime/renderer-contract';
221
+ const expectedWorkerRenderer = ${JSON.stringify(federation.compatibility)};
222
+ const workerFederation = signal => ({
223
+ locale: ${JSON.stringify(context.i18n?.fallbackLanguage ?? 'default')},
224
+ signal,
225
+ transport: createWorkerFederationTransport({
226
+ signal,
227
+ services: ${JSON.stringify(federation.services)}.map(service => ({...service, fetch: request => globalThis.fetch(request)})),
228
+ admitRendererContract(value) {
229
+ const contract = readRendererFederationContract(value);
230
+ assertRendererFederationCompatibility(expectedWorkerRenderer, contract);
231
+ return contract;
232
+ },
233
+ }),
234
+ });
235
+ `;
236
+ }
172
237
  exports.NATIVE_APPLICATION_CLIENT_REQUEST = __webpack_exports__.NATIVE_APPLICATION_CLIENT_REQUEST;
173
238
  exports.createNativeEntryGenerator = __webpack_exports__.createNativeEntryGenerator;
174
239
  exports.createNativeEntryStubGenerator = __webpack_exports__.createNativeEntryStubGenerator;