@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.20

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 (213) hide show
  1. package/dist/cjs/backend-federation-build/codegen.js +267 -0
  2. package/dist/cjs/backend-federation-build/config.js +239 -0
  3. package/dist/cjs/backend-federation-build/emit.js +154 -0
  4. package/dist/cjs/backend-federation-build/index.js +53 -0
  5. package/dist/cjs/build-config/build-environment.js +129 -0
  6. package/dist/cjs/build-config/precompress/plugin.js +124 -0
  7. package/dist/cjs/build-config/precompress/types.js +18 -0
  8. package/dist/cjs/build-config/public.js +43 -0
  9. package/dist/cjs/build-config/remote-address.js +58 -0
  10. package/dist/cjs/cloudflare/artifacts.js +8 -19
  11. package/dist/cjs/cloudflare/constants.js +1 -1
  12. package/dist/cjs/cloudflare/delivery-unit.js +23 -42
  13. package/dist/cjs/cloudflare/index.js +10 -2
  14. package/dist/cjs/cloudflare/worker-manifest.js +13 -4
  15. package/dist/cjs/cloudflare/wrangler-config.js +35 -7
  16. package/dist/cjs/cloudflare-builder.js +251 -75
  17. package/dist/cjs/cloudflare-output-contract.js +69 -3
  18. package/dist/cjs/cloudflare-output-verifier/identity.js +29 -27
  19. package/dist/cjs/cloudflare-output-verifier/index.js +10 -0
  20. package/dist/cjs/cloudflare-output-verifier/manifest.js +46 -0
  21. package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +7 -1
  22. package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +14 -6
  23. package/dist/cjs/config.js +34 -1
  24. package/dist/cjs/deploy-output/npmAliases.js +251 -0
  25. package/dist/cjs/deploy-output/plugin.js +97 -0
  26. package/dist/cjs/deploy-output/public-assets.js +146 -0
  27. package/dist/cjs/deploy-output/target.js +104 -0
  28. package/dist/cjs/deploy-output/trace-files.js +90 -0
  29. package/dist/cjs/native-type-checker.js +193 -0
  30. package/dist/cjs/policy-defaults.js +101 -0
  31. package/dist/cjs/release-envelope/framework-output.js +153 -79
  32. package/dist/cjs/release-envelope/index.js +10 -4
  33. package/dist/cjs/release-envelope/plugin.js +18 -13
  34. package/dist/cjs/release-identity.js +5 -6
  35. package/dist/cjs/runtime-package-resolution.js +118 -0
  36. package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  37. package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  38. package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  39. package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  40. package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
  41. package/dist/esm/backend-federation-build/codegen.mjs +216 -0
  42. package/dist/esm/backend-federation-build/config.mjs +163 -0
  43. package/dist/esm/backend-federation-build/emit.mjs +103 -0
  44. package/dist/esm/backend-federation-build/index.mjs +1 -0
  45. package/dist/esm/build-config/build-environment.mjs +88 -0
  46. package/dist/esm/build-config/precompress/plugin.mjs +76 -0
  47. package/dist/esm/build-config/precompress/types.mjs +0 -0
  48. package/dist/esm/build-config/public.mjs +1 -0
  49. package/dist/esm/build-config/remote-address.mjs +20 -0
  50. package/dist/esm/cloudflare/artifacts.mjs +8 -19
  51. package/dist/esm/cloudflare/constants.mjs +1 -1
  52. package/dist/esm/cloudflare/delivery-unit.mjs +17 -36
  53. package/dist/esm/cloudflare/index.mjs +10 -2
  54. package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
  55. package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
  56. package/dist/esm/cloudflare-builder.mjs +245 -75
  57. package/dist/esm/cloudflare-output-contract.mjs +59 -2
  58. package/dist/esm/cloudflare-output-verifier/identity.mjs +27 -25
  59. package/dist/esm/cloudflare-output-verifier/index.mjs +10 -0
  60. package/dist/esm/cloudflare-output-verifier/manifest.mjs +46 -0
  61. package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +7 -1
  62. package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +15 -7
  63. package/dist/esm/config.mjs +3 -0
  64. package/dist/esm/deploy-output/npmAliases.mjs +199 -0
  65. package/dist/esm/deploy-output/plugin.mjs +46 -0
  66. package/dist/esm/deploy-output/public-assets.mjs +82 -0
  67. package/dist/esm/deploy-output/target.mjs +57 -0
  68. package/dist/esm/deploy-output/trace-files.mjs +38 -0
  69. package/dist/esm/native-type-checker.mjs +142 -0
  70. package/dist/esm/policy-defaults.mjs +45 -0
  71. package/dist/esm/release-envelope/framework-output.mjs +130 -56
  72. package/dist/esm/release-envelope/index.mjs +10 -4
  73. package/dist/esm/release-envelope/plugin.mjs +18 -13
  74. package/dist/esm/release-identity.mjs +5 -6
  75. package/dist/esm/runtime-package-resolution.mjs +60 -0
  76. package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  77. package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  78. package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  79. package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  80. package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
  81. package/dist/esm-node/backend-federation-build/codegen.mjs +217 -0
  82. package/dist/esm-node/backend-federation-build/config.mjs +164 -0
  83. package/dist/esm-node/backend-federation-build/emit.mjs +104 -0
  84. package/dist/esm-node/backend-federation-build/index.mjs +2 -0
  85. package/dist/esm-node/build-config/build-environment.mjs +89 -0
  86. package/dist/esm-node/build-config/precompress/plugin.mjs +77 -0
  87. package/dist/esm-node/build-config/precompress/types.mjs +1 -0
  88. package/dist/esm-node/build-config/public.mjs +2 -0
  89. package/dist/esm-node/build-config/remote-address.mjs +21 -0
  90. package/dist/esm-node/cloudflare/artifacts.mjs +8 -19
  91. package/dist/esm-node/cloudflare/constants.mjs +1 -1
  92. package/dist/esm-node/cloudflare/delivery-unit.mjs +17 -36
  93. package/dist/esm-node/cloudflare/index.mjs +10 -2
  94. package/dist/esm-node/cloudflare/worker-manifest.mjs +13 -4
  95. package/dist/esm-node/cloudflare/wrangler-config.mjs +35 -7
  96. package/dist/esm-node/cloudflare-builder.mjs +245 -75
  97. package/dist/esm-node/cloudflare-output-contract.mjs +59 -2
  98. package/dist/esm-node/cloudflare-output-verifier/identity.mjs +27 -25
  99. package/dist/esm-node/cloudflare-output-verifier/index.mjs +10 -0
  100. package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +46 -0
  101. package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +7 -1
  102. package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +15 -7
  103. package/dist/esm-node/config.mjs +3 -0
  104. package/dist/esm-node/deploy-output/npmAliases.mjs +200 -0
  105. package/dist/esm-node/deploy-output/plugin.mjs +49 -0
  106. package/dist/esm-node/deploy-output/public-assets.mjs +83 -0
  107. package/dist/esm-node/deploy-output/target.mjs +58 -0
  108. package/dist/esm-node/deploy-output/trace-files.mjs +39 -0
  109. package/dist/esm-node/native-type-checker.mjs +143 -0
  110. package/dist/esm-node/policy-defaults.mjs +46 -0
  111. package/dist/esm-node/release-envelope/framework-output.mjs +130 -56
  112. package/dist/esm-node/release-envelope/index.mjs +10 -4
  113. package/dist/esm-node/release-envelope/plugin.mjs +18 -13
  114. package/dist/esm-node/release-identity.mjs +5 -6
  115. package/dist/esm-node/runtime-package-resolution.mjs +61 -0
  116. package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  117. package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  118. package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  119. package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  120. package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
  121. package/dist/types/backend-federation-build/codegen.d.ts +116 -0
  122. package/dist/types/backend-federation-build/config.d.ts +121 -0
  123. package/dist/types/backend-federation-build/emit.d.ts +21 -0
  124. package/dist/types/backend-federation-build/index.d.ts +2 -0
  125. package/dist/types/build-config/build-environment.d.ts +14 -0
  126. package/dist/types/build-config/precompress/plugin.d.ts +4 -0
  127. package/dist/types/build-config/precompress/types.d.ts +19 -0
  128. package/dist/types/build-config/public.d.ts +2 -0
  129. package/dist/types/build-config/remote-address.d.ts +3 -0
  130. package/dist/types/cloudflare/artifacts.d.ts +7 -6
  131. package/dist/types/cloudflare/constants.d.ts +1 -1
  132. package/dist/types/cloudflare/delivery-unit.d.ts +3 -3
  133. package/dist/types/cloudflare/worker-manifest.d.ts +2 -2
  134. package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
  135. package/dist/types/cloudflare-builder.d.ts +49 -9
  136. package/dist/types/cloudflare-output-contract.d.ts +4 -1
  137. package/dist/types/cloudflare-output-verifier/identity.d.ts +1 -1
  138. package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
  139. package/dist/types/config.d.ts +29 -1
  140. package/dist/types/deploy-output/npmAliases.d.ts +14 -0
  141. package/dist/types/deploy-output/plugin.d.ts +35 -0
  142. package/dist/types/deploy-output/public-assets.d.ts +51 -0
  143. package/dist/types/deploy-output/target.d.ts +29 -0
  144. package/dist/types/deploy-output/trace-files.d.ts +17 -0
  145. package/dist/types/native-type-checker.d.ts +15 -0
  146. package/dist/types/policy-defaults.d.ts +46 -0
  147. package/dist/types/precompress/LICENSE +20 -0
  148. package/dist/types/precompress/index.d.ts +76 -0
  149. package/dist/types/release-envelope/framework-output.d.ts +8 -3
  150. package/dist/types/release-envelope/plugin.d.ts +7 -7
  151. package/dist/types/runtime-package-resolution.d.ts +28 -0
  152. package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
  153. package/package.json +97 -15
  154. package/src/backend-federation-build/codegen.ts +254 -0
  155. package/src/backend-federation-build/config.ts +492 -0
  156. package/src/backend-federation-build/emit.ts +213 -0
  157. package/src/backend-federation-build/index.ts +2 -0
  158. package/src/build-config/build-environment.ts +160 -0
  159. package/src/build-config/precompress/plugin.ts +140 -0
  160. package/src/build-config/precompress/types.ts +26 -0
  161. package/src/build-config/public.ts +5 -0
  162. package/src/build-config/remote-address.ts +33 -0
  163. package/src/cloudflare/artifacts.ts +22 -43
  164. package/src/cloudflare/constants.ts +1 -1
  165. package/src/cloudflare/delivery-unit.ts +42 -53
  166. package/src/cloudflare/index.ts +24 -11
  167. package/src/cloudflare/worker-manifest.ts +20 -3
  168. package/src/cloudflare/wrangler-config.ts +86 -10
  169. package/src/cloudflare-builder.ts +472 -151
  170. package/src/cloudflare-output-contract.ts +70 -0
  171. package/src/cloudflare-output-verifier/identity.ts +5 -1
  172. package/src/cloudflare-output-verifier/index.ts +20 -0
  173. package/src/cloudflare-output-verifier/manifest.ts +77 -0
  174. package/src/cloudflare-output-verifier/mutation-policy.ts +11 -1
  175. package/src/cloudflare-output-verifier/worker-bundles.ts +32 -14
  176. package/src/config.ts +34 -6
  177. package/src/deploy-output/npmAliases.ts +382 -0
  178. package/src/deploy-output/plugin.ts +86 -0
  179. package/src/deploy-output/public-assets.ts +224 -0
  180. package/src/deploy-output/target.ts +106 -0
  181. package/src/deploy-output/trace-files.ts +67 -0
  182. package/src/native-type-checker.ts +183 -0
  183. package/src/policy-defaults.ts +127 -0
  184. package/src/release-envelope/framework-output.ts +346 -94
  185. package/src/release-envelope/index.ts +26 -5
  186. package/src/release-envelope/plugin.ts +43 -40
  187. package/src/release-identity.ts +13 -2
  188. package/src/runtime-package-resolution.ts +115 -0
  189. package/src/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
  190. package/src/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
  191. package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
  192. package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
  193. package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
  194. package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +0 -11
  195. package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +0 -281
  196. package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  197. package/dist/cjs/templates/cloudflare-worker-path.mjs +0 -98
  198. package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +0 -11
  199. package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +0 -281
  200. package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  201. package/dist/esm/templates/cloudflare-worker-path.mjs +0 -98
  202. package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +0 -11
  203. package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +0 -281
  204. package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  205. package/dist/esm-node/templates/cloudflare-worker-path.mjs +0 -98
  206. package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +0 -5
  207. package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +0 -48
  208. package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +0 -13
  209. package/dist/types/templates/cloudflare-worker-path.d.mts +0 -21
  210. package/src/templates/cloudflare-worker-fs-promises.mjs +0 -11
  211. package/src/templates/cloudflare-worker-loadable-server.mjs +0 -281
  212. package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
  213. package/src/templates/cloudflare-worker-path.mjs +0 -98
