@bleedingdev/modern-js-ultramodern-app-tools 3.9.3-ultramodern.3 → 3.9.3-ultramodern.5

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 (36) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/native-composition/native-infrastructure.js +11 -1
  3. package/dist/cjs/native-composition/preset.js +29 -19
  4. package/dist/cjs/native-composition/renderer-build-resolution.js +5 -1
  5. package/dist/cjs/native-composition/renderer-release-identity.js +95 -0
  6. package/dist/cjs/native-composition/workspace-preset.js +10 -7
  7. package/dist/cjs/renderers/react/build-metadata.js +2 -43
  8. package/dist/cjs/renderers/react/ssr-integration-plugin.js +11 -3
  9. package/dist/esm/native-composition/native-infrastructure.mjs +11 -1
  10. package/dist/esm/native-composition/preset.mjs +25 -18
  11. package/dist/esm/native-composition/renderer-build-resolution.mjs +5 -1
  12. package/dist/esm/native-composition/renderer-release-identity.mjs +54 -0
  13. package/dist/esm/native-composition/workspace-preset.mjs +10 -7
  14. package/dist/esm/renderers/react/build-metadata.mjs +2 -43
  15. package/dist/esm/renderers/react/ssr-integration-plugin.mjs +11 -3
  16. package/dist/esm-node/native-composition/native-infrastructure.mjs +11 -1
  17. package/dist/esm-node/native-composition/preset.mjs +25 -18
  18. package/dist/esm-node/native-composition/renderer-build-resolution.mjs +5 -1
  19. package/dist/esm-node/native-composition/renderer-release-identity.mjs +55 -0
  20. package/dist/esm-node/native-composition/workspace-preset.mjs +10 -7
  21. package/dist/esm-node/renderers/react/build-metadata.mjs +2 -43
  22. package/dist/esm-node/renderers/react/ssr-integration-plugin.mjs +11 -3
  23. package/dist/types/native-composition/preset.d.ts +10 -1
  24. package/dist/types/native-composition/renderer-release-identity.d.ts +11 -0
  25. package/dist/types-esm/native-composition/preset.d.mts +10 -1
  26. package/dist/types-esm/native-composition/renderer-release-identity.d.mts +11 -0
  27. package/lib/build-target.d.ts +17 -0
  28. package/lib/react-types.d.ts +1 -0
  29. package/package.json +30 -30
  30. package/src/native-composition/native-infrastructure.ts +12 -1
  31. package/src/native-composition/preset.ts +44 -27
  32. package/src/native-composition/renderer-build-resolution.ts +6 -1
  33. package/src/native-composition/renderer-release-identity.ts +78 -0
  34. package/src/native-composition/workspace-preset.ts +31 -20
  35. package/src/renderers/react/build-metadata.ts +3 -49
  36. package/src/renderers/react/ssr-integration-plugin.ts +14 -4
