@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.11 → 3.9.0-ultramodern.13
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/build-config/remote-address.js +56 -0
- package/dist/cjs/cloudflare/delivery-unit.js +16 -26
- package/dist/cjs/cloudflare/index.js +7 -1
- package/dist/cjs/cloudflare-builder.js +13 -3
- package/dist/cjs/cloudflare-output-contract.js +1 -0
- 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/config.js +4 -0
- 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/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/build-config/remote-address.mjs +18 -0
- package/dist/esm/cloudflare/delivery-unit.mjs +16 -26
- package/dist/esm/cloudflare/index.mjs +7 -1
- package/dist/esm/cloudflare-builder.mjs +13 -3
- package/dist/esm/cloudflare-output-contract.mjs +1 -0
- 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/config.mjs +1 -0
- 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-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/build-config/remote-address.mjs +19 -0
- package/dist/esm-node/cloudflare/delivery-unit.mjs +16 -26
- package/dist/esm-node/cloudflare/index.mjs +7 -1
- package/dist/esm-node/cloudflare-builder.mjs +13 -3
- package/dist/esm-node/cloudflare-output-contract.mjs +1 -0
- 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/config.mjs +1 -0
- 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/types/backend-federation-build/codegen.d.ts +30 -0
- package/dist/types/backend-federation-build/config.d.ts +32 -13
- package/dist/types/build-config/remote-address.d.ts +3 -0
- package/dist/types/cloudflare/delivery-unit.d.ts +1 -1
- package/dist/types/cloudflare-builder.d.ts +1 -0
- package/dist/types/cloudflare-output-contract.d.ts +1 -1
- package/dist/types/config.d.ts +1 -0
- package/package.json +20 -19
- 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/build-config/remote-address.ts +31 -0
- package/src/cloudflare/delivery-unit.ts +39 -33
- package/src/cloudflare/index.ts +20 -6
- package/src/cloudflare-builder.ts +18 -4
- package/src/cloudflare-output-contract.ts +1 -0
- 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/config.ts +1 -0
- 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
|
@@ -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,
|
|
@@ -0,0 +1,56 @@
|
|
|
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
|
+
createRemoteManifestUrl: ()=>createRemoteManifestUrl
|
|
32
|
+
});
|
|
33
|
+
const surface_resolution_namespaceObject = require("@modern-js/surface-resolution");
|
|
34
|
+
const external_build_environment_js_namespaceObject = require("./build-environment.js");
|
|
35
|
+
function createRemoteManifestUrl(options) {
|
|
36
|
+
const env = Object.fromEntries([
|
|
37
|
+
options.manifestEnv,
|
|
38
|
+
options.publicUrlEnv,
|
|
39
|
+
'MODERNJS_DEPLOY',
|
|
40
|
+
'ULTRAMODERN_CLOUDFLARE_WORKERS_DEV_SUBDOMAIN',
|
|
41
|
+
'ULTRAMODERN_CLOUDFLARE_REQUIRE_PUBLIC_URLS'
|
|
42
|
+
].map((name)=>[
|
|
43
|
+
name,
|
|
44
|
+
(0, external_build_environment_js_namespaceObject.getBuildConfigEnvironment)(name)
|
|
45
|
+
]));
|
|
46
|
+
const address = (0, surface_resolution_namespaceObject.resolveBrowserManifestAddress)(env, options, (0, external_build_environment_js_namespaceObject.getBuildConfigEnvironment)('NODE_ENV') ?? 'production');
|
|
47
|
+
if (!address.ok) throw new Error(`Remote ${options.mfName}: ${address.reason}`);
|
|
48
|
+
return env[options.manifestEnv]?.trim() || `${options.mfName}@${address.manifestUrl}`;
|
|
49
|
+
}
|
|
50
|
+
exports.createRemoteManifestUrl = __webpack_exports__.createRemoteManifestUrl;
|
|
51
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
52
|
+
"createRemoteManifestUrl"
|
|
53
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
54
|
+
Object.defineProperty(exports, '__esModule', {
|
|
55
|
+
value: true
|
|
56
|
+
});
|
|
@@ -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
|
});
|
|
@@ -256,9 +256,9 @@ const prependBundlerChain = (environment, handler)=>{
|
|
|
256
256
|
};
|
|
257
257
|
const getWorkerEntries = (environment, normalizedConfig, appContext)=>{
|
|
258
258
|
const configuredEntries = environment.source?.entry;
|
|
259
|
-
if (!configuredEntries) return;
|
|
260
|
-
const entries = rewriteWorkerEntries(configuredEntries);
|
|
261
259
|
const effectApiEntry = getEffectBffEntry(normalizedConfig, appContext);
|
|
260
|
+
if (!configuredEntries && !effectApiEntry) return;
|
|
261
|
+
const entries = configuredEntries ? rewriteWorkerEntries(configuredEntries) : {};
|
|
262
262
|
return effectApiEntry ? {
|
|
263
263
|
...entries,
|
|
264
264
|
[BFF_EFFECT_WORKER_ENTRY_NAME]: [
|
|
@@ -338,7 +338,14 @@ const createCloudflareBundlerChain = (appContext, workerEntryNames)=>{
|
|
|
338
338
|
};
|
|
339
339
|
function getCloudflareBuilderEnvironments({ appContext, environments, normalizedConfig, resolveDeployProvider = resolveStdEnvDeployProvider }) {
|
|
340
340
|
if (!isCloudflareWorkerDeploy(normalizedConfig, resolveDeployProvider)) return environments;
|
|
341
|
-
const workerEnvironment = environments[builder_namespaceObject.SERVICE_WORKER_ENVIRONMENT_NAME]
|
|
341
|
+
const workerEnvironment = environments[builder_namespaceObject.SERVICE_WORKER_ENVIRONMENT_NAME] ?? (appContext.apiOnly ? {
|
|
342
|
+
output: {
|
|
343
|
+
target: 'web-worker'
|
|
344
|
+
},
|
|
345
|
+
source: {
|
|
346
|
+
entry: {}
|
|
347
|
+
}
|
|
348
|
+
} : void 0);
|
|
342
349
|
if (!workerEnvironment) return environments;
|
|
343
350
|
const workerEntries = getWorkerEntries(workerEnvironment, normalizedConfig, appContext);
|
|
344
351
|
if (!workerEntries) return environments;
|
|
@@ -354,6 +361,9 @@ function getCloudflareBuilderEnvironments({ appContext, environments, normalized
|
|
|
354
361
|
entry: workerEntries
|
|
355
362
|
}
|
|
356
363
|
}, createCloudflareBundlerChain(appContext, Object.keys(workerEntries)));
|
|
364
|
+
if (appContext.apiOnly) return {
|
|
365
|
+
[builder_namespaceObject.SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment
|
|
366
|
+
};
|
|
357
367
|
return {
|
|
358
368
|
...environments,
|
|
359
369
|
[builder_namespaceObject.SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment
|
|
@@ -56,30 +56,32 @@ const verifyDeliveryUnitIdentity = (issues, manifest, manifestPath, declared)=>{
|
|
|
56
56
|
]){
|
|
57
57
|
const marker = stamped.surfaces[surface];
|
|
58
58
|
const expected = declared?.surfaces?.[surface];
|
|
59
|
-
if (
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
59
|
+
if (expected || marker) {
|
|
60
|
+
if (declared?.surfaces && !expected) {
|
|
61
|
+
if (marker) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
62
|
+
code: 'delivery-unit-drift',
|
|
63
|
+
message: `Cloudflare worker manifest declares an unexpected ${surface} delivery-unit surface for this topology profile.`,
|
|
64
|
+
path: manifestPath
|
|
65
|
+
});
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (!marker || 'object' != typeof marker) {
|
|
69
|
+
(0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
70
|
+
code: 'missing-delivery-unit',
|
|
71
|
+
message: `Cloudflare worker manifest is missing the ${surface} delivery-unit surface marker.`,
|
|
72
|
+
path: manifestPath
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
for (const field of backend_federation_contracts_namespaceObject.DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
77
|
+
const markerValue = (0, backend_federation_contracts_namespaceObject.deliveryUnitIdentityFieldValue)(marker, field);
|
|
78
|
+
const stampedValue = (0, backend_federation_contracts_namespaceObject.deliveryUnitIdentityFieldValue)(stamped, field);
|
|
79
|
+
(0, external_issues_js_namespaceObject.assertEqual)(issues, markerValue, stampedValue, {
|
|
80
|
+
code: 'delivery-unit-drift',
|
|
81
|
+
message: `Cloudflare worker manifest ${surface} surface deliveryUnit.${field} must derive from one delivery-unit record (expected ${stampedValue ?? 'undefined'}, received ${markerValue ?? 'undefined'}).`,
|
|
82
|
+
path: manifestPath
|
|
83
|
+
});
|
|
84
|
+
}
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
};
|
|
@@ -118,6 +118,16 @@ const verifyCloudflareOutput = async (options)=>{
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
if (wrangler) {
|
|
121
|
+
if ('string' != typeof wrangler.name || 0 === wrangler.name.trim().length) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
122
|
+
code: 'invalid-wrangler',
|
|
123
|
+
message: 'wrangler.json name must be a non-empty worker name.',
|
|
124
|
+
path: wranglerPath
|
|
125
|
+
});
|
|
126
|
+
if ('string' != typeof wrangler.compatibility_date || !/^\d{4}-\d{2}-\d{2}$/u.test(wrangler.compatibility_date)) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
127
|
+
code: 'invalid-wrangler',
|
|
128
|
+
message: 'wrangler.json compatibility_date must use YYYY-MM-DD.',
|
|
129
|
+
path: wranglerPath
|
|
130
|
+
});
|
|
121
131
|
(0, external_issues_js_namespaceObject.assertEqual)(issues, wrangler.main, outputPlan.wrangler.main, {
|
|
122
132
|
code: 'invalid-wrangler',
|
|
123
133
|
message: `wrangler.json main must be ${outputPlan.wrangler.main}.`,
|
|
@@ -74,6 +74,52 @@ const verifyManifestShape = (issues, manifest, manifestPath)=>{
|
|
|
74
74
|
message: 'Cloudflare output manifest routeSpec.routes must be array.',
|
|
75
75
|
path: manifestPath
|
|
76
76
|
});
|
|
77
|
+
const security = manifest.security;
|
|
78
|
+
if (security && 'object' == typeof security && 'boolean' == typeof security.enabled) {
|
|
79
|
+
const cors = security.cors;
|
|
80
|
+
if (!cors || 'object' != typeof cors || 'boolean' != typeof cors.assets || !Array.isArray(cors.allowedOrigins) || !Array.isArray(cors.allowedMethods) || !Array.isArray(cors.allowedHeaders)) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
81
|
+
code: 'invalid-manifest',
|
|
82
|
+
message: 'Cloudflare output manifest security.cors is incomplete.',
|
|
83
|
+
path: manifestPath
|
|
84
|
+
});
|
|
85
|
+
if (security.enabled) {
|
|
86
|
+
const headers = security.headers;
|
|
87
|
+
const csp = security.contentSecurityPolicy;
|
|
88
|
+
const noindex = security.noindex;
|
|
89
|
+
if (!headers || 'object' != typeof headers || ![
|
|
90
|
+
'string',
|
|
91
|
+
'boolean'
|
|
92
|
+
].includes(typeof headers.referrerPolicy) || ![
|
|
93
|
+
'string',
|
|
94
|
+
'boolean'
|
|
95
|
+
].includes(typeof headers.contentTypeOptions) || ![
|
|
96
|
+
'string',
|
|
97
|
+
'boolean'
|
|
98
|
+
].includes(typeof headers.permissionsPolicy)) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
99
|
+
code: 'invalid-manifest',
|
|
100
|
+
message: 'Cloudflare output manifest security.headers is incomplete.',
|
|
101
|
+
path: manifestPath
|
|
102
|
+
});
|
|
103
|
+
if (!csp || ![
|
|
104
|
+
'off',
|
|
105
|
+
'report-only',
|
|
106
|
+
'enforce'
|
|
107
|
+
].includes(csp.mode) || !csp.directives || 'object' != typeof csp.directives || Array.isArray(csp.directives) || Object.values(csp.directives).some((value)=>!Array.isArray(value) || value.some((entry)=>'string' != typeof entry))) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
108
|
+
code: 'invalid-manifest',
|
|
109
|
+
message: 'Cloudflare output manifest security.contentSecurityPolicy is invalid.',
|
|
110
|
+
path: manifestPath
|
|
111
|
+
});
|
|
112
|
+
if (!noindex || 'boolean' != typeof noindex.workersDev || 'boolean' != typeof noindex.localhost || !Array.isArray(noindex.previewHostnames)) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
113
|
+
code: 'invalid-manifest',
|
|
114
|
+
message: 'Cloudflare output manifest security.noindex is incomplete.',
|
|
115
|
+
path: manifestPath
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
} else (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
119
|
+
code: 'invalid-manifest',
|
|
120
|
+
message: 'Cloudflare output manifest security.enabled must be a boolean.',
|
|
121
|
+
path: manifestPath
|
|
122
|
+
});
|
|
77
123
|
if (manifest.bff?.runtimeFramework === 'effect') (0, external_issues_js_namespaceObject.assertEqual)(issues, manifest.bff.dispatcherExport, constants_js_namespaceObject.BFF_EFFECT_WORKER_DISPATCHER_EXPORT, {
|
|
78
124
|
code: 'invalid-manifest',
|
|
79
125
|
message: `Cloudflare Effect BFF manifest dispatcherExport must be ${constants_js_namespaceObject.BFF_EFFECT_WORKER_DISPATCHER_EXPORT}.`,
|
|
@@ -128,7 +128,13 @@ const verifyCloudflareOutputMutationPolicy = async (options)=>{
|
|
|
128
128
|
const files = (await Promise.all(options.scanRoots.map((scanRoot)=>walkFiles(external_node_path_default().resolve(scanRoot))))).flat();
|
|
129
129
|
for (const file of files){
|
|
130
130
|
if (excludedFiles.has(file)) continue;
|
|
131
|
-
|
|
131
|
+
let source;
|
|
132
|
+
try {
|
|
133
|
+
source = await promises_default().readFile(file, 'utf-8');
|
|
134
|
+
} catch (error) {
|
|
135
|
+
if ('ENOENT' === error.code) continue;
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
132
138
|
for (const forbidden of FORBIDDEN_MUTATION_PATTERNS)if (forbidden.pattern.test(source)) (0, external_issues_js_namespaceObject.addIssue)(issues, {
|
|
133
139
|
code: forbidden.code,
|
|
134
140
|
message: forbidden.message,
|