@@ -0,0 +1,21 @@
1
+ import "node:module";
2
+ import { resolveBrowserManifestAddress } from "@modern-js/surface-resolution";
3
+ import { resolveDeployTarget } from "../deploy-output/target.mjs";
4
+ import { getBuildConfigEnvironment } from "./build-environment.mjs";
5
+ function createRemoteManifestUrl(options) {
6
+ const env = {
7
+ ...Object.fromEntries([
8
+ options.manifestEnv,
9
+ options.publicUrlEnv,
10
+ 'ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN'
11
+ ].map((name)=>[
12
+ name,
13
+ getBuildConfigEnvironment(name)
14
+ ])),
15
+ MODERNJS_DEPLOY: resolveDeployTarget().target
16
+ };
17
+ const address = resolveBrowserManifestAddress(env, options, getBuildConfigEnvironment('NODE_ENV') ?? 'production');
18
+ if (!address.ok) throw new Error(`Remote ${options.mfName}: ${address.reason}`);
19
+ return env[options.manifestEnv]?.trim() || `${options.mfName}@${address.manifestUrl}`;
20
+ }
21
+ export { createRemoteManifestUrl };
@@ -1,6 +1,7 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { fs } from "@modern-js/utils";
4
+ import { CLOUDFLARE_PUBLIC_ASSET_SCOPE, normalizeDeclaredPublicAssets, stageDeclaredPublicAssets } from "../deploy-output/public-assets.mjs";
4
5
  import { RESERVED_ARTIFACT_DESTINATION_DIRECTORIES, RESERVED_ARTIFACT_DESTINATION_FILES, ROUTE_SPEC_OUTPUT } from "./constants.mjs";