package/README.md CHANGED
@@ -142,7 +142,9 @@ export default defineConfig(
142
142
  The workspace preset reads `topology/reference-topology.json` and
143
143
  `topology/local-overlays/development.json` relative to that config. Those records
144
144
  provide app identity, renderer, development ports, composed remote references
145
- and delivery unit identity. An authored `renderer` must match the topology.
145
+ and delivery unit identity. An authored `renderer` must match the topology. A
146
+ headless (API-only) unit declares renderer `none` and no Module Federation
147
+ name; its config selects no `renderer`.
146
148
  Adding a shell or vertical changes the records; existing application configs
147
149
  keep their authored contents.
148
150
 
@@ -61,6 +61,7 @@ const external_native_i18n_js_namespaceObject = require("./native-i18n.js");
61
61
  const external_native_worker_js_namespaceObject = require("./native-worker.js");
62
62
  const external_renderer_profile_js_namespaceObject = require("./renderer-profile.js");
63
63
  const external_renderer_registration_js_namespaceObject = require("./renderer-registration.js");
64
+ const external_renderer_release_identity_js_namespaceObject = require("./renderer-release-identity.js");
64
65
  const external_server_plugin_resolution_js_namespaceObject = require("./server-plugin-resolution.js");
65
66
  async function findSource(directory, name, extensions) {
66
67
  for (const extension of extensions){
@@ -148,7 +149,15 @@ function nativeRendererInfrastructurePlugin(renderer, generator, options = {}) {
148
149
  }
149
150
  if (options.resolveBuildIdentities && !metadataRead) api.modifyResolvedConfig((config)=>{
150
151
  const { command, apiOnly } = api.getAppContext();
151
- if ('dev' !== command || apiOnly) return config;
152
+ if (apiOnly) return config;
153
+ const identity = (0, external_renderer_release_identity_js_namespaceObject.rendererReleaseIdentityBuilderPlugin)(()=>buildIdentities);
154
+ if ('dev' !== command) return {
155
+ ...config,
156
+ builderPlugins: [
157
+ ...config.builderPlugins ?? [],
158
+ identity
159
+ ]
160
+ };
152
161
  development ??= new external_native_development_js_namespaceObject.NativeDevelopment({
153
162
  renderer,
154
163
  profile,
@@ -165,6 +174,7 @@ function nativeRendererInfrastructurePlugin(renderer, generator, options = {}) {
165
174
  ...config,
166
175
  builderPlugins: [
167
176
  ...config.builderPlugins ?? [],
177
+ identity,
168
178
  development.plugin
169
179
  ]
170
180
  };
@@ -41,7 +41,8 @@ __webpack_require__.d(__webpack_exports__, {
41
41
  createPresetUltramodernConfig: ()=>createPresetUltramodernConfig,
42
42
  isUltramodernReleaseIdentityBannerPlugin: ()=>isUltramodernReleaseIdentityBannerPlugin,
43
43
  presetUltramodern: ()=>presetUltramodern,
44
- releaseIdentityBanner: ()=>releaseIdentityBanner
44
+ releaseIdentityBanner: ()=>releaseIdentityBanner,
45
+ ultramodernReleaseIdentityBannerPlugin: ()=>ultramodernReleaseIdentityBannerPlugin
45
46
  });
46
47
  const external_node_fs_namespaceObject = require("node:fs");
47
48
  var external_node_fs_default = /*#__PURE__*/ __webpack_require__.n(external_node_fs_namespaceObject);
@@ -68,6 +69,20 @@ class UltramodernReleaseIdentityBannerPlugin extends core_namespaceObject.rspack
68
69
  }
69
70
  }
70
71
  const releaseIdentityBanner = (values)=>values.map((value)=>`${JSON.stringify(value)};`).join('');
72
+ const ultramodernReleaseIdentityBannerPlugin = (values)=>({
73
+ name: 'ultramodern:release-identity-banner',
74
+ setup (api) {
75
+ api.modifyRspackConfig((config)=>{
76
+ config.plugins ??= [];
77
+ config.plugins.push(new UltramodernReleaseIdentityBannerPlugin({
78
+ banner: releaseIdentityBanner(values),
79
+ raw: true,
80
+ stage: core_namespaceObject.rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
81
+ test: /\.(?:c|m)?js$/u
82
+ }));
83
+ });
84
+ }
85
+ });
71
86
  function isUltramodernReleaseIdentityBannerPlugin(plugin) {
72
87
  return 'object' == typeof plugin && null !== plugin && Object.getOwnPropertyDescriptor(plugin, RELEASE_IDENTITY_BANNER)?.value === true;
73
88
  }
@@ -138,6 +153,15 @@ const createRendererPreset = (options = {}, renderer = 'react')=>{
138
153
  (0, module_federation_shared_plugin_js_namespaceObject.ultramodernModuleFederationSharedPlugin)()
139
154
  ]
140
155
  } : {},
156
+ ...bundledReleaseIdentity ? {
157
+ builderPlugins: [
158
+ ultramodernReleaseIdentityBannerPlugin([
159
+ bundledReleaseIdentity.buildMarker,
160
+ bundledReleaseIdentity.sourceRevision,
161
+ bundledReleaseIdentity.releaseVersion
162
+ ])
163
+ ]
164
+ } : {},
141
165
  server,
142
166
  source: {
143
167
  ...'react' === renderer ? {
@@ -156,23 +180,7 @@ const createRendererPreset = (options = {}, renderer = 'react')=>{
156
180
  bundlerChain: (chain, utils)=>{
157
181
  if ('react' === renderer) setReactRouterBridgeSafeAliases(chain, utils);
158
182
  },
159
- lightningcssLoader: true,
160
- ...bundledReleaseIdentity ? {
161
- rspack: (config)=>{
162
- config.plugins ??= [];
163
- config.plugins.push(new UltramodernReleaseIdentityBannerPlugin({
164
- banner: releaseIdentityBanner([
165
- bundledReleaseIdentity.buildMarker,
166
- bundledReleaseIdentity.sourceRevision,
167
- bundledReleaseIdentity.releaseVersion
168
- ]),
169
- raw: true,
170
- stage: core_namespaceObject.rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
171
- test: /\.(?:c|m)?js$/u
172
- }));
173
- return config;
174
- }
175
- } : {}
183
+ lightningcssLoader: true
176
184
  }
177
185
  };
178
186
  if (enableBffRequestId) presetConfig.bff = {
@@ -198,12 +206,14 @@ exports.createPresetUltramodernConfig = __webpack_exports__.createPresetUltramod
198
206
  exports.isUltramodernReleaseIdentityBannerPlugin = __webpack_exports__.isUltramodernReleaseIdentityBannerPlugin;
199
207
  exports.presetUltramodern = __webpack_exports__.presetUltramodern;
200
208
  exports.releaseIdentityBanner = __webpack_exports__.releaseIdentityBanner;
209
+ exports.ultramodernReleaseIdentityBannerPlugin = __webpack_exports__.ultramodernReleaseIdentityBannerPlugin;
201
210
  for(var __rspack_i in __webpack_exports__)if (-1 === [
202
211
  "UltramodernReleaseIdentityBannerPlugin",
203
212
  "createPresetUltramodernConfig",
204
213
  "isUltramodernReleaseIdentityBannerPlugin",
205
214
  "presetUltramodern",
206
- "releaseIdentityBanner"
215
+ "releaseIdentityBanner",
216
+ "ultramodernReleaseIdentityBannerPlugin"
207
217
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
208
218
  Object.defineProperty(exports, '__esModule', {
209
219
  value: true
@@ -50,7 +50,11 @@ function createRendererBuildIdentityResolver(renderer) {
50
50
  mode: context.mode ?? ('production' === process.env.NODE_ENV ? 'production' : 'development'),
51
51
  ...delivery ? {
52
52
  appId: delivery.appId,
53
- sourceRevision: delivery.sourceRevision
53
+ deliveryUnit: {
54
+ unitId: delivery.unitId,
55
+ buildMarker: delivery.buildMarker,
56
+ sourceRevision: delivery.sourceRevision
57
+ }
54
58
  } : {
55
59
  appId: context.packageName || void 0
56
60
  }
@@ -0,0 +1,95 @@
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
+ applyRendererReleaseIdentity: ()=>applyRendererReleaseIdentity,
32
+ rendererReleaseIdentityBuilderPlugin: ()=>rendererReleaseIdentityBuilderPlugin
33
+ });
34
+ const core_namespaceObject = require("@rsbuild/core");
35
+ const external_preset_js_namespaceObject = require("./preset.js");
36
+ function applyRendererReleaseIdentity(api, getIdentities) {
37
+ api.modifyBundlerChain({
38
+ order: 'post',
39
+ handler: (chain)=>{
40
+ const identities = getIdentities();
41
+ if (!identities) return;
42
+ if (chain.plugins.has('globalVars')) chain.plugin('globalVars').tap((args)=>{
43
+ const definitions = {
44
+ ...args[0]
45
+ };
46
+ delete definitions.ULTRAMODERN_BUILD_MARKER;
47
+ delete definitions.ULTRAMODERN_SOURCE_REVISION;
48
+ return [
49
+ definitions,
50
+ ...args.slice(1)
51
+ ];
52
+ });
53
+ chain.plugin('ultramodern-renderer-runtime-identity').use(core_namespaceObject.rspack.DefinePlugin, [
54
+ {
55
+ ULTRAMODERN_BUILD_MARKER: JSON.stringify(identities.buildId),
56
+ ULTRAMODERN_SOURCE_REVISION: JSON.stringify(identities.sourceRevision)
57
+ }
58
+ ]);
59
+ }
60
+ });
61
+ api.modifyRspackConfig({
62
+ order: 'post',
63
+ handler: (config)=>{
64
+ const identities = getIdentities();
65
+ if (!identities) return config;
66
+ const { buildId, sourceRevision } = identities;
67
+ config.plugins = (config.plugins ?? []).filter((plugin)=>!(0, external_preset_js_namespaceObject.isUltramodernReleaseIdentityBannerPlugin)(plugin));
68
+ config.plugins.push(new core_namespaceObject.rspack.BannerPlugin({
69
+ banner: (0, external_preset_js_namespaceObject.releaseIdentityBanner)([
70
+ buildId,
71
+ sourceRevision
72
+ ]),
73
+ raw: true,
74
+ stage: core_namespaceObject.rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
75
+ test: /\.(?:c|m)?js$/u
76
+ }));
77
+ return config;
78
+ }
79
+ });
80
+ }
81
+ const rendererReleaseIdentityBuilderPlugin = (getIdentities)=>({
82
+ name: 'ultramodern:renderer-release-identity',
83
+ setup (api) {
84
+ applyRendererReleaseIdentity(api, getIdentities);
85
+ }
86
+ });
87
+ exports.applyRendererReleaseIdentity = __webpack_exports__.applyRendererReleaseIdentity;
88
+ exports.rendererReleaseIdentityBuilderPlugin = __webpack_exports__.rendererReleaseIdentityBuilderPlugin;
89
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
90
+ "applyRendererReleaseIdentity",
91
+ "rendererReleaseIdentityBuilderPlugin"
92
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
93
+ Object.defineProperty(exports, '__esModule', {
94
+ value: true
95
+ });
@@ -196,7 +196,8 @@ const resolveWorkspaceConfig = (config, options)=>{
196
196
  if (app.package !== packageManifest.name || app.deliveryUnit?.packageName !== packageManifest.name) throw new Error(`[ultramodern-workspace] Package identity for ${options.appId} does not match topology.`);
197
197
  if (app.deliveryUnit?.version !== packageManifest.version) throw new Error(`[ultramodern-workspace] Delivery unit version for ${options.appId} does not match package.json.`);
198
198
  const declaredRenderer = app.renderer;
199
- if (void 0 !== declaredRenderer && void 0 !== config.renderer && config.renderer !== declaredRenderer) throw new Error(`[ultramodern-workspace] Renderer for ${options.appId} does not match topology.`);
199
+ const headless = 'api-only' === app.surfaceProfile || 'none' === declaredRenderer;
200
+ if (headless && void 0 !== config.renderer || void 0 !== declaredRenderer && void 0 !== config.renderer && config.renderer !== declaredRenderer) throw new Error(`[ultramodern-workspace] Renderer for ${options.appId} does not match topology${headless ? ': a headless unit selects no renderer' : ''}.`);
200
201
  const portEnv = portEnvironment(app);
201
202
  const port = developmentPort(environment[portEnv] ?? overlay.ports[options.appId], options.appId);
202
203
  const allowedOrigins = Object.entries(overlay.ports).map(([id, defaultPort])=>{
@@ -243,9 +244,9 @@ const resolveWorkspaceConfig = (config, options)=>{
243
244
  binding
244
245
  ] : [];
245
246
  });
246
- const mfName = requiredString(app.moduleFederation?.name, `${options.appId}.moduleFederation.name`);
247
+ const mfName = headless ? void 0 : requiredString(app.moduleFederation?.name, `${options.appId}.moduleFederation.name`);
247
248
  const workspaceConfig = {
248
- ...void 0 !== declaredRenderer ? {
249
+ ...!headless && void 0 !== declaredRenderer ? {
249
250
  renderer: declaredRenderer
250
251
  } : {},
251
252
  ...cloudflare ? {
@@ -301,7 +302,7 @@ const resolveWorkspaceConfig = (config, options)=>{
301
302
  ...dynamicRemotes.size > 0 ? [
302
303
  dynamicCloudflareServicesPlugin(referencedRemotes, dynamicRemotes, workspaceRoot, environment, services)
303
304
  ] : [],
304
- ...'api-only' === app.surfaceProfile ? [] : [
305
+ ...headless ? [] : [
305
306
  zephyrBuildPlugin(configFilename, environment)
306
307
  ]
307
308
  ],
@@ -327,9 +328,11 @@ const resolveWorkspaceConfig = (config, options)=>{
327
328
  'defaults'
328
329
  ]
329
330
  },
330
- bundlerChain: (chain)=>{
331
- chain.output.uniqueName(mfName).chunkLoadingGlobal(`__ULTRAMODERN_${envSegment(mfName)}_LOADED_CHUNKS__`);
332
- },
331
+ ...mfName ? {
332
+ bundlerChain: (chain)=>{
333
+ chain.output.uniqueName(mfName).chunkLoadingGlobal(`__ULTRAMODERN_${envSegment(mfName)}_LOADED_CHUNKS__`);
334
+ }
335
+ } : {},
333
336
  devServer: {
334
337
  headers: {
335
338
  'Access-Control-Allow-Headers': 'Accept, Authorization, Content-Type, X-Requested-With',
@@ -54,11 +54,10 @@ const renderer_build_identity_namespaceObject = require("@modern-js/app-tools-ex
54
54
  const runtime_package_resolution_namespaceObject = require("@modern-js/app-tools-extensions/runtime-package-resolution");
55
55
  const data_namespaceObject = require("@modern-js/renderer-core/data");
56
56
  const utils_namespaceObject = require("@modern-js/utils");
57
- const core_namespaceObject = require("@rsbuild/core");
58
57
  const config_read_context_js_namespaceObject = require("../../native-composition/config-read-context.js");
59
58
  const native_build_manifest_js_namespaceObject = require("../../native-composition/native-build-manifest.js");
60
- const preset_js_namespaceObject = require("../../native-composition/preset.js");
61
59
  const renderer_profile_js_namespaceObject = require("../../native-composition/renderer-profile.js");
60
+ const renderer_release_identity_js_namespaceObject = require("../../native-composition/renderer-release-identity.js");
62
61
  const external_adapter_js_namespaceObject = require("./adapter.js");
63
62
  const REACT_RENDERER_IDENTITY_ELEMENT_ID = 'ultramodern-renderer-identity';
64
63
  async function resolveReactMetadataServerPlugin(registrarUrl = __rslib_import_meta_url__) {
@@ -120,47 +119,7 @@ function reactRendererBuildMetadataPlugin(options) {
120
119
  };
121
120
  }
122
121
  });
123
- api.modifyBundlerChain({
124
- order: 'post',
125
- handler: (chain)=>{
126
- if (!identities) return;
127
- if (chain.plugins.has('globalVars')) chain.plugin('globalVars').tap((args)=>{
128
- const definitions = {
129
- ...args[0]
130
- };
131
- delete definitions.ULTRAMODERN_BUILD_MARKER;
132
- delete definitions.ULTRAMODERN_SOURCE_REVISION;
133
- return [
134
- definitions,
135
- ...args.slice(1)
136
- ];
137
- });
138
- chain.plugin('ultramodern-react-runtime-identity').use(core_namespaceObject.rspack.DefinePlugin, [
139
- {
140
- ULTRAMODERN_BUILD_MARKER: JSON.stringify(identities.buildId),
141
- ULTRAMODERN_SOURCE_REVISION: JSON.stringify(identities.sourceRevision)
142
- }
143
- ]);
144
- }
145
- });
146
- api.modifyRspackConfig({
147
- order: 'post',
148
- handler: (config)=>{
149
- if (!identities) return config;
150
- const { buildId, sourceRevision } = identities;
151
- config.plugins = (config.plugins ?? []).filter((plugin)=>!(0, preset_js_namespaceObject.isUltramodernReleaseIdentityBannerPlugin)(plugin));
152
- config.plugins.push(new core_namespaceObject.rspack.BannerPlugin({
153
- banner: (0, preset_js_namespaceObject.releaseIdentityBanner)([
154
- buildId,
155
- sourceRevision
156
- ]),
157
- raw: true,
158
- stage: core_namespaceObject.rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
159
- test: /\.(?:c|m)?js$/u
160
- }));
161
- return config;
162
- }
163
- });
122
+ (0, renderer_release_identity_js_namespaceObject.applyRendererReleaseIdentity)(api, ()=>identities);
164
123
  api.modifyHTMLTags((tags, { filename, environment })=>{
165
124
  if ('client' !== environment.name) return tags;
166
125
  const entries = Object.entries(environment.htmlPaths).filter(([, output])=>output === filename);
@@ -38,6 +38,8 @@ const normalizeSsrCapabilities = (config)=>{
38
38
  worker: config.deploy?.target === 'cloudflare'
39
39
  };
40
40
  };
41
+ const MODERN_TARGET_DEFINE = 'process.env.MODERN_TARGET';
42
+ const IMPORT_META_MODERN_TARGET_DEFINE = 'import.meta.env.MODERN_TARGET';
41
43
  const ssrIntegrationBuilderPlugin = (modernAPI)=>({
42
44
  name: '@modern-js/ultramodern-builder-plugin-ssr',
43
45
  pre: [
@@ -45,10 +47,15 @@ const ssrIntegrationBuilderPlugin = (modernAPI)=>({
45
47
  ],
46
48
  setup (api) {
47
49
  const capabilities = normalizeSsrCapabilities(modernAPI.getNormalizedConfig());
48
- api.modifyEnvironmentConfig((config, { name, mergeEnvironmentConfig })=>mergeEnvironmentConfig(config, {
50
+ api.modifyEnvironmentConfig((config, { name, mergeEnvironmentConfig })=>{
51
+ const buildTarget = config.source.define?.[MODERN_TARGET_DEFINE];
52
+ return mergeEnvironmentConfig(config, {
49
53
  source: {
50
54
  define: {
51
- 'process.env.MODERN_MF_APP_SSR': JSON.stringify(String(capabilities.federation))
55
+ 'process.env.MODERN_MF_APP_SSR': JSON.stringify(String(capabilities.federation)),
56
+ ...void 0 === buildTarget ? {} : {
57
+ [IMPORT_META_MODERN_TARGET_DEFINE]: buildTarget
58
+ }
52
59
  }
53
60
  },
54
61
  ...'workerSSR' === name && capabilities.worker ? {
@@ -56,7 +63,8 @@ const ssrIntegrationBuilderPlugin = (modernAPI)=>({
56
63
  module: true
57
64
  }
58
65
  } : {}
59
- }));
66
+ });
67
+ });
60
68
  }
61
69
  });
62
70
  const ultramodernSSRIntegrationPlugin = ()=>({
@@ -14,6 +14,7 @@ import { resolveNativeI18nEntry } from "./native-i18n.mjs";
14
14
  import { isNativeWorkerBuild, nativeWorkerEntrySource, nativeWorkerEnvironment, writeNativeWorkerResources } from "./native-worker.mjs";
15
15
  import { resolveCandidateRendererProfile, resolveRendererProfile } from "./renderer-profile.mjs";
16
16
  import { nativeInfrastructurePluginName, resolveNativeRendererAdapter } from "./renderer-registration.mjs";
17
+ import { rendererReleaseIdentityBuilderPlugin } from "./renderer-release-identity.mjs";
17
18
  import { resolveSdkServerPlugin } from "./server-plugin-resolution.mjs";
18
19
  async function findSource(directory, name, extensions) {
19
20
  for (const extension of extensions){
@@ -101,7 +102,15 @@ function nativeRendererInfrastructurePlugin(renderer, generator, options = {}) {
101
102
  }
102
103
  if (options.resolveBuildIdentities && !metadataRead) api.modifyResolvedConfig((config)=>{
103
104
  const { command, apiOnly } = api.getAppContext();
104
- if ('dev' !== command || apiOnly) return config;
105
+ if (apiOnly) return config;
106
+ const identity = rendererReleaseIdentityBuilderPlugin(()=>buildIdentities);
107
+ if ('dev' !== command) return {
108
+ ...config,
109
+ builderPlugins: [
110
+ ...config.builderPlugins ?? [],
111
+ identity
112
+ ]
113
+ };
105
114
  development ??= new NativeDevelopment({
106
115
  renderer,
107
116
  profile,
@@ -118,6 +127,7 @@ function nativeRendererInfrastructurePlugin(renderer, generator, options = {}) {
118
127
  ...config,
119
128
  builderPlugins: [
120
129
  ...config.builderPlugins ?? [],
130
+ identity,
121
131
  development.plugin
122
132
  ]
123
133
  };
@@ -21,6 +21,20 @@ class UltramodernReleaseIdentityBannerPlugin extends rspack.BannerPlugin {
21
21
  }
22
22
  }
23
23
  const releaseIdentityBanner = (values)=>values.map((value)=>`${JSON.stringify(value)};`).join('');
24
+ const ultramodernReleaseIdentityBannerPlugin = (values)=>({
25
+ name: 'ultramodern:release-identity-banner',
26
+ setup (api) {
27
+ api.modifyRspackConfig((config)=>{
28
+ config.plugins ??= [];
29
+ config.plugins.push(new UltramodernReleaseIdentityBannerPlugin({
30
+ banner: releaseIdentityBanner(values),
31
+ raw: true,
32
+ stage: rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
33
+ test: /\.(?:c|m)?js$/u
34
+ }));
35
+ });
36
+ }
37
+ });
24
38
  function isUltramodernReleaseIdentityBannerPlugin(plugin) {
25
39
  return 'object' == typeof plugin && null !== plugin && Object.getOwnPropertyDescriptor(plugin, RELEASE_IDENTITY_BANNER)?.value === true;
26
40
  }
@@ -91,6 +105,15 @@ const createRendererPreset = (options = {}, renderer = 'react')=>{
91
105
  ultramodernModuleFederationSharedPlugin()
92
106
  ]
93
107
  } : {},
108
+ ...bundledReleaseIdentity ? {
109
+ builderPlugins: [
110
+ ultramodernReleaseIdentityBannerPlugin([
111
+ bundledReleaseIdentity.buildMarker,
112
+ bundledReleaseIdentity.sourceRevision,
113
+ bundledReleaseIdentity.releaseVersion
114
+ ])
115
+ ]
116
+ } : {},
94
117
  server,
95
118
  source: {
96
119
  ...'react' === renderer ? {
@@ -109,23 +132,7 @@ const createRendererPreset = (options = {}, renderer = 'react')=>{
109
132
  bundlerChain: (chain, utils)=>{
110
133
  if ('react' === renderer) setReactRouterBridgeSafeAliases(chain, utils);
111
134
  },
112
- lightningcssLoader: true,
113
- ...bundledReleaseIdentity ? {
114
- rspack: (config)=>{
115
- config.plugins ??= [];
116
- config.plugins.push(new UltramodernReleaseIdentityBannerPlugin({
117
- banner: releaseIdentityBanner([
118
- bundledReleaseIdentity.buildMarker,
119
- bundledReleaseIdentity.sourceRevision,
120
- bundledReleaseIdentity.releaseVersion
121
- ]),
122
- raw: true,
123
- stage: rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
124
- test: /\.(?:c|m)?js$/u
125
- }));
126
- return config;
127
- }
128
- } : {}
135
+ lightningcssLoader: true
129
136
  }
130
137
  };
131
138
  if (enableBffRequestId) presetConfig.bff = {
@@ -146,4 +153,4 @@ const presetUltramodern = (config, options = {})=>{
146
153
  ];
147
154
  return merged;
148
155
  };
149
- export { UltramodernReleaseIdentityBannerPlugin, createPresetUltramodernConfig, isUltramodernReleaseIdentityBannerPlugin, presetUltramodern, releaseIdentityBanner };
156
+ export { UltramodernReleaseIdentityBannerPlugin, createPresetUltramodernConfig, isUltramodernReleaseIdentityBannerPlugin, presetUltramodern, releaseIdentityBanner, ultramodernReleaseIdentityBannerPlugin };
@@ -18,7 +18,11 @@ function createRendererBuildIdentityResolver(renderer) {
18
18
  mode: context.mode ?? ('production' === process.env.NODE_ENV ? 'production' : 'development'),
19
19
  ...delivery ? {
20
20
  appId: delivery.appId,
21
- sourceRevision: delivery.sourceRevision
21
+ deliveryUnit: {
22
+ unitId: delivery.unitId,
23
+ buildMarker: delivery.buildMarker,
24
+ sourceRevision: delivery.sourceRevision
25
+ }
22
26
  } : {
23
27
  appId: context.packageName || void 0
24
28
  }
@@ -0,0 +1,54 @@
1
+ import { rspack } from "@rsbuild/core";
2
+ import { isUltramodernReleaseIdentityBannerPlugin, releaseIdentityBanner } from "./preset.mjs";
3
+ function applyRendererReleaseIdentity(api, getIdentities) {
4
+ api.modifyBundlerChain({
5
+ order: 'post',
6
+ handler: (chain)=>{
7
+ const identities = getIdentities();
8
+ if (!identities) return;
9
+ if (chain.plugins.has('globalVars')) chain.plugin('globalVars').tap((args)=>{
10
+ const definitions = {
11
+ ...args[0]
12
+ };
13
+ delete definitions.ULTRAMODERN_BUILD_MARKER;
14
+ delete definitions.ULTRAMODERN_SOURCE_REVISION;
15
+ return [
16
+ definitions,
17
+ ...args.slice(1)
18
+ ];
19
+ });
20
+ chain.plugin('ultramodern-renderer-runtime-identity').use(rspack.DefinePlugin, [
21
+ {
22
+ ULTRAMODERN_BUILD_MARKER: JSON.stringify(identities.buildId),
23
+ ULTRAMODERN_SOURCE_REVISION: JSON.stringify(identities.sourceRevision)
24
+ }
25
+ ]);
26
+ }
27
+ });
28
+ api.modifyRspackConfig({
29
+ order: 'post',
30
+ handler: (config)=>{
31
+ const identities = getIdentities();
32
+ if (!identities) return config;
33
+ const { buildId, sourceRevision } = identities;
34
+ config.plugins = (config.plugins ?? []).filter((plugin)=>!isUltramodernReleaseIdentityBannerPlugin(plugin));
35
+ config.plugins.push(new rspack.BannerPlugin({
36
+ banner: releaseIdentityBanner([
37
+ buildId,
38
+ sourceRevision
39
+ ]),
40
+ raw: true,
41
+ stage: rspack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
42
+ test: /\.(?:c|m)?js$/u
43
+ }));
44
+ return config;
45
+ }
46
+ });
47
+ }
48
+ const rendererReleaseIdentityBuilderPlugin = (getIdentities)=>({
49
+ name: 'ultramodern:renderer-release-identity',
50
+ setup (api) {
51
+ applyRendererReleaseIdentity(api, getIdentities);
52
+ }
53
+ });
54
+ export { applyRendererReleaseIdentity, rendererReleaseIdentityBuilderPlugin };
@@ -153,7 +153,8 @@ const resolveWorkspaceConfig = (config, options)=>{
153
153
  if (app.package !== packageManifest.name || app.deliveryUnit?.packageName !== packageManifest.name) throw new Error(`[ultramodern-workspace] Package identity for ${options.appId} does not match topology.`);
154
154
  if (app.deliveryUnit?.version !== packageManifest.version) throw new Error(`[ultramodern-workspace] Delivery unit version for ${options.appId} does not match package.json.`);
155
155
  const declaredRenderer = app.renderer;
156
- if (void 0 !== declaredRenderer && void 0 !== config.renderer && config.renderer !== declaredRenderer) throw new Error(`[ultramodern-workspace] Renderer for ${options.appId} does not match topology.`);
156
+ const headless = 'api-only' === app.surfaceProfile || 'none' === declaredRenderer;
157
+ if (headless && void 0 !== config.renderer || void 0 !== declaredRenderer && void 0 !== config.renderer && config.renderer !== declaredRenderer) throw new Error(`[ultramodern-workspace] Renderer for ${options.appId} does not match topology${headless ? ': a headless unit selects no renderer' : ''}.`);
157
158
  const portEnv = portEnvironment(app);
158
159
  const port = developmentPort(environment[portEnv] ?? overlay.ports[options.appId], options.appId);
159
160
  const allowedOrigins = Object.entries(overlay.ports).map(([id, defaultPort])=>{
@@ -200,9 +201,9 @@ const resolveWorkspaceConfig = (config, options)=>{
200
201
  binding
201
202
  ] : [];
202
203
  });
203
- const mfName = requiredString(app.moduleFederation?.name, `${options.appId}.moduleFederation.name`);
204
+ const mfName = headless ? void 0 : requiredString(app.moduleFederation?.name, `${options.appId}.moduleFederation.name`);
204
205
  const workspaceConfig = {
205
- ...void 0 !== declaredRenderer ? {
206
+ ...!headless && void 0 !== declaredRenderer ? {
206
207
  renderer: declaredRenderer
207
208
  } : {},
208
209
  ...cloudflare ? {
@@ -258,7 +259,7 @@ const resolveWorkspaceConfig = (config, options)=>{
258
259
  ...dynamicRemotes.size > 0 ? [
259
260
  dynamicCloudflareServicesPlugin(referencedRemotes, dynamicRemotes, workspaceRoot, environment, services)
260
261
  ] : [],
261
- ...'api-only' === app.surfaceProfile ? [] : [
262
+ ...headless ? [] : [
262
263
  zephyrBuildPlugin(configFilename, environment)
263
264
  ]
264
265
  ],
@@ -284,9 +285,11 @@ const resolveWorkspaceConfig = (config, options)=>{
284
285
  'defaults'
285
286
  ]
286
287
  },
287
- bundlerChain: (chain)=>{
288
- chain.output.uniqueName(mfName).chunkLoadingGlobal(`__ULTRAMODERN_${envSegment(mfName)}_LOADED_CHUNKS__`);
289
- },
288
+ ...mfName ? {
289
+ bundlerChain: (chain)=>{
290
+ chain.output.uniqueName(mfName).chunkLoadingGlobal(`__ULTRAMODERN_${envSegment(mfName)}_LOADED_CHUNKS__`);
291
+ }
292
+ } : {},
290
293
  devServer: {
291
294
  headers: {
292
295
  'Access-Control-Allow-Headers': 'Accept, Authorization, Content-Type, X-Requested-With',