@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.12 → 3.9.0-ultramodern.14
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.
- package/dist/cjs/backend-federation-build/codegen.js +7 -2
- package/dist/cjs/backend-federation-build/config.js +86 -36
- package/dist/cjs/backend-federation-build/emit.js +17 -13
- package/dist/cjs/cloudflare/delivery-unit.js +16 -26
- package/dist/cjs/cloudflare/index.js +7 -1
- package/dist/cjs/cloudflare/worker-manifest.js +13 -4
- package/dist/cjs/cloudflare/wrangler-config.js +35 -7
- package/dist/cjs/cloudflare-builder.js +247 -16
- package/dist/cjs/cloudflare-output-contract.js +32 -2
- package/dist/cjs/cloudflare-output-verifier/identity.js +26 -24
- package/dist/cjs/cloudflare-output-verifier/index.js +10 -0
- package/dist/cjs/cloudflare-output-verifier/manifest.js +46 -0
- package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +7 -1
- package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +10 -5
- package/dist/cjs/deploy-output/npmAliases.js +28 -3
- package/dist/cjs/release-envelope/framework-output.js +62 -49
- package/dist/cjs/release-envelope/index.js +10 -4
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm/backend-federation-build/codegen.mjs +7 -2
- package/dist/esm/backend-federation-build/config.mjs +78 -31
- package/dist/esm/backend-federation-build/emit.mjs +18 -14
- package/dist/esm/cloudflare/delivery-unit.mjs +16 -26
- package/dist/esm/cloudflare/index.mjs +7 -1
- package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm/cloudflare-builder.mjs +241 -19
- package/dist/esm/cloudflare-output-contract.mjs +25 -1
- package/dist/esm/cloudflare-output-verifier/identity.mjs +26 -24
- package/dist/esm/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm/deploy-output/npmAliases.mjs +28 -3
- package/dist/esm/release-envelope/framework-output.mjs +62 -49
- package/dist/esm/release-envelope/index.mjs +10 -4
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm-node/backend-federation-build/codegen.mjs +7 -2
- package/dist/esm-node/backend-federation-build/config.mjs +78 -31
- package/dist/esm-node/backend-federation-build/emit.mjs +18 -14
- package/dist/esm-node/cloudflare/delivery-unit.mjs +16 -26
- package/dist/esm-node/cloudflare/index.mjs +7 -1
- package/dist/esm-node/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm-node/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm-node/cloudflare-builder.mjs +241 -19
- package/dist/esm-node/cloudflare-output-contract.mjs +25 -1
- package/dist/esm-node/cloudflare-output-verifier/identity.mjs +26 -24
- package/dist/esm-node/cloudflare-output-verifier/index.mjs +10 -0
- package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +46 -0
- package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +7 -1
- package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm-node/deploy-output/npmAliases.mjs +28 -3
- package/dist/esm-node/release-envelope/framework-output.mjs +62 -49
- package/dist/esm-node/release-envelope/index.mjs +10 -4
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/types/backend-federation-build/codegen.d.ts +30 -0
- package/dist/types/backend-federation-build/config.d.ts +32 -13
- package/dist/types/cloudflare/delivery-unit.d.ts +1 -1
- package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
- package/dist/types/cloudflare-builder.d.ts +45 -1
- package/dist/types/cloudflare-output-contract.d.ts +3 -1
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
- package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
- package/package.json +25 -21
- package/src/backend-federation-build/codegen.ts +6 -2
- package/src/backend-federation-build/config.ts +207 -71
- package/src/backend-federation-build/emit.ts +33 -22
- package/src/cloudflare/delivery-unit.ts +39 -33
- package/src/cloudflare/index.ts +20 -6
- package/src/cloudflare/worker-manifest.ts +19 -3
- package/src/cloudflare/wrangler-config.ts +86 -10
- package/src/cloudflare-builder.ts +464 -15
- package/src/cloudflare-output-contract.ts +35 -2
- package/src/cloudflare-output-verifier/identity.ts +4 -0
- package/src/cloudflare-output-verifier/index.ts +20 -0
- package/src/cloudflare-output-verifier/manifest.ts +77 -0
- package/src/cloudflare-output-verifier/mutation-policy.ts +11 -1
- package/src/cloudflare-output-verifier/worker-bundles.ts +27 -11
- package/src/deploy-output/npmAliases.ts +52 -3
- package/src/release-envelope/framework-output.ts +163 -90
- package/src/release-envelope/index.ts +26 -5
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
|
@@ -213,8 +213,13 @@ const createBackendManifest = (workspaceRoot, distDirectory, app, entryIntegrity
|
|
|
213
213
|
source: {
|
|
214
214
|
module: sourceModule
|
|
215
215
|
},
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
...'rpc' === app.apiProtocol ? {
|
|
217
|
+
rpcPath: app.rpcPath,
|
|
218
|
+
rpcSerialization: 'json'
|
|
219
|
+
} : {
|
|
220
|
+
readinessPath: `${app.apiPrefix}/${app.apiStem}/readiness`,
|
|
221
|
+
openapiPath: `${app.apiPrefix}/openapi.json`
|
|
222
|
+
},
|
|
218
223
|
...app.deliveryUnit ? {
|
|
219
224
|
deliveryUnit: app.deliveryUnit
|
|
220
225
|
} : {},
|
|
@@ -37,9 +37,10 @@ var __webpack_require__ = {};
|
|
|
37
37
|
var __webpack_exports__ = {};
|
|
38
38
|
__webpack_require__.r(__webpack_exports__);
|
|
39
39
|
__webpack_require__.d(__webpack_exports__, {
|
|
40
|
-
|
|
40
|
+
DEVELOPMENT_OVERLAY_PATH: ()=>DEVELOPMENT_OVERLAY_PATH,
|
|
41
|
+
REFERENCE_TOPOLOGY_PATH: ()=>REFERENCE_TOPOLOGY_PATH,
|
|
41
42
|
buildArtifactPathFor: ()=>buildArtifactPathFor,
|
|
42
|
-
|
|
43
|
+
createAppFromTopology: ()=>createAppFromTopology,
|
|
43
44
|
createStampedDeliveryUnit: ()=>createStampedDeliveryUnit,
|
|
44
45
|
findBackendFederationApp: ()=>findBackendFederationApp,
|
|
45
46
|
findWorkspaceRoot: ()=>findWorkspaceRoot,
|
|
@@ -54,7 +55,8 @@ const external_node_path_namespaceObject = require("node:path");
|
|
|
54
55
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
55
56
|
const release_identity_namespaceObject = require("@modern-js/app-tools-extensions/release-identity");
|
|
56
57
|
const backend_federation_contracts_namespaceObject = require("@modern-js/backend-federation-contracts");
|
|
57
|
-
const
|
|
58
|
+
const REFERENCE_TOPOLOGY_PATH = 'topology/reference-topology.json';
|
|
59
|
+
const DEVELOPMENT_OVERLAY_PATH = 'topology/local-overlays/development.json';
|
|
58
60
|
const normalizeRelativePath = (value)=>value.replace(/\\/gu, '/').replace(/^\.\/+/u, '');
|
|
59
61
|
const isRecord = (value)=>'object' == typeof value && null !== value;
|
|
60
62
|
const readJsonFile = async (filePath)=>JSON.parse(await promises_default().readFile(filePath, 'utf8'));
|
|
@@ -82,15 +84,25 @@ const readBuildIdentity = async (appDirectory)=>{
|
|
|
82
84
|
const toPascalCase = (value)=>value.split(/[^a-zA-Z0-9]+/u).filter(Boolean).map((part)=>part.charAt(0).toUpperCase() + part.slice(1)).join('');
|
|
83
85
|
const stringValue = (value)=>'string' == typeof value && value.length > 0 ? value : void 0;
|
|
84
86
|
const createBackendName = (app, id)=>{
|
|
85
|
-
const configuredName = stringValue(app.backendFederation?.name) ?? stringValue(app.backendFederation?.executionSurfaces?.node?.remoteName)
|
|
87
|
+
const configuredName = stringValue(app.backendFederation?.name) ?? stringValue(app.backendFederation?.executionSurfaces?.node?.remoteName);
|
|
86
88
|
if (configuredName) return configuredName;
|
|
87
89
|
const mfName = stringValue(app.moduleFederation?.name);
|
|
88
90
|
return mfName ? `${mfName}Backend` : `vertical${toPascalCase(id)}Backend`;
|
|
89
91
|
};
|
|
92
|
+
const rebaseDefaultLocalUrl = (value, defaultPort, publicOrigin)=>{
|
|
93
|
+
let url;
|
|
94
|
+
try {
|
|
95
|
+
url = new URL(value);
|
|
96
|
+
} catch {
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
if ('http:' !== url.protocol || 'localhost' !== url.hostname || Number(url.port) !== defaultPort || url.username || url.password) return value;
|
|
100
|
+
return `${publicOrigin}${url.pathname}${url.search}${url.hash}`;
|
|
101
|
+
};
|
|
90
102
|
const findWorkspaceRoot = (appDirectory)=>{
|
|
91
103
|
let current = appDirectory;
|
|
92
104
|
while(true){
|
|
93
|
-
if ((0, external_node_fs_namespaceObject.existsSync)(external_node_path_default().join(current,
|
|
105
|
+
if ((0, external_node_fs_namespaceObject.existsSync)(external_node_path_default().join(current, REFERENCE_TOPOLOGY_PATH))) return current;
|
|
94
106
|
const parent = external_node_path_default().dirname(current);
|
|
95
107
|
if (parent === current) return;
|
|
96
108
|
current = parent;
|
|
@@ -114,59 +126,96 @@ const createStampedDeliveryUnit = (input)=>{
|
|
|
114
126
|
if (!validation.ok) return;
|
|
115
127
|
return (0, backend_federation_contracts_namespaceObject.deliveryUnitContractBlock)(record);
|
|
116
128
|
};
|
|
117
|
-
const
|
|
118
|
-
const id = stringValue(
|
|
119
|
-
const appPath = stringValue(
|
|
120
|
-
if (!id || 'vertical' !==
|
|
121
|
-
const directory =
|
|
129
|
+
const createAppFromTopology = (workspaceRoot, appDirectory, topologyApp, overlay, packageManifest)=>{
|
|
130
|
+
const id = stringValue(topologyApp.id);
|
|
131
|
+
const appPath = stringValue(topologyApp.path);
|
|
132
|
+
if (!id || !appPath || 'vertical' !== topologyApp.kind || !isRecord(topologyApp.api) || !isRecord(topologyApp.backendFederation)) return;
|
|
133
|
+
const directory = normalizeRelativePath(appPath);
|
|
122
134
|
if (external_node_path_default().resolve(workspaceRoot, directory) !== external_node_path_default().resolve(appDirectory)) return;
|
|
123
|
-
const
|
|
124
|
-
if (
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
const
|
|
130
|
-
|
|
135
|
+
const defaultPort = overlay.ports?.[id];
|
|
136
|
+
if ('number' != typeof defaultPort || !Number.isInteger(defaultPort) || defaultPort < 1 || defaultPort > 65535) throw new Error(`[backend-federation-build] Invalid development port for ${id}.`);
|
|
137
|
+
const portEnv = stringValue(topologyApp.portEnv) ?? `VERTICAL_${(stringValue(topologyApp.domain) ?? id).replace(/[^a-zA-Z0-9]/gu, '_').toUpperCase()}_PORT`;
|
|
138
|
+
const port = Number(process.env[portEnv] ?? defaultPort);
|
|
139
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error(`[backend-federation-build] Invalid ${portEnv} development port for ${id}.`);
|
|
140
|
+
const publicUrlEnv = stringValue(topologyApp.cloudflare?.publicUrlEnv);
|
|
141
|
+
const configuredPublicUrl = publicUrlEnv ? process.env[publicUrlEnv]?.trim() : void 0;
|
|
142
|
+
let publicOrigin = `http://localhost:${port}`;
|
|
143
|
+
if (configuredPublicUrl) {
|
|
144
|
+
let url;
|
|
145
|
+
try {
|
|
146
|
+
url = new URL(configuredPublicUrl);
|
|
147
|
+
} catch {
|
|
148
|
+
throw new Error(`[backend-federation-build] Invalid ${publicUrlEnv} public URL for ${id}.`);
|
|
149
|
+
}
|
|
150
|
+
if (![
|
|
151
|
+
'http:',
|
|
152
|
+
'https:'
|
|
153
|
+
].includes(url.protocol) || url.username || url.password) throw new Error(`[backend-federation-build] Invalid ${publicUrlEnv} public URL for ${id}.`);
|
|
154
|
+
publicOrigin = url.origin;
|
|
155
|
+
}
|
|
156
|
+
const apiPrefix = stringValue(topologyApp.api.bff?.prefix) ?? `/${id}-api`;
|
|
157
|
+
const apiProtocol = topologyApp.api.protocol ?? 'rest';
|
|
158
|
+
if ('rest' !== apiProtocol && 'rpc' !== apiProtocol) throw new Error(`[backend-federation-build] Unsupported API protocol for ${id}.`);
|
|
159
|
+
const rpcPath = 'rpc' === apiProtocol ? stringValue(topologyApp.api.rpcPath) : void 0;
|
|
160
|
+
if ('rpc' === apiProtocol && (!rpcPath || 'json' !== topologyApp.api.rpcSerialization)) throw new Error(`[backend-federation-build] Missing JSON RPC route metadata for ${id}.`);
|
|
161
|
+
const apiStem = stringValue(topologyApp.api.stem) ?? id;
|
|
162
|
+
const backendName = createBackendName(topologyApp, id);
|
|
163
|
+
const nodeOverlay = overlay.serverExecution?.[id]?.node;
|
|
164
|
+
if (!isRecord(nodeOverlay)) throw new Error(`[backend-federation-build] Missing declared Node server execution for ${id}.`);
|
|
165
|
+
const manifestUrl = rebaseDefaultLocalUrl(stringValue(nodeOverlay?.manifestUrl) ?? `http://localhost:${defaultPort}/${backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_MANIFEST_FILE}`, defaultPort, publicOrigin);
|
|
166
|
+
const containerEntry = rebaseDefaultLocalUrl(stringValue(nodeOverlay?.containerEntry) ?? `http://localhost:${defaultPort}/${backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_REMOTE_ENTRY_FILE}`, defaultPort, publicOrigin);
|
|
167
|
+
const configuredRemoteType = stringValue(nodeOverlay?.remoteType) ?? stringValue(topologyApp.backendFederation?.executionSurfaces?.node?.remoteType);
|
|
131
168
|
if (void 0 !== configuredRemoteType && 'commonjs-module' !== configuredRemoteType) throw new Error(`[backend-federation-build] Node backend federation remoteType must be "commonjs-module"; received "${configuredRemoteType}" for ${id}.`);
|
|
132
169
|
if (!new URL(containerEntry).pathname.endsWith(`/${backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_REMOTE_ENTRY_FILE}`)) throw new Error(`[backend-federation-build] Node backend federation containerEntry must end with "/${backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_REMOTE_ENTRY_FILE}"; received "${containerEntry}" for ${id}.`);
|
|
133
170
|
const remoteType = 'commonjs-module';
|
|
134
|
-
const packageName = stringValue(
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
171
|
+
const packageName = stringValue(packageManifest.name);
|
|
172
|
+
const version = stringValue(packageManifest.version);
|
|
173
|
+
if (stringValue(topologyApp.package) !== packageName || !version) throw new Error(`[backend-federation-build] Topology package identity must match package.json for ${id}.`);
|
|
174
|
+
const declaredUiManifestUrl = stringValue(overlay.manifests?.[id]);
|
|
175
|
+
const uiManifestUrl = declaredUiManifestUrl ? rebaseDefaultLocalUrl(declaredUiManifestUrl, defaultPort, publicOrigin) : void 0;
|
|
176
|
+
const topologyDeliveryUnit = isRecord(topologyApp.deliveryUnit) ? {
|
|
177
|
+
unitId: stringValue(topologyApp.deliveryUnit.unitId),
|
|
178
|
+
buildMarker: stringValue(topologyApp.deliveryUnit.buildMarker),
|
|
179
|
+
sourceRevision: stringValue(topologyApp.deliveryUnit.sourceRevision),
|
|
180
|
+
packageName: stringValue(topologyApp.deliveryUnit.packageName),
|
|
181
|
+
version: stringValue(topologyApp.deliveryUnit.version)
|
|
142
182
|
} : void 0;
|
|
143
183
|
return {
|
|
144
184
|
id,
|
|
145
185
|
directory,
|
|
146
186
|
packageName,
|
|
187
|
+
version,
|
|
147
188
|
port,
|
|
148
189
|
apiPrefix,
|
|
190
|
+
apiProtocol,
|
|
191
|
+
rpcPath,
|
|
149
192
|
apiStem,
|
|
150
193
|
backendName,
|
|
151
194
|
manifestUrl,
|
|
152
195
|
containerEntry,
|
|
153
196
|
remoteType,
|
|
154
197
|
uiManifestUrl,
|
|
155
|
-
|
|
198
|
+
topologyDeliveryUnit
|
|
156
199
|
};
|
|
157
200
|
};
|
|
158
201
|
const findBackendFederationApp = async (workspaceRoot, appDirectory)=>{
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
202
|
+
const topologyPath = external_node_path_default().join(workspaceRoot, REFERENCE_TOPOLOGY_PATH);
|
|
203
|
+
const topology = await readJsonFile(topologyPath);
|
|
204
|
+
if (!isRecord(topology) || !Array.isArray(topology.verticals)) throw new Error(`[backend-federation-build] Invalid declared topology at ${topologyPath}.`);
|
|
205
|
+
const overlayPath = external_node_path_default().join(workspaceRoot, DEVELOPMENT_OVERLAY_PATH);
|
|
206
|
+
const overlay = await readJsonFile(overlayPath);
|
|
207
|
+
if (!isRecord(overlay) || !isRecord(overlay.ports)) throw new Error(`[backend-federation-build] Invalid development overlay at ${overlayPath}.`);
|
|
208
|
+
const packageManifest = await readJsonFile(external_node_path_default().join(appDirectory, 'package.json'));
|
|
209
|
+
for (const app of topology.verticals){
|
|
210
|
+
const resolved = createAppFromTopology(workspaceRoot, appDirectory, app, overlay, packageManifest);
|
|
164
211
|
if (resolved) return resolved;
|
|
165
212
|
}
|
|
213
|
+
throw new Error(`[backend-federation-build] ${appDirectory} is missing from the declared reference topology.`);
|
|
166
214
|
};
|
|
167
|
-
exports.
|
|
215
|
+
exports.DEVELOPMENT_OVERLAY_PATH = __webpack_exports__.DEVELOPMENT_OVERLAY_PATH;
|
|
216
|
+
exports.REFERENCE_TOPOLOGY_PATH = __webpack_exports__.REFERENCE_TOPOLOGY_PATH;
|
|
168
217
|
exports.buildArtifactPathFor = __webpack_exports__.buildArtifactPathFor;
|
|
169
|
-
exports.
|
|
218
|
+
exports.createAppFromTopology = __webpack_exports__.createAppFromTopology;
|
|
170
219
|
exports.createStampedDeliveryUnit = __webpack_exports__.createStampedDeliveryUnit;
|
|
171
220
|
exports.findBackendFederationApp = __webpack_exports__.findBackendFederationApp;
|
|
172
221
|
exports.findWorkspaceRoot = __webpack_exports__.findWorkspaceRoot;
|
|
@@ -174,9 +223,10 @@ exports.normalizeRelativePath = __webpack_exports__.normalizeRelativePath;
|
|
|
174
223
|
exports.readBuildIdentity = __webpack_exports__.readBuildIdentity;
|
|
175
224
|
exports.resolveWorkspaceSourceRevision = __webpack_exports__.resolveWorkspaceSourceRevision;
|
|
176
225
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
177
|
-
"
|
|
226
|
+
"DEVELOPMENT_OVERLAY_PATH",
|
|
227
|
+
"REFERENCE_TOPOLOGY_PATH",
|
|
178
228
|
"buildArtifactPathFor",
|
|
179
|
-
"
|
|
229
|
+
"createAppFromTopology",
|
|
180
230
|
"createStampedDeliveryUnit",
|
|
181
231
|
"findBackendFederationApp",
|
|
182
232
|
"findWorkspaceRoot",
|
|
@@ -59,35 +59,39 @@ const emitBackendFederationArtifacts = async (appDirectory, distDirectory)=>{
|
|
|
59
59
|
const app = await (0, external_config_js_namespaceObject.findBackendFederationApp)(workspaceRoot, appDirectory);
|
|
60
60
|
if (!app) return;
|
|
61
61
|
const buildIdentity = await (0, external_config_js_namespaceObject.readBuildIdentity)(appDirectory);
|
|
62
|
-
const
|
|
63
|
-
const
|
|
62
|
+
const topologyDeliveryUnit = app.topologyDeliveryUnit;
|
|
63
|
+
const hasTopologyDeliveryUnit = void 0 !== topologyDeliveryUnit && (void 0 !== topologyDeliveryUnit.unitId || void 0 !== topologyDeliveryUnit.buildMarker || void 0 !== topologyDeliveryUnit.packageName || void 0 !== topologyDeliveryUnit.version);
|
|
64
64
|
const hasBuildIdentity = void 0 !== buildIdentity.unitId || void 0 !== buildIdentity.buildVersion || void 0 !== buildIdentity.packageName || void 0 !== buildIdentity.version;
|
|
65
65
|
if (hasBuildIdentity) {
|
|
66
|
-
const
|
|
66
|
+
const topologyPath = external_node_path_default().join(workspaceRoot, external_config_js_namespaceObject.REFERENCE_TOPOLOGY_PATH);
|
|
67
67
|
const buildIdentityPath = (0, external_config_js_namespaceObject.buildArtifactPathFor)(appDirectory);
|
|
68
68
|
const mismatches = [];
|
|
69
69
|
const compare = (label, a, b, leftLabel = 'deliveryUnit')=>{
|
|
70
70
|
if (void 0 !== a && void 0 !== b && a !== b) mismatches.push(`${label}: ${leftLabel}=${a} vs ultramodern-build=${b}`);
|
|
71
71
|
};
|
|
72
72
|
compare('appId', app.id, buildIdentity.appId, 'topology');
|
|
73
|
-
if (
|
|
74
|
-
compare('unitId',
|
|
75
|
-
compare('buildMarker/build',
|
|
76
|
-
compare('packageName',
|
|
77
|
-
compare('version',
|
|
73
|
+
if (hasTopologyDeliveryUnit) {
|
|
74
|
+
compare('unitId', topologyDeliveryUnit?.unitId, buildIdentity.unitId);
|
|
75
|
+
compare('buildMarker/build', topologyDeliveryUnit?.buildMarker, buildIdentity.buildVersion);
|
|
76
|
+
compare('packageName', topologyDeliveryUnit?.packageName, buildIdentity.packageName);
|
|
77
|
+
compare('version', topologyDeliveryUnit?.version, buildIdentity.version);
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
compare('packageName', app.packageName, buildIdentity.packageName, 'package.json');
|
|
80
|
+
compare('packageName', topologyDeliveryUnit?.packageName, app.packageName, 'topology');
|
|
81
|
+
compare('version', app.version, buildIdentity.version, 'package.json');
|
|
82
|
+
compare('version', topologyDeliveryUnit?.version, app.version, 'topology');
|
|
83
|
+
if (mismatches.length > 0) throw new Error(`[backend-federation-build] Delivery-unit identity drift between ${topologyPath}, package.json and ${buildIdentityPath}: ${mismatches.join('; ')}`);
|
|
80
84
|
}
|
|
81
|
-
const unitId =
|
|
82
|
-
const generationBuildMarker =
|
|
85
|
+
const unitId = topologyDeliveryUnit?.unitId ?? buildIdentity.unitId;
|
|
86
|
+
const generationBuildMarker = topologyDeliveryUnit?.buildMarker ?? buildIdentity.buildVersion;
|
|
83
87
|
const sourceRevision = await (0, external_config_js_namespaceObject.resolveWorkspaceSourceRevision)(workspaceRoot);
|
|
84
88
|
const buildVersion = generationBuildMarker && unitId ? (0, release_identity_namespaceObject.resolveUltramodernReleaseIdentity)({
|
|
85
89
|
generationBuildMarker,
|
|
86
90
|
unitId,
|
|
87
91
|
workspaceRoot
|
|
88
92
|
}).buildMarker : void 0;
|
|
89
|
-
const packageName =
|
|
90
|
-
const version =
|
|
93
|
+
const packageName = app.packageName;
|
|
94
|
+
const version = app.version;
|
|
91
95
|
const deliveryUnit = (0, external_config_js_namespaceObject.createStampedDeliveryUnit)({
|
|
92
96
|
appId: app.id,
|
|
93
97
|
unitId,
|
|
@@ -46,11 +46,11 @@ const backend_federation_contracts_namespaceObject = require("@modern-js/backend
|
|
|
46
46
|
const utils_namespaceObject = require("@modern-js/utils");
|
|
47
47
|
const external_release_identity_js_namespaceObject = require("../release-identity.js");
|
|
48
48
|
const external_utils_js_namespaceObject = require("./utils.js");
|
|
49
|
-
const
|
|
49
|
+
const TOPOLOGY_PATH = 'topology/reference-topology.json';
|
|
50
50
|
const findWorkspaceRoot = async (appDirectory)=>{
|
|
51
51
|
let current = external_node_path_default().resolve(appDirectory);
|
|
52
52
|
for(;;){
|
|
53
|
-
if (await utils_namespaceObject.fs.pathExists(external_node_path_default().join(current,
|
|
53
|
+
if (await utils_namespaceObject.fs.pathExists(external_node_path_default().join(current, TOPOLOGY_PATH))) return current;
|
|
54
54
|
const parent = external_node_path_default().dirname(current);
|
|
55
55
|
if (parent === current) return;
|
|
56
56
|
current = parent;
|
|
@@ -67,36 +67,25 @@ const stampReleaseIdentity = (identity, workspaceRoot)=>{
|
|
|
67
67
|
})
|
|
68
68
|
};
|
|
69
69
|
};
|
|
70
|
-
const
|
|
70
|
+
const resolveTopologyApp = async (appDirectory)=>{
|
|
71
71
|
const workspaceRoot = await findWorkspaceRoot(appDirectory);
|
|
72
72
|
if (!workspaceRoot) return;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
if (!(0, external_utils_js_namespaceObject.isRecord)(compactConfig)) return {
|
|
82
|
-
workspaceRoot
|
|
83
|
-
};
|
|
84
|
-
const topology = (0, external_utils_js_namespaceObject.isRecord)(compactConfig.topology) ? compactConfig.topology : void 0;
|
|
85
|
-
const apps = Array.isArray(topology?.apps) ? topology.apps : void 0;
|
|
86
|
-
if (!apps) return {
|
|
87
|
-
app: compactConfig,
|
|
88
|
-
workspaceRoot
|
|
89
|
-
};
|
|
73
|
+
const topology = await utils_namespaceObject.fs.readJSON(external_node_path_default().join(workspaceRoot, TOPOLOGY_PATH));
|
|
74
|
+
if (!(0, external_utils_js_namespaceObject.isRecord)(topology) || !(0, external_utils_js_namespaceObject.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.');
|
|
75
|
+
const apps = [
|
|
76
|
+
topology.shell,
|
|
77
|
+
...topology.verticals,
|
|
78
|
+
...Array.isArray(topology.shells) ? topology.shells : []
|
|
79
|
+
];
|
|
90
80
|
const resolvedAppDirectory = external_node_path_default().resolve(appDirectory);
|
|
91
81
|
const app = apps.find((candidate)=>{
|
|
92
82
|
if (!(0, external_utils_js_namespaceObject.isRecord)(candidate)) return false;
|
|
93
83
|
const appPath = (0, backend_federation_contracts_namespaceObject.nonEmptyString)(candidate.path);
|
|
94
84
|
return void 0 !== appPath && external_node_path_default().resolve(workspaceRoot, appPath.replace(/^\.\/+/u, '')) === resolvedAppDirectory;
|
|
95
85
|
});
|
|
86
|
+
if (!(0, external_utils_js_namespaceObject.isRecord)(app)) throw new Error(`[cloudflare-delivery-unit] ${appDirectory} is missing from the declared reference topology.`);
|
|
96
87
|
return {
|
|
97
|
-
|
|
98
|
-
app
|
|
99
|
-
} : {},
|
|
88
|
+
app,
|
|
100
89
|
workspaceRoot
|
|
101
90
|
};
|
|
102
91
|
};
|
|
@@ -123,10 +112,11 @@ const createDeliveryUnitStamp = (identity, app)=>{
|
|
|
123
112
|
};
|
|
124
113
|
};
|
|
125
114
|
const resolveTopologyDeliveryUnit = async (appDirectory)=>{
|
|
126
|
-
const resolved = await
|
|
115
|
+
const resolved = await resolveTopologyApp(appDirectory);
|
|
127
116
|
if (!resolved?.app) return;
|
|
128
117
|
const identity = (0, backend_federation_contracts_namespaceObject.toDeliveryUnitIdentity)(resolved.app.deliveryUnit);
|
|
129
|
-
|
|
118
|
+
if (!identity) throw new Error('[cloudflare-delivery-unit] Declared app is missing a valid delivery-unit identity.');
|
|
119
|
+
return createDeliveryUnitStamp(stampReleaseIdentity(identity, resolved.workspaceRoot), resolved.app);
|
|
130
120
|
};
|
|
131
121
|
const resolveWorkerDeliveryUnitStamp = async (appDirectory)=>{
|
|
132
122
|
const buildArtifactPath = external_node_path_default().join(appDirectory, backend_federation_contracts_namespaceObject.ULTRAMODERN_BUILD_ARTIFACT_PATH);
|
|
@@ -137,7 +127,7 @@ const resolveWorkerDeliveryUnitStamp = async (appDirectory)=>{
|
|
|
137
127
|
identity = (0, backend_federation_contracts_namespaceObject.toDeliveryUnitIdentity)(artifact.deliveryUnit);
|
|
138
128
|
}
|
|
139
129
|
if (!identity) return;
|
|
140
|
-
const resolved = await
|
|
130
|
+
const resolved = await resolveTopologyApp(appDirectory);
|
|
141
131
|
if (resolved) identity = stampReleaseIdentity(identity, resolved.workspaceRoot);
|
|
142
132
|
return createDeliveryUnitStamp(identity, resolved?.app);
|
|
143
133
|
};
|
|
@@ -41,6 +41,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
41
41
|
});
|
|
42
42
|
const external_node_path_namespaceObject = require("node:path");
|
|
43
43
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
44
|
+
const backend_federation_contracts_namespaceObject = require("@modern-js/backend-federation-contracts");
|
|
44
45
|
const utils_namespaceObject = require("@modern-js/utils");
|
|
45
46
|
const external_cloudflare_output_plan_js_namespaceObject = require("../cloudflare-output-plan.js");
|
|
46
47
|
const index_js_namespaceObject = require("../cloudflare-output-verifier/index.js");
|
|
@@ -78,7 +79,7 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
|
|
|
78
79
|
await utils_namespaceObject.fs.remove(outputDirectory);
|
|
79
80
|
},
|
|
80
81
|
async writeOutput () {
|
|
81
|
-
if (releaseEnvelopeEnabled
|
|
82
|
+
if (releaseEnvelopeEnabled) await (0, framework_output_js_namespaceObject.emitFrameworkMicroVerticalReleaseEnvelope)({
|
|
82
83
|
apiOnly,
|
|
83
84
|
distDirectory,
|
|
84
85
|
target: 'cloudflare'
|
|
@@ -87,6 +88,11 @@ const createCloudflarePreset = ({ api, appContext, modernConfig })=>{
|
|
|
87
88
|
await utils_namespaceObject.fs.copy(distDirectory, publicDirectory, {
|
|
88
89
|
filter: (src)=>{
|
|
89
90
|
const relativePath = external_node_path_default().relative(distDirectory, src).replace(/\\/gu, '/');
|
|
91
|
+
if (apiOnly && '' !== relativePath && ![
|
|
92
|
+
backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_MANIFEST_FILE,
|
|
93
|
+
backend_federation_contracts_namespaceObject.BACKEND_FEDERATION_REMOTE_ENTRY_FILE,
|
|
94
|
+
backend_federation_contracts_namespaceObject.ULTRAMODERN_BUILD_ARTIFACT_FILE
|
|
95
|
+
].includes(relativePath)) return false;
|
|
90
96
|
return 'release' !== relativePath && !relativePath.startsWith('release/') && 'public' !== relativePath && !relativePath.startsWith('public/') && (0, external_worker_manifest_js_namespaceObject.shouldCopyToPublicAssets)(src, distDirectory, publicAssetExcludes);
|
|
91
97
|
}
|
|
92
98
|
});
|
|
@@ -46,6 +46,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
46
46
|
const external_node_path_namespaceObject = require("node:path");
|
|
47
47
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
48
48
|
const utils_namespaceObject = require("@modern-js/utils");
|
|
49
|
+
const external_cloudflare_output_contract_js_namespaceObject = require("../cloudflare-output-contract.js");
|
|
49
50
|
const external_artifacts_js_namespaceObject = require("./artifacts.js");
|
|
50
51
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
51
52
|
const external_i18n_worker_js_namespaceObject = require("./i18n-worker.js");
|
|
@@ -111,13 +112,18 @@ const createWorkerManifest = async (outputDirectory, modernConfig, appContext, d
|
|
|
111
112
|
const routeSpec = await (0, external_artifacts_js_namespaceObject.readRouteSpec)(outputDirectory);
|
|
112
113
|
const routes = await Promise.all(routeSpec.routes.map(async (route)=>{
|
|
113
114
|
const worker = 'string' == typeof route.worker ? route.worker : void 0;
|
|
115
|
+
const routeDataWorker = route.isSSR && 'string' == typeof route.entryName ? `${external_constants_js_namespaceObject.WORKER_BUNDLE_DIRECTORY}/${(0, external_cloudflare_output_contract_js_namespaceObject.getCloudflareWorkerRouteDataEntryName)(route.entryName)}.js` : void 0;
|
|
116
|
+
const hasRouteDataWorker = routeDataWorker ? await utils_namespaceObject.fs.pathExists(external_node_path_default().join(outputDirectory, routeDataWorker)) : false;
|
|
114
117
|
return {
|
|
115
118
|
urlPath: route.urlPath,
|
|
116
119
|
entryName: route.entryName,
|
|
117
120
|
entryPath: route.entryPath,
|
|
118
121
|
isSSR: Boolean(route.isSSR),
|
|
119
122
|
worker,
|
|
120
|
-
workerExists: worker ? await utils_namespaceObject.fs.pathExists(external_node_path_default().join(outputDirectory, worker)) : false
|
|
123
|
+
workerExists: worker ? await utils_namespaceObject.fs.pathExists(external_node_path_default().join(outputDirectory, worker)) : false,
|
|
124
|
+
...hasRouteDataWorker ? {
|
|
125
|
+
routeDataWorker
|
|
126
|
+
} : {}
|
|
121
127
|
};
|
|
122
128
|
}));
|
|
123
129
|
const bffPrefix = modernConfig.bff?.prefix;
|
|
@@ -177,9 +183,12 @@ const createWorkerManifest = async (outputDirectory, modernConfig, appContext, d
|
|
|
177
183
|
};
|
|
178
184
|
const createWorkerModuleLoaders = (manifest)=>{
|
|
179
185
|
const imports = new Map();
|
|
180
|
-
for (const route of manifest.routeSpec.routes)
|
|
181
|
-
|
|
182
|
-
|
|
186
|
+
for (const route of manifest.routeSpec.routes)for (const worker of [
|
|
187
|
+
route.workerExists ? route.worker : void 0,
|
|
188
|
+
route.routeDataWorker
|
|
189
|
+
])if (worker) {
|
|
190
|
+
const importPath = `../${String(worker).replace(/^\/+/u, '')}`;
|
|
191
|
+
imports.set(worker, `() => import(${JSON.stringify(importPath)})`);
|
|
183
192
|
}
|
|
184
193
|
if (manifest.bff?.worker) {
|
|
185
194
|
const importPath = `../${String(manifest.bff.worker).replace(/^\/+/u, '')}`;
|
|
@@ -45,12 +45,16 @@ const external_node_path_namespaceObject = require("node:path");
|
|
|
45
45
|
var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
|
|
46
46
|
const external_constants_js_namespaceObject = require("./constants.js");
|
|
47
47
|
const external_utils_js_namespaceObject = require("./utils.js");
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
48
|
+
const assertSupportedCompatibilityDate = (compatibilityDate, label)=>{
|
|
49
|
+
if ('string' != typeof compatibilityDate) throw new Error(`${label} must be a YYYY-MM-DD string.`);
|
|
50
|
+
if (!external_constants_js_namespaceObject.COMPATIBILITY_DATE_PATTERN.test(compatibilityDate)) throw new Error(`${label} must use YYYY-MM-DD, received ${JSON.stringify(compatibilityDate)}.`);
|
|
51
|
+
if (compatibilityDate < external_constants_js_namespaceObject.DEFAULT_COMPATIBILITY_DATE) throw new Error(`${label} must be ${external_constants_js_namespaceObject.DEFAULT_COMPATIBILITY_DATE} or later, the date the Cloudflare worker Node.js built-in contract is verified against; received ${JSON.stringify(compatibilityDate)}.`);
|
|
52
52
|
return compatibilityDate;
|
|
53
53
|
};
|
|
54
|
+
const getCompatibilityDate = (modernConfig, wranglerCompatibilityDate)=>{
|
|
55
|
+
if (void 0 !== wranglerCompatibilityDate) return assertSupportedCompatibilityDate(wranglerCompatibilityDate, 'deploy.worker.wrangler.compatibility_date');
|
|
56
|
+
return assertSupportedCompatibilityDate(modernConfig.deploy?.worker?.compatibilityDate?.trim() || external_constants_js_namespaceObject.DEFAULT_COMPATIBILITY_DATE, 'deploy.worker.compatibilityDate');
|
|
57
|
+
};
|
|
54
58
|
const getWorkerName = (appDirectory)=>{
|
|
55
59
|
const basename = external_node_path_default().basename(appDirectory);
|
|
56
60
|
return basename.replace(/[^a-zA-Z0-9-_]/g, '-') || 'modern-cloudflare-worker';
|
|
@@ -65,11 +69,11 @@ const getConfiguredWrangler = (modernConfig)=>{
|
|
|
65
69
|
if (!(0, external_utils_js_namespaceObject.isJsonRecord)(wrangler)) throw new Error('deploy.worker.wrangler must be a JSON object.');
|
|
66
70
|
return wrangler;
|
|
67
71
|
};
|
|
68
|
-
const createWranglerCompatibilityFlags = (configuredFlags)=>{
|
|
72
|
+
const createWranglerCompatibilityFlags = (configuredFlags, label = 'deploy.worker.wrangler.compatibility_flags')=>{
|
|
69
73
|
if (void 0 === configuredFlags) return [
|
|
70
74
|
...external_constants_js_namespaceObject.REQUIRED_COMPATIBILITY_FLAGS
|
|
71
75
|
];
|
|
72
|
-
if (!Array.isArray(configuredFlags) || configuredFlags.some((flag)=>'string' != typeof flag)) throw new Error(
|
|
76
|
+
if (!Array.isArray(configuredFlags) || configuredFlags.some((flag)=>'string' != typeof flag)) throw new Error(`${label} must be an array of strings.`);
|
|
73
77
|
return [
|
|
74
78
|
...new Set([
|
|
75
79
|
...configuredFlags,
|
|
@@ -77,6 +81,26 @@ const createWranglerCompatibilityFlags = (configuredFlags)=>{
|
|
|
77
81
|
])
|
|
78
82
|
];
|
|
79
83
|
};
|
|
84
|
+
const createWranglerEnvironments = (wranglerEnv)=>{
|
|
85
|
+
if (void 0 === wranglerEnv) return;
|
|
86
|
+
if (!(0, external_utils_js_namespaceObject.isJsonRecord)(wranglerEnv)) throw new Error('deploy.worker.wrangler.env must be an object.');
|
|
87
|
+
return Object.fromEntries(Object.entries(wranglerEnv).map(([name, environment])=>{
|
|
88
|
+
const label = `deploy.worker.wrangler.env.${name}`;
|
|
89
|
+
if (!(0, external_utils_js_namespaceObject.isJsonRecord)(environment)) throw new Error(`${label} must be an object.`);
|
|
90
|
+
return [
|
|
91
|
+
name,
|
|
92
|
+
{
|
|
93
|
+
...environment,
|
|
94
|
+
...void 0 === environment.compatibility_date ? {} : {
|
|
95
|
+
compatibility_date: assertSupportedCompatibilityDate(environment.compatibility_date, `${label}.compatibility_date`)
|
|
96
|
+
},
|
|
97
|
+
...void 0 === environment.compatibility_flags ? {} : {
|
|
98
|
+
compatibility_flags: createWranglerCompatibilityFlags(environment.compatibility_flags, `${label}.compatibility_flags`)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
];
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
80
104
|
const createWranglerAssetsConfig = (configuredAssets)=>{
|
|
81
105
|
if (void 0 !== configuredAssets && !(0, external_utils_js_namespaceObject.isJsonRecord)(configuredAssets)) throw new Error('deploy.worker.wrangler.assets must be an object.');
|
|
82
106
|
return {
|
|
@@ -173,17 +197,21 @@ const createWorkerManifestServiceBindings = (serviceBindings)=>{
|
|
|
173
197
|
};
|
|
174
198
|
const createWranglerConfig = (appDirectory, modernConfig)=>{
|
|
175
199
|
const wrangler = getConfiguredWrangler(modernConfig);
|
|
200
|
+
const environments = createWranglerEnvironments(wrangler.env);
|
|
176
201
|
const d1Databases = createWranglerD1Databases(modernConfig, wrangler.d1_databases);
|
|
177
202
|
const serviceBindings = createWorkerServiceBindings(modernConfig, wrangler.services);
|
|
178
203
|
const wranglerServices = createWranglerServices(serviceBindings);
|
|
179
204
|
return {
|
|
180
205
|
$schema: 'node_modules/wrangler/config-schema.json',
|
|
181
206
|
name: getConfiguredWorkerName(appDirectory, modernConfig),
|
|
182
|
-
compatibility_date: getCompatibilityDate(modernConfig),
|
|
183
207
|
...wrangler,
|
|
208
|
+
compatibility_date: getCompatibilityDate(modernConfig, wrangler.compatibility_date),
|
|
184
209
|
main: external_constants_js_namespaceObject.WORKER_ENTRY,
|
|
185
210
|
compatibility_flags: createWranglerCompatibilityFlags(wrangler.compatibility_flags),
|
|
186
211
|
assets: createWranglerAssetsConfig(wrangler.assets),
|
|
212
|
+
...void 0 === environments ? {} : {
|
|
213
|
+
env: environments
|
|
214
|
+
},
|
|
187
215
|
...void 0 === d1Databases ? {} : {
|
|
188
216
|
d1_databases: d1Databases
|
|
189
217
|
},
|