5
6
  import { normalizeRelativePath } from "./utils.mjs";
6
7
  const normalizeCloudflareArtifact = (artifact, index)=>{
@@ -16,18 +17,7 @@ const normalizeCloudflareArtifact = (artifact, index)=>{
16
17
  };
17
18
  };
18
19
  const getCloudflareArtifacts = (modernConfig)=>(modernConfig.deploy?.worker?.artifacts ?? []).map(normalizeCloudflareArtifact);
19
- const normalizeCloudflarePublicAsset = (asset, index)=>{
20
- const from = normalizeRelativePath(asset.from, `deploy.worker.publicAssets[${index}].from`, 'app root');
21
- const to = normalizeRelativePath(asset.to, `deploy.worker.publicAssets[${index}].to`, 'Cloudflare public output', {
22
- allowRoot: true
23
- });
24
- return {
25
- from,
26
- to,
27
- index
28
- };
29
- };
30
- const getCloudflarePublicAssets = (modernConfig)=>(modernConfig.deploy?.worker?.publicAssets ?? []).map(normalizeCloudflarePublicAsset);
20
+ const getCloudflarePublicAssets = (modernConfig)=>normalizeDeclaredPublicAssets(modernConfig.deploy?.worker?.publicAssets, CLOUDFLARE_PUBLIC_ASSET_SCOPE);
31
21
  const copyCloudflareArtifacts = async (appDirectory, outputDirectory, artifacts)=>{
32
22
  for (const artifact of artifacts){
33
23
  const sourcePath = node_path.join(appDirectory, artifact.from);
@@ -35,13 +25,12 @@ const copyCloudflareArtifacts = async (appDirectory, outputDirectory, artifacts)
35
25
  await fs.copy(sourcePath, node_path.join(outputDirectory, artifact.to));
36
26
  }
37
27
  };
38
- const copyCloudflarePublicAssets = async (appDirectory, publicDirectory, publicAssets)=>{
39
- for (const asset of publicAssets){
40
- const sourcePath = node_path.join(appDirectory, asset.from);
41
- if (!await fs.pathExists(sourcePath)) throw new Error(`deploy.worker.publicAssets[${asset.index}].from does not exist: ${asset.from}`);
42
- await fs.copy(sourcePath, node_path.join(publicDirectory, asset.to));
43
- }
44
- };
28
+ const copyCloudflarePublicAssets = async (appDirectory, outputDirectory, publicAssets)=>stageDeclaredPublicAssets({
29
+ appDirectory,
30
+ outputDirectory,
31
+ assets: publicAssets,
32
+ scope: CLOUDFLARE_PUBLIC_ASSET_SCOPE
33
+ });
45
34
  const copyCloudflareD1Migrations = async (appDirectory, outputDirectory, modernConfig)=>{
46
35
  for (const [index, database] of (modernConfig.deploy?.worker?.d1Databases ?? []).entries()){
47
36
  if (!database.migrationsDir) continue;
@@ -19,7 +19,7 @@ const DEFAULT_SERVER_ONLY_PUBLIC_ASSET_EXCLUDES = [
19
19
  ];
20
20
  const BFF_EFFECT_WORKER_ENTRY = `${WORKER_BUNDLE_DIRECTORY}/__modern_bff_effect.js`;
21
21
  const BFF_EFFECT_WORKER_DISPATCHER_EXPORT = '__modern_create_effect_bff_dispatcher';
22
- const EFFECT_BFF_CLOUDFLARE_IMPORT_GUIDANCE = 'Ensure the Effect API entry exists at api/index.ts or bff.effect.entry, and import Cloudflare edge handlers from @modern-js/plugin-bff/effect-edge instead of lambda/Hono server helpers.';
22
+ const EFFECT_BFF_CLOUDFLARE_IMPORT_GUIDANCE = 'Ensure the Effect API entry exists at api/index.ts or bff.effect.entry, and import Cloudflare edge handlers from @modern-js/bff-effect/effect-edge instead of lambda/Hono server helpers.';
23
23
  const DEFAULT_COMPATIBILITY_DATE = '2026-06-02';
24
24
  const COMPATIBILITY_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/u;
25
25
  const REQUIRED_COMPATIBILITY_FLAGS = CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS;
@@ -1,14 +1,14 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
+ import { ULTRAMODERN_BUILD_ARTIFACT_PATH, isUltramodernBuildArtifact, nonEmptyString, toDeliveryUnitIdentity } from "@modern-js/backend-federation-contracts";
3
4
  import { fs } from "@modern-js/utils";
4
- import { ULTRAMODERN_BUILD_ARTIFACT_PATH, ULTRAMODERN_BUILD_MODULE_PATH, isUltramodernBuildArtifact, nonEmptyString, toDeliveryUnitIdentity } from "@modern-js/utils/universal";
5
5
  import { resolveUltramodernReleaseIdentity } from "../release-identity.mjs";
6
6
  import { isRecord } from "./utils.mjs";
7
- const COMPACT_CONFIG_PATH = '.modernjs/ultramodern.json';
7
+ const TOPOLOGY_PATH = 'topology/reference-topology.json';
8
8
  const findWorkspaceRoot = async (appDirectory)=>{
9
9
  let current = node_path.resolve(appDirectory);
10
10
  for(;;){
11
- if (await fs.pathExists(node_path.join(current, COMPACT_CONFIG_PATH))) return current;
11
+ if (await fs.pathExists(node_path.join(current, TOPOLOGY_PATH))) return current;
12
12
  const parent = node_path.dirname(current);
13
13
  if (parent === current) return;
14
14
  current = parent;
@@ -25,36 +25,25 @@ const stampReleaseIdentity = (identity, workspaceRoot)=>{
25
25
  })
26
26
  };
27
27
  };
28
- const resolveCompactApp = async (appDirectory)=>{
28
+ const resolveTopologyApp = async (appDirectory)=>{
29
29
  const workspaceRoot = await findWorkspaceRoot(appDirectory);
30
30
  if (!workspaceRoot) return;
31
- let compactConfig;
32
- try {
33
- compactConfig = await fs.readJSON(node_path.join(workspaceRoot, COMPACT_CONFIG_PATH));
34
- } catch {
35
- return {
36
- workspaceRoot
37
- };
38
- }
39
- if (!isRecord(compactConfig)) return {
40
- workspaceRoot
41
- };
42
- const topology = isRecord(compactConfig.topology) ? compactConfig.topology : void 0;
43
- const apps = Array.isArray(topology?.apps) ? topology.apps : void 0;
44
- if (!apps) return {
45
- app: compactConfig,
46
- workspaceRoot
47
- };
31
+ const topology = await fs.readJSON(node_path.join(workspaceRoot, TOPOLOGY_PATH));
32
+ if (!isRecord(topology) || !isRecord(topology.shell) || !Array.isArray(topology.verticals) || void 0 !== topology.shells && !Array.isArray(topology.shells)) throw new Error('[cloudflare-delivery-unit] Invalid declared reference topology.');
33
+ const apps = [
34
+ topology.shell,
35
+ ...topology.verticals,
36
+ ...Array.isArray(topology.shells) ? topology.shells : []
37
+ ];
48
38
  const resolvedAppDirectory = node_path.resolve(appDirectory);
49
39
  const app = apps.find((candidate)=>{
50
40
  if (!isRecord(candidate)) return false;
51
41
  const appPath = nonEmptyString(candidate.path);
52
42
  return void 0 !== appPath && node_path.resolve(workspaceRoot, appPath.replace(/^\.\/+/u, '')) === resolvedAppDirectory;
53
43
  });
44
+ if (!isRecord(app)) throw new Error(`[cloudflare-delivery-unit] ${appDirectory} is missing from the declared reference topology.`);
54
45
  return {
55
- ...isRecord(app) ? {
56
- app
57
- } : {},
46
+ app,
58
47
  workspaceRoot
59
48
  };
60
49
  };
@@ -81,30 +70,22 @@ const createDeliveryUnitStamp = (identity, app)=>{
81
70
  };
82
71
  };
83
72
  const resolveTopologyDeliveryUnit = async (appDirectory)=>{
84
- const resolved = await resolveCompactApp(appDirectory);
73
+ const resolved = await resolveTopologyApp(appDirectory);
85
74
  if (!resolved?.app) return;
86
75
  const identity = toDeliveryUnitIdentity(resolved.app.deliveryUnit);
87
- return identity ? createDeliveryUnitStamp(stampReleaseIdentity(identity, resolved.workspaceRoot), resolved.app) : void 0;
76
+ if (!identity) throw new Error('[cloudflare-delivery-unit] Declared app is missing a valid delivery-unit identity.');
77
+ return createDeliveryUnitStamp(stampReleaseIdentity(identity, resolved.workspaceRoot), resolved.app);
88
78
  };
89
79
  const resolveWorkerDeliveryUnitStamp = async (appDirectory)=>{
90
80
  const buildArtifactPath = node_path.join(appDirectory, ULTRAMODERN_BUILD_ARTIFACT_PATH);
91
- const buildModulePath = node_path.join(appDirectory, ULTRAMODERN_BUILD_MODULE_PATH);
92
81
  let identity;
93
82
  if (await fs.pathExists(buildArtifactPath)) {
94
83
  const artifact = await fs.readJSON(buildArtifactPath);
95
84
  if (!isUltramodernBuildArtifact(artifact)) return;
96
85
  identity = toDeliveryUnitIdentity(artifact.deliveryUnit);
97
- } else if (await fs.pathExists(buildModulePath)) {
98
- console.warn(`[cloudflare] ${buildArtifactPath} missing; falling back to legacy regex parsing of ${buildModulePath}. Regenerate the workspace to emit ultramodern-build.json.`);
99
- const source = await fs.readFile(buildModulePath, 'utf8');
100
- identity = toDeliveryUnitIdentity({
101
- buildMarker: source.match(/\bbuild:\s*['"]([^'"]+)['"]/u)?.[1],
102
- unitId: source.match(/\bunitId:\s*['"]([^'"]+)['"]/u)?.[1],
103
- sourceRevision: source.match(/\bsourceRevision:\s*['"]([^'"]+)['"]/u)?.[1]
104
- });
105
86
  }
106
87
  if (!identity) return;
107
- const resolved = await resolveCompactApp(appDirectory);
88
+ const resolved = await resolveTopologyApp(appDirectory);
108
89
  if (resolved) identity = stampReleaseIdentity(identity, resolved.workspaceRoot);
109
90
  return createDeliveryUnitStamp(identity, resolved?.app);
110
91
  };
@@ -1,5 +1,6 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
+ import { BACKEND_FEDERATION_MANIFEST_FILE, BACKEND_FEDERATION_REMOTE_ENTRY_FILE, ULTRAMODERN_BUILD_ARTIFACT_FILE } from "@modern-js/backend-federation-contracts";
3
4
  import { fs } from "@modern-js/utils";
4
5
  import { createCloudflareOutputPlan } from "../cloudflare-output-plan.mjs";
5
6
  import { assertCloudflareOutput } from "../cloudflare-output-verifier/index.mjs";
@@ -32,12 +33,13 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
32
33
  const publicAssetExcludes = getPublicAssetExcludes(appDirectory, modernConfig);
33
34
  const releaseEnvelopeEnabled = api.isPluginExists('@modern-js/ultramodern-release-envelope');
34
35
  let hasReleaseEnvelope = false;
36
+ let declaredPublicAssets = [];
35
37
  return {
36
38
  async prepare () {
37
39
  await fs.remove(outputDirectory);
38
40
  },
39
41
  async writeOutput () {
40
- if (releaseEnvelopeEnabled && await fs.pathExists(node_path.join(distDirectory, MICROVERTICAL_RELEASE_ENVELOPE_PATH))) await emitFrameworkMicroVerticalReleaseEnvelope({
42
+ if (releaseEnvelopeEnabled) await emitFrameworkMicroVerticalReleaseEnvelope({
41
43
  apiOnly,
42
44
  distDirectory,
43
45
  target: 'cloudflare'
@@ -46,6 +48,11 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
46
48
  await fs.copy(distDirectory, publicDirectory, {
47
49
  filter: (src)=>{
48
50
  const relativePath = node_path.relative(distDirectory, src).replace(/\\/gu, '/');
51
+ if (apiOnly && '' !== relativePath && ![
52
+ BACKEND_FEDERATION_MANIFEST_FILE,
53
+ BACKEND_FEDERATION_REMOTE_ENTRY_FILE,
54
+ ULTRAMODERN_BUILD_ARTIFACT_FILE
55
+ ].includes(relativePath)) return false;
49
56
  return 'release' !== relativePath && !relativePath.startsWith('release/') && 'public' !== relativePath && !relativePath.startsWith('public/') && shouldCopyToPublicAssets(src, distDirectory, publicAssetExcludes);
50
57
  }
51
58
  });
@@ -69,7 +76,7 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
69
76
  await fs.writeJSON(outputPlan.paths.workerPackage, outputPlan.packages.worker);
70
77
  }
71
78
  await copyCloudflareArtifacts(appDirectory, outputDirectory, cloudflareArtifacts);
72
- await copyCloudflarePublicAssets(appDirectory, publicDirectory, getCloudflarePublicAssets(modernConfig));
79
+ declaredPublicAssets = await copyCloudflarePublicAssets(appDirectory, outputDirectory, getCloudflarePublicAssets(modernConfig));
73
80
  await copyCloudflareD1Migrations(appDirectory, outputDirectory, modernConfig);
74
81
  await fs.writeJSON(wranglerConfigPath, createWranglerConfig(appDirectory, modernConfig), {
75
82
  spaces: 2
@@ -98,6 +105,7 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
98
105
  });
99
106
  if (hasReleaseEnvelope) {
100
107
  await emitCloudflareStagedReleaseEnvelope({
108
+ declaredPublicAssets,
101
109
  distDirectory,
102
110
  outputDirectory
103
111
  });
@@ -1,6 +1,7 @@
1
1
  import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { fs } from "@modern-js/utils";
4
+ import { getCloudflareWorkerRouteDataEntryName } from "../cloudflare-output-contract.mjs";
4
5
  import { readRouteSpec } from "./artifacts.mjs";
5
6
  import { ASSETS_BINDING, BFF_EFFECT_WORKER_DISPATCHER_EXPORT, BFF_EFFECT_WORKER_ENTRY, CLOUDFLARE_RUNTIME_TYPE, CLOUDFLARE_WORKER_BUNDLE_FORMAT, DEFAULT_SERVER_ONLY_PUBLIC_ASSET_EXCLUDES, EFFECT_BFF_CLOUDFLARE_IMPORT_GUIDANCE, LOADABLE_STATS_FILE, PUBLIC_ASSETS_DIRECTORY, ROUTE_MANIFEST_FILE, ROUTE_SPEC_FILE, ROUTE_SPEC_OUTPUT, SERVER_BUNDLE_DIRECTORY, WORKER_BUNDLE_DIRECTORY, WORKER_ENTRY } from "./constants.mjs";
6
7
  import { createI18nWorkerManifest } from "./i18n-worker.mjs";
@@ -66,13 +67,18 @@ const createWorkerManifest = async (outputDirectory, modernConfig, appContext, d
66
67
  const routeSpec = await readRouteSpec(outputDirectory);
67
68
  const routes = await Promise.all(routeSpec.routes.map(async (route)=>{
68
69
  const worker = 'string' == typeof route.worker ? route.worker : void 0;
70
+ const routeDataWorker = route.isSSR && 'string' == typeof route.entryName ? `${WORKER_BUNDLE_DIRECTORY}/${getCloudflareWorkerRouteDataEntryName(route.entryName)}.js` : void 0;
71
+ const hasRouteDataWorker = routeDataWorker ? await fs.pathExists(node_path.join(outputDirectory, routeDataWorker)) : false;
69
72
  return {
70
73
  urlPath: route.urlPath,
71
74
  entryName: route.entryName,
72
75
  entryPath: route.entryPath,
73
76
  isSSR: Boolean(route.isSSR),
74
77
  worker,
75
- workerExists: worker ? await fs.pathExists(node_path.join(outputDirectory, worker)) : false
78
+ workerExists: worker ? await fs.pathExists(node_path.join(outputDirectory, worker)) : false,
79
+ ...hasRouteDataWorker ? {
80
+ routeDataWorker
81
+ } : {}
76
82
  };
77
83
  }));
78
84
  const bffPrefix = modernConfig.bff?.prefix;
@@ -132,9 +138,12 @@ const createWorkerManifest = async (outputDirectory, modernConfig, appContext, d
132
138
  };
133
139
  const createWorkerModuleLoaders = (manifest)=>{
134
140
  const imports = new Map();
135
- for (const route of manifest.routeSpec.routes)if (route.worker && route.workerExists) {
136
- const importPath = `../${String(route.worker).replace(/^\/+/u, '')}`;
137
- imports.set(route.worker, `() => import(${JSON.stringify(importPath)})`);
141
+ for (const route of manifest.routeSpec.routes)for (const worker of [
142
+ route.workerExists ? route.worker : void 0,
143
+ route.routeDataWorker
144
+ ])if (worker) {
145
+ const importPath = `../${String(worker).replace(/^\/+/u, '')}`;
146
+ imports.set(worker, `() => import(${JSON.stringify(importPath)})`);
138
147
  }
139
148
  if (manifest.bff?.worker) {
140
149
  const importPath = `../${String(manifest.bff.worker).replace(/^\/+/u, '')}`;
@@ -2,12 +2,16 @@ import "node:module";
2
2
  import node_path from "node:path";
3
3
  import { ASSETS_BINDING, COMPATIBILITY_DATE_PATTERN, DEFAULT_COMPATIBILITY_DATE, PUBLIC_ASSETS_DIRECTORY, REQUIRED_COMPATIBILITY_FLAGS, WORKER_ENTRY } from "./constants.mjs";
4
4
  import { isJsonRecord, normalizeRelativePath } from "./utils.mjs";
5
- const getCompatibilityDate = (modernConfig)=>{
6
- const configuredDate = modernConfig.deploy?.worker?.compatibilityDate?.trim();
7
- const compatibilityDate = configuredDate || DEFAULT_COMPATIBILITY_DATE;
8
- if (!COMPATIBILITY_DATE_PATTERN.test(compatibilityDate)) throw new Error(`deploy.worker.compatibilityDate must use YYYY-MM-DD, received ${JSON.stringify(compatibilityDate)}.`);
5
+ const assertSupportedCompatibilityDate = (compatibilityDate, label)=>{
6
+ if ('string' != typeof compatibilityDate) throw new Error(`${label} must be a YYYY-MM-DD string.`);
7
+ if (!COMPATIBILITY_DATE_PATTERN.test(compatibilityDate)) throw new Error(`${label} must use YYYY-MM-DD, received ${JSON.stringify(compatibilityDate)}.`);
8
+ if (compatibilityDate < DEFAULT_COMPATIBILITY_DATE) throw new Error(`${label} must be ${DEFAULT_COMPATIBILITY_DATE} or later, the date the Cloudflare worker Node.js built-in contract is verified against; received ${JSON.stringify(compatibilityDate)}.`);
9
9
  return compatibilityDate;
10
10
  };
11
+ const getCompatibilityDate = (modernConfig, wranglerCompatibilityDate)=>{
12
+ if (void 0 !== wranglerCompatibilityDate) return assertSupportedCompatibilityDate(wranglerCompatibilityDate, 'deploy.worker.wrangler.compatibility_date');
13
+ return assertSupportedCompatibilityDate(modernConfig.deploy?.worker?.compatibilityDate?.trim() || DEFAULT_COMPATIBILITY_DATE, 'deploy.worker.compatibilityDate');
14
+ };
11
15
  const getWorkerName = (appDirectory)=>{
12
16
  const basename = node_path.basename(appDirectory);
13
17
  return basename.replace(/[^a-zA-Z0-9-_]/g, '-') || 'modern-cloudflare-worker';
@@ -22,11 +26,11 @@ const getConfiguredWrangler = (modernConfig)=>{
22
26
  if (!isJsonRecord(wrangler)) throw new Error('deploy.worker.wrangler must be a JSON object.');
23
27
  return wrangler;
24
28
  };
25
- const createWranglerCompatibilityFlags = (configuredFlags)=>{
29
+ const createWranglerCompatibilityFlags = (configuredFlags, label = 'deploy.worker.wrangler.compatibility_flags')=>{
26
30
  if (void 0 === configuredFlags) return [
27
31
  ...REQUIRED_COMPATIBILITY_FLAGS
28
32
  ];
29
- if (!Array.isArray(configuredFlags) || configuredFlags.some((flag)=>'string' != typeof flag)) throw new Error('deploy.worker.wrangler.compatibility_flags must be an array of strings.');
33
+ if (!Array.isArray(configuredFlags) || configuredFlags.some((flag)=>'string' != typeof flag)) throw new Error(`${label} must be an array of strings.`);
30
34
  return [
31
35
  ...new Set([
32
36
  ...configuredFlags,
@@ -34,6 +38,26 @@ const createWranglerCompatibilityFlags = (configuredFlags)=>{
34
38
  ])
35
39
  ];
36
40
  };
41
+ const createWranglerEnvironments = (wranglerEnv)=>{
42
+ if (void 0 === wranglerEnv) return;
43
+ if (!isJsonRecord(wranglerEnv)) throw new Error('deploy.worker.wrangler.env must be an object.');
44
+ return Object.fromEntries(Object.entries(wranglerEnv).map(([name, environment])=>{
45
+ const label = `deploy.worker.wrangler.env.${name}`;
46
+ if (!isJsonRecord(environment)) throw new Error(`${label} must be an object.`);
47
+ return [
48
+ name,
49
+ {
50
+ ...environment,
51
+ ...void 0 === environment.compatibility_date ? {} : {
52
+ compatibility_date: assertSupportedCompatibilityDate(environment.compatibility_date, `${label}.compatibility_date`)
53
+ },
54
+ ...void 0 === environment.compatibility_flags ? {} : {
55
+ compatibility_flags: createWranglerCompatibilityFlags(environment.compatibility_flags, `${label}.compatibility_flags`)
56
+ }
57
+ }
58
+ ];
59
+ }));
60
+ };
37
61
  const createWranglerAssetsConfig = (configuredAssets)=>{
38
62
  if (void 0 !== configuredAssets && !isJsonRecord(configuredAssets)) throw new Error('deploy.worker.wrangler.assets must be an object.');
39
63
  return {
@@ -130,17 +154,21 @@ const createWorkerManifestServiceBindings = (serviceBindings)=>{
130
154
  };
131
155
  const createWranglerConfig = (appDirectory, modernConfig)=>{
132
156
  const wrangler = getConfiguredWrangler(modernConfig);
157
+ const environments = createWranglerEnvironments(wrangler.env);
133
158
  const d1Databases = createWranglerD1Databases(modernConfig, wrangler.d1_databases);
134
159
  const serviceBindings = createWorkerServiceBindings(modernConfig, wrangler.services);
135
160
  const wranglerServices = createWranglerServices(serviceBindings);
136
161
  return {
137
162
  $schema: 'node_modules/wrangler/config-schema.json',
138
163
  name: getConfiguredWorkerName(appDirectory, modernConfig),
139
- compatibility_date: getCompatibilityDate(modernConfig),
140
164
  ...wrangler,
165
+ compatibility_date: getCompatibilityDate(modernConfig, wrangler.compatibility_date),
141
166
  main: WORKER_ENTRY,
142
167
  compatibility_flags: createWranglerCompatibilityFlags(wrangler.compatibility_flags),
143
168
  assets: createWranglerAssetsConfig(wrangler.assets),
169
+ ...void 0 === environments ? {} : {
170
+ env: environments
171
+ },
144
172
  ...void 0 === d1Databases ? {} : {
145
173
  d1_databases: d1Databases
146
174
  },