@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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 +267 -0
- package/dist/cjs/backend-federation-build/config.js +239 -0
- package/dist/cjs/backend-federation-build/emit.js +154 -0
- package/dist/cjs/backend-federation-build/index.js +53 -0
- package/dist/cjs/build-config/build-environment.js +129 -0
- package/dist/cjs/build-config/precompress/plugin.js +124 -0
- package/dist/cjs/build-config/precompress/types.js +18 -0
- package/dist/cjs/build-config/public.js +43 -0
- package/dist/cjs/build-config/remote-address.js +58 -0
- package/dist/cjs/cloudflare/artifacts.js +8 -19
- package/dist/cjs/cloudflare/constants.js +1 -1
- package/dist/cjs/cloudflare/delivery-unit.js +23 -42
- package/dist/cjs/cloudflare/index.js +10 -2
- package/dist/cjs/cloudflare/worker-manifest.js +13 -4
- package/dist/cjs/cloudflare/wrangler-config.js +35 -7
- package/dist/cjs/cloudflare-builder.js +252 -75
- package/dist/cjs/cloudflare-output-contract.js +69 -3
- package/dist/cjs/cloudflare-output-verifier/identity.js +29 -27
- 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 +14 -6
- package/dist/cjs/config.js +34 -1
- package/dist/cjs/deploy-output/npmAliases.js +251 -0
- package/dist/cjs/deploy-output/plugin.js +97 -0
- package/dist/cjs/deploy-output/public-assets.js +146 -0
- package/dist/cjs/deploy-output/target.js +104 -0
- package/dist/cjs/deploy-output/trace-files.js +90 -0
- package/dist/cjs/native-type-checker.js +193 -0
- package/dist/cjs/policy-defaults.js +101 -0
- package/dist/cjs/release-envelope/framework-output.js +153 -79
- package/dist/cjs/release-envelope/index.js +10 -4
- package/dist/cjs/release-envelope/plugin.js +18 -13
- package/dist/cjs/release-identity.js +5 -6
- package/dist/cjs/runtime-package-resolution.js +118 -0
- package/dist/cjs/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- 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 +216 -0
- package/dist/esm/backend-federation-build/config.mjs +163 -0
- package/dist/esm/backend-federation-build/emit.mjs +103 -0
- package/dist/esm/backend-federation-build/index.mjs +1 -0
- package/dist/esm/build-config/build-environment.mjs +88 -0
- package/dist/esm/build-config/precompress/plugin.mjs +76 -0
- package/dist/esm/build-config/precompress/types.mjs +0 -0
- package/dist/esm/build-config/public.mjs +1 -0
- package/dist/esm/build-config/remote-address.mjs +20 -0
- package/dist/esm/cloudflare/artifacts.mjs +8 -19
- package/dist/esm/cloudflare/constants.mjs +1 -1
- package/dist/esm/cloudflare/delivery-unit.mjs +17 -36
- package/dist/esm/cloudflare/index.mjs +10 -2
- package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm/cloudflare-builder.mjs +246 -75
- package/dist/esm/cloudflare-output-contract.mjs +59 -2
- package/dist/esm/cloudflare-output-verifier/identity.mjs +27 -25
- 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 +15 -7
- package/dist/esm/config.mjs +3 -0
- package/dist/esm/deploy-output/npmAliases.mjs +199 -0
- package/dist/esm/deploy-output/plugin.mjs +46 -0
- package/dist/esm/deploy-output/public-assets.mjs +82 -0
- package/dist/esm/deploy-output/target.mjs +57 -0
- package/dist/esm/deploy-output/trace-files.mjs +38 -0
- package/dist/esm/native-type-checker.mjs +142 -0
- package/dist/esm/policy-defaults.mjs +45 -0
- package/dist/esm/release-envelope/framework-output.mjs +130 -56
- package/dist/esm/release-envelope/index.mjs +10 -4
- package/dist/esm/release-envelope/plugin.mjs +18 -13
- package/dist/esm/release-identity.mjs +5 -6
- package/dist/esm/runtime-package-resolution.mjs +60 -0
- package/dist/esm/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- 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 +217 -0
- package/dist/esm-node/backend-federation-build/config.mjs +164 -0
- package/dist/esm-node/backend-federation-build/emit.mjs +104 -0
- package/dist/esm-node/backend-federation-build/index.mjs +2 -0
- package/dist/esm-node/build-config/build-environment.mjs +89 -0
- package/dist/esm-node/build-config/precompress/plugin.mjs +77 -0
- package/dist/esm-node/build-config/precompress/types.mjs +1 -0
- package/dist/esm-node/build-config/public.mjs +2 -0
- package/dist/esm-node/build-config/remote-address.mjs +21 -0
- package/dist/esm-node/cloudflare/artifacts.mjs +8 -19
- package/dist/esm-node/cloudflare/constants.mjs +1 -1
- package/dist/esm-node/cloudflare/delivery-unit.mjs +17 -36
- package/dist/esm-node/cloudflare/index.mjs +10 -2
- 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 +246 -75
- package/dist/esm-node/cloudflare-output-contract.mjs +59 -2
- package/dist/esm-node/cloudflare-output-verifier/identity.mjs +27 -25
- 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 +15 -7
- package/dist/esm-node/config.mjs +3 -0
- package/dist/esm-node/deploy-output/npmAliases.mjs +200 -0
- package/dist/esm-node/deploy-output/plugin.mjs +49 -0
- package/dist/esm-node/deploy-output/public-assets.mjs +83 -0
- package/dist/esm-node/deploy-output/target.mjs +58 -0
- package/dist/esm-node/deploy-output/trace-files.mjs +39 -0
- package/dist/esm-node/native-type-checker.mjs +143 -0
- package/dist/esm-node/policy-defaults.mjs +46 -0
- package/dist/esm-node/release-envelope/framework-output.mjs +130 -56
- package/dist/esm-node/release-envelope/index.mjs +10 -4
- package/dist/esm-node/release-envelope/plugin.mjs +18 -13
- package/dist/esm-node/release-identity.mjs +5 -6
- package/dist/esm-node/runtime-package-resolution.mjs +61 -0
- package/dist/esm-node/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- 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 +116 -0
- package/dist/types/backend-federation-build/config.d.ts +121 -0
- package/dist/types/backend-federation-build/emit.d.ts +21 -0
- package/dist/types/backend-federation-build/index.d.ts +2 -0
- package/dist/types/build-config/build-environment.d.ts +14 -0
- package/dist/types/build-config/precompress/plugin.d.ts +4 -0
- package/dist/types/build-config/precompress/types.d.ts +19 -0
- package/dist/types/build-config/public.d.ts +2 -0
- package/dist/types/build-config/remote-address.d.ts +3 -0
- package/dist/types/cloudflare/artifacts.d.ts +7 -6
- package/dist/types/cloudflare/constants.d.ts +1 -1
- package/dist/types/cloudflare/delivery-unit.d.ts +3 -3
- package/dist/types/cloudflare/worker-manifest.d.ts +2 -2
- package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
- package/dist/types/cloudflare-builder.d.ts +49 -9
- package/dist/types/cloudflare-output-contract.d.ts +4 -1
- package/dist/types/cloudflare-output-verifier/identity.d.ts +1 -1
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
- package/dist/types/config.d.ts +29 -1
- package/dist/types/deploy-output/npmAliases.d.ts +14 -0
- package/dist/types/deploy-output/plugin.d.ts +35 -0
- package/dist/types/deploy-output/public-assets.d.ts +51 -0
- package/dist/types/deploy-output/target.d.ts +29 -0
- package/dist/types/deploy-output/trace-files.d.ts +17 -0
- package/dist/types/native-type-checker.d.ts +15 -0
- package/dist/types/policy-defaults.d.ts +46 -0
- package/dist/types/precompress/LICENSE +20 -0
- package/dist/types/precompress/index.d.ts +76 -0
- package/dist/types/release-envelope/framework-output.d.ts +8 -3
- package/dist/types/release-envelope/plugin.d.ts +7 -7
- package/dist/types/runtime-package-resolution.d.ts +28 -0
- package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
- package/package.json +97 -15
- package/src/backend-federation-build/codegen.ts +254 -0
- package/src/backend-federation-build/config.ts +492 -0
- package/src/backend-federation-build/emit.ts +213 -0
- package/src/backend-federation-build/index.ts +2 -0
- package/src/build-config/build-environment.ts +160 -0
- package/src/build-config/precompress/plugin.ts +140 -0
- package/src/build-config/precompress/types.ts +26 -0
- package/src/build-config/public.ts +5 -0
- package/src/build-config/remote-address.ts +33 -0
- package/src/cloudflare/artifacts.ts +22 -43
- package/src/cloudflare/constants.ts +1 -1
- package/src/cloudflare/delivery-unit.ts +42 -53
- package/src/cloudflare/index.ts +24 -11
- package/src/cloudflare/worker-manifest.ts +20 -3
- package/src/cloudflare/wrangler-config.ts +86 -10
- package/src/cloudflare-builder.ts +475 -151
- package/src/cloudflare-output-contract.ts +70 -0
- package/src/cloudflare-output-verifier/identity.ts +5 -1
- 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 +32 -14
- package/src/config.ts +34 -6
- package/src/deploy-output/npmAliases.ts +382 -0
- package/src/deploy-output/plugin.ts +86 -0
- package/src/deploy-output/public-assets.ts +224 -0
- package/src/deploy-output/target.ts +106 -0
- package/src/deploy-output/trace-files.ts +67 -0
- package/src/native-type-checker.ts +183 -0
- package/src/policy-defaults.ts +127 -0
- package/src/release-envelope/framework-output.ts +346 -94
- package/src/release-envelope/index.ts +26 -5
- package/src/release-envelope/plugin.ts +43 -40
- package/src/release-identity.ts +13 -2
- package/src/runtime-package-resolution.ts +115 -0
- package/src/templates/cloudflare-entry.001-bootstrap-security.mjs +0 -3
- package/src/templates/cloudflare-entry.002-assets-routes.mjs +1 -1
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +5 -1
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +98 -10
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/cjs/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/dist/esm-node/templates/cloudflare-worker-path.mjs +0 -98
- package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +0 -5
- package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +0 -48
- package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +0 -13
- package/dist/types/templates/cloudflare-worker-path.d.mts +0 -21
- package/src/templates/cloudflare-worker-fs-promises.mjs +0 -11
- package/src/templates/cloudflare-worker-loadable-server.mjs +0 -281
- package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +0 -14
- package/src/templates/cloudflare-worker-path.mjs +0 -98
|
@@ -1,16 +1,52 @@
|
|
|
1
1
|
import node_fs from "node:fs";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
2
|
+
import { createRequire, isBuiltin } from "node:module";
|
|
3
3
|
import node_path from "node:path";
|
|
4
4
|
import { SERVICE_WORKER_ENVIRONMENT_NAME } from "@modern-js/builder";
|
|
5
5
|
import { isProd } from "@modern-js/utils";
|
|
6
|
-
import {
|
|
7
|
-
import { CLOUDFLARE_WORKER_NODE_BUILTINS } from "./cloudflare-output-contract.mjs";
|
|
6
|
+
import { CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT, CLOUDFLARE_WORKER_NODE_BUILTINS, CLOUDFLARE_WORKER_PLATFORM_MODULES, getCloudflareWorkerRouteDataEntryName } from "./cloudflare-output-contract.mjs";
|
|
8
7
|
import { getTemplatePath } from "./read-template.mjs";
|
|
9
8
|
const moduleRequire = createRequire(import.meta.url);
|
|
10
9
|
const BFF_EFFECT_WORKER_ENTRY_NAME = '__modern_bff_effect';
|
|
11
10
|
const BFF_EFFECT_WORKER_RUNTIME_QUERY = 'modern-bff-runtime';
|
|
12
|
-
const
|
|
13
|
-
const
|
|
11
|
+
const SERVER_LOADER_COMBINED_FILE = 'server-loader-combined.js';
|
|
12
|
+
const ROUTE_SERVER_LOADERS_FILE = 'route-server-loaders.js';
|
|
13
|
+
const WORKER_ROUTE_DATA_FILE = 'cloudflare-worker-route-data.js';
|
|
14
|
+
const WORKER_ROUTE_DATA_TEMPLATE = 'cloudflare-worker-route-data.mjs';
|
|
15
|
+
const DATA_LOADER_CLIENT_TRANSFORM = /plugin-data-loader[\\/](?:.+[\\/])?loader\.[cm]?js$/u;
|
|
16
|
+
const WORKER_DEPENDENCY_CONDITIONS = [
|
|
17
|
+
[
|
|
18
|
+
'esm',
|
|
19
|
+
'import'
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
'wasm',
|
|
23
|
+
'import'
|
|
24
|
+
],
|
|
25
|
+
[
|
|
26
|
+
'loaderImport',
|
|
27
|
+
'import'
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
'worker',
|
|
31
|
+
'import'
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
'commonjs',
|
|
35
|
+
'require'
|
|
36
|
+
],
|
|
37
|
+
[
|
|
38
|
+
'amd',
|
|
39
|
+
'require'
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
'loader',
|
|
43
|
+
'require'
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
'unknown',
|
|
47
|
+
'require'
|
|
48
|
+
]
|
|
49
|
+
];
|
|
14
50
|
const JS_OR_TS_EXTENSIONS = new Set([
|
|
15
51
|
'.js',
|
|
16
52
|
'.jsx',
|
|
@@ -70,19 +106,154 @@ const resolvePackageFile = (packageName, filePath, paths)=>{
|
|
|
70
106
|
const setAliasIfPresent = (alias, name, value)=>{
|
|
71
107
|
if (value) alias.set(name, value);
|
|
72
108
|
};
|
|
73
|
-
const getCloudflareWorkerNodeExternals = ()=>Object.fromEntries(
|
|
74
|
-
|
|
109
|
+
const getCloudflareWorkerNodeExternals = ()=>Object.fromEntries([
|
|
110
|
+
...CLOUDFLARE_WORKER_NODE_BUILTINS.flatMap((builtin)=>{
|
|
111
|
+
const nodeBuiltin = `node:${builtin}`;
|
|
112
|
+
const external = `module-import ${nodeBuiltin}`;
|
|
113
|
+
return isBuiltin(builtin) ? [
|
|
114
|
+
[
|
|
115
|
+
builtin,
|
|
116
|
+
external
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
nodeBuiltin,
|
|
120
|
+
external
|
|
121
|
+
]
|
|
122
|
+
] : [
|
|
123
|
+
[
|
|
124
|
+
nodeBuiltin,
|
|
125
|
+
external
|
|
126
|
+
]
|
|
127
|
+
];
|
|
128
|
+
}),
|
|
129
|
+
...CLOUDFLARE_WORKER_PLATFORM_MODULES.map((platformModule)=>[
|
|
130
|
+
platformModule,
|
|
131
|
+
`module-import ${platformModule}`
|
|
132
|
+
])
|
|
133
|
+
]);
|
|
134
|
+
const getPackageNameFromRequest = (request)=>{
|
|
135
|
+
if (request.startsWith('.') || request.startsWith('/') || request.includes(':') || node_path.isAbsolute(request)) return;
|
|
136
|
+
const segments = request.split('/');
|
|
137
|
+
return request.startsWith('@') ? segments.length > 1 ? `${segments[0]}/${segments[1]}` : void 0 : segments[0];
|
|
138
|
+
};
|
|
139
|
+
const isRedirectedByAliasField = (manifest, aliasFields, request)=>aliasFields.some((field)=>{
|
|
140
|
+
let value = manifest;
|
|
141
|
+
for (const key of 'string' == typeof field ? [
|
|
142
|
+
field
|
|
143
|
+
] : field)value = value && 'object' == typeof value ? value[key] : void 0;
|
|
144
|
+
return 'object' == typeof value && null !== value && Object.hasOwn(value, request);
|
|
145
|
+
});
|
|
146
|
+
const findOwningPackageManifest = (directory, cache)=>{
|
|
147
|
+
if (cache.has(directory)) return cache.get(directory);
|
|
148
|
+
let manifest;
|
|
149
|
+
const packageJsonPath = node_path.join(directory, 'package.json');
|
|
150
|
+
if (node_fs.existsSync(packageJsonPath)) try {
|
|
151
|
+
manifest = JSON.parse(node_fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
152
|
+
} catch {
|
|
153
|
+
manifest = void 0;
|
|
154
|
+
}
|
|
155
|
+
else if (node_path.dirname(directory) !== directory) manifest = findOwningPackageManifest(node_path.dirname(directory), cache);
|
|
156
|
+
cache.set(directory, manifest);
|
|
157
|
+
return manifest;
|
|
158
|
+
};
|
|
159
|
+
const isPackageInstalled = (packageName, directory, moduleDirectories)=>moduleDirectories.some((moduleDirectory)=>{
|
|
160
|
+
if (node_path.isAbsolute(moduleDirectory)) return node_fs.existsSync(node_path.join(moduleDirectory, packageName));
|
|
161
|
+
let current = directory;
|
|
162
|
+
while(true){
|
|
163
|
+
if (node_fs.existsSync(node_path.join(current, moduleDirectory, packageName))) return true;
|
|
164
|
+
const parent = node_path.dirname(current);
|
|
165
|
+
if (parent === current) return false;
|
|
166
|
+
current = parent;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
const createAbsentOptionalDependencyFilter = (isRedirected = ()=>false, moduleDirectories = [
|
|
170
|
+
'node_modules'
|
|
171
|
+
], aliasFields = [])=>{
|
|
172
|
+
const manifests = new Map();
|
|
173
|
+
return (request, context)=>{
|
|
174
|
+
const packageName = getPackageNameFromRequest(request);
|
|
175
|
+
if (!packageName || !context || isRedirected(request)) return false;
|
|
176
|
+
const manifest = findOwningPackageManifest(context, manifests);
|
|
177
|
+
if (!manifest) return false;
|
|
178
|
+
const optional = manifest.peerDependenciesMeta?.[packageName]?.optional === true || Object.hasOwn(manifest.optionalDependencies ?? {}, packageName);
|
|
179
|
+
return optional && !isRedirectedByAliasField(manifest, aliasFields, request) && !isPackageInstalled(packageName, context, moduleDirectories);
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
const getAliasNames = (alias)=>alias ? Array.isArray(alias) ? alias.map((entry)=>entry.onlyModule ? `${entry.name}$` : entry.name) : Object.keys(alias) : [];
|
|
183
|
+
const getExternalMatchers = (externals)=>{
|
|
184
|
+
if (Array.isArray(externals)) return externals.flatMap(getExternalMatchers);
|
|
185
|
+
if ('string' == typeof externals) return [
|
|
186
|
+
(request)=>request === externals
|
|
187
|
+
];
|
|
188
|
+
if (externals instanceof RegExp) return [
|
|
189
|
+
(request)=>{
|
|
190
|
+
externals.lastIndex = 0;
|
|
191
|
+
return externals.test(request);
|
|
192
|
+
}
|
|
193
|
+
];
|
|
194
|
+
if (externals && 'object' == typeof externals) {
|
|
195
|
+
const names = new Set(Object.entries(externals).filter(([, value])=>false !== value).map(([name])=>name));
|
|
75
196
|
return [
|
|
76
|
-
|
|
77
|
-
builtin,
|
|
78
|
-
`module-import ${nodeBuiltin}`
|
|
79
|
-
],
|
|
80
|
-
[
|
|
81
|
-
nodeBuiltin,
|
|
82
|
-
`module-import ${nodeBuiltin}`
|
|
83
|
-
]
|
|
197
|
+
(request)=>names.has(request)
|
|
84
198
|
];
|
|
85
|
-
}
|
|
199
|
+
}
|
|
200
|
+
return [];
|
|
201
|
+
};
|
|
202
|
+
const createRequestRedirectMatcher = (options)=>{
|
|
203
|
+
const aliasNames = [
|
|
204
|
+
...getAliasNames(options.resolve?.alias),
|
|
205
|
+
...getAliasNames(options.resolve?.fallback)
|
|
206
|
+
];
|
|
207
|
+
const externalMatchers = getExternalMatchers(options.externals);
|
|
208
|
+
return (request)=>externalMatchers.some((matches)=>matches(request)) || aliasNames.some((name)=>name.endsWith('$') ? request === name.slice(0, -1) : request === name || request.startsWith(`${name}/`));
|
|
209
|
+
};
|
|
210
|
+
const getFunctionExternals = (externals)=>Array.isArray(externals) ? externals.flatMap(getFunctionExternals) : 'function' == typeof externals ? [
|
|
211
|
+
externals
|
|
212
|
+
] : [];
|
|
213
|
+
const callFunctionExternal = (external, data)=>new Promise((resolve, reject)=>{
|
|
214
|
+
const returned = external(data, (error, result)=>error ? reject(error) : resolve(result));
|
|
215
|
+
if (null !== returned && 'object' == typeof returned && 'function' == typeof returned.then) returned.then(resolve, reject);
|
|
216
|
+
else if (1 === external.length) resolve(returned);
|
|
217
|
+
});
|
|
218
|
+
const claimsByFunctionExternal = async (externals, data)=>{
|
|
219
|
+
for (const external of externals)try {
|
|
220
|
+
const result = await callFunctionExternal(external, data);
|
|
221
|
+
if (null != result && false !== result) return true;
|
|
222
|
+
} catch {
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
};
|
|
227
|
+
const PLUGIN_NAME = 'AbsentOptionalDependencyPlugin';
|
|
228
|
+
class AbsentOptionalDependencyPlugin {
|
|
229
|
+
apply(compiler) {
|
|
230
|
+
const isAbsent = createAbsentOptionalDependencyFilter(createRequestRedirectMatcher(compiler.options), compiler.options.resolve.modules, compiler.options.resolve.aliasFields);
|
|
231
|
+
const functionExternals = getFunctionExternals(compiler.options.externals);
|
|
232
|
+
compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (factory)=>{
|
|
233
|
+
factory.hooks.beforeResolve.tapPromise(PLUGIN_NAME, async (data)=>{
|
|
234
|
+
if (!isAbsent(data.request, data.context)) return;
|
|
235
|
+
const claimed = await claimsByFunctionExternal(functionExternals, {
|
|
236
|
+
context: data.context,
|
|
237
|
+
contextInfo: {
|
|
238
|
+
issuer: data.contextInfo.issuer,
|
|
239
|
+
issuerLayer: data.contextInfo.issuerLayer ?? null
|
|
240
|
+
},
|
|
241
|
+
getResolve: (options)=>{
|
|
242
|
+
const resolver = factory.getResolver('normal', options ?? {});
|
|
243
|
+
return (context, request, callback)=>{
|
|
244
|
+
if (callback) return void resolver.resolve({}, context, request, {}, callback);
|
|
245
|
+
return new Promise((resolve, reject)=>{
|
|
246
|
+
resolver.resolve({}, context, request, {}, (error, result)=>error ? reject(error) : resolve(result || void 0));
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
request: data.request
|
|
251
|
+
});
|
|
252
|
+
return claimed ? void 0 : false;
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
86
257
|
const normalizeWorkerOutputName = (name)=>node_path.posix.normalize(name.replace(/\\/gu, '/')).toLowerCase();
|
|
87
258
|
const reserveWorkerChunkName = (baseName, reservedOutputNames)=>{
|
|
88
259
|
let name = baseName;
|
|
@@ -132,11 +303,8 @@ function applyCloudflareWorkerRspackConfig(chain, workerEntryNames) {
|
|
|
132
303
|
chain.optimization.runtimeChunk(config.optimization.runtimeChunk);
|
|
133
304
|
chain.optimization.splitChunks(config.optimization.splitChunks);
|
|
134
305
|
}
|
|
135
|
-
function
|
|
136
|
-
const
|
|
137
|
-
chain.plugins.delete('plugin-module-federation');
|
|
138
|
-
chain.resolve.alias.set(`${MF_SSR_DATA_FETCH_RUNTIME_PLUGIN}$`, runtimePlugin);
|
|
139
|
-
chain.resolve.alias.set(`${MF_SSR_DEV_RUNTIME_PLUGIN}$`, runtimePlugin);
|
|
306
|
+
function removeCloudflareWorkerDataLoaderClientTransform(chain) {
|
|
307
|
+
for (const [name, rule] of Object.entries(chain.module.rules.entries() ?? {}))if (rule.uses.values().some((use)=>DATA_LOADER_CLIENT_TRANSFORM.test(String(use.get('loader'))))) chain.module.rules.delete(name);
|
|
140
308
|
}
|
|
141
309
|
const getEffectBffEntry = (normalizedConfig, appContext)=>{
|
|
142
310
|
if (!normalizedConfig.bff || 'hono' === normalizedConfig.bff.runtimeFramework) return;
|
|
@@ -147,18 +315,6 @@ const getEffectBffEntry = (normalizedConfig, appContext)=>{
|
|
|
147
315
|
}
|
|
148
316
|
return resolveJsOrTsEntry(node_path.resolve(appContext.apiDirectory, 'index'));
|
|
149
317
|
};
|
|
150
|
-
const CLOUDFLARE_DEPLOY_PROVIDERS = new Set([
|
|
151
|
-
'cloudflare',
|
|
152
|
-
'cloudflare_pages',
|
|
153
|
-
'cloudflare_workers'
|
|
154
|
-
]);
|
|
155
|
-
const resolveStdEnvDeployProvider = ()=>provider;
|
|
156
|
-
const isCloudflareWorkerDeploy = (normalizedConfig, resolveDeployProvider)=>{
|
|
157
|
-
const explicitTarget = normalizedConfig.deploy?.target || process.env.MODERNJS_DEPLOY;
|
|
158
|
-
if (explicitTarget) return 'cloudflare' === explicitTarget;
|
|
159
|
-
const detectedProvider = resolveDeployProvider();
|
|
160
|
-
return detectedProvider ? CLOUDFLARE_DEPLOY_PROVIDERS.has(detectedProvider) : false;
|
|
161
|
-
};
|
|
162
318
|
const rewriteWorkerEntryPath = (entry)=>entry.replace('index.jsx', 'index.server.jsx').replace('bootstrap.server.jsx', 'index.server.jsx').replace('bootstrap.jsx', 'index.server.jsx');
|
|
163
319
|
const rewriteWorkerEntryDescription = (description)=>{
|
|
164
320
|
const entryImport = description.import;
|
|
@@ -203,11 +359,40 @@ const prependBundlerChain = (environment, handler)=>{
|
|
|
203
359
|
}
|
|
204
360
|
};
|
|
205
361
|
};
|
|
362
|
+
const createWorkerRouteDataModule = ()=>[
|
|
363
|
+
`import { routes } from './${ROUTE_SERVER_LOADERS_FILE}';`,
|
|
364
|
+
`import { createRouteDataRequestHandler } from ${JSON.stringify(getTemplatePath(WORKER_ROUTE_DATA_TEMPLATE))};`,
|
|
365
|
+
'',
|
|
366
|
+
`export const ${CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT} =`,
|
|
367
|
+
' createRouteDataRequestHandler(routes);',
|
|
368
|
+
''
|
|
369
|
+
].join('\n');
|
|
370
|
+
const getWorkerRouteDataEntries = (appContext)=>{
|
|
371
|
+
const { entrypoints, internalDirectory } = appContext;
|
|
372
|
+
if (!entrypoints || !internalDirectory) return {};
|
|
373
|
+
return Object.fromEntries(entrypoints.flatMap(({ entryName })=>{
|
|
374
|
+
const entryDirectory = node_path.join(internalDirectory, entryName);
|
|
375
|
+
if (!node_fs.existsSync(node_path.join(entryDirectory, SERVER_LOADER_COMBINED_FILE)) || !node_fs.existsSync(node_path.join(entryDirectory, ROUTE_SERVER_LOADERS_FILE))) return [];
|
|
376
|
+
const routeDataFile = node_path.join(entryDirectory, WORKER_ROUTE_DATA_FILE);
|
|
377
|
+
node_fs.writeFileSync(routeDataFile, createWorkerRouteDataModule());
|
|
378
|
+
return [
|
|
379
|
+
[
|
|
380
|
+
getCloudflareWorkerRouteDataEntryName(entryName),
|
|
381
|
+
[
|
|
382
|
+
routeDataFile
|
|
383
|
+
]
|
|
384
|
+
]
|
|
385
|
+
];
|
|
386
|
+
}));
|
|
387
|
+
};
|
|
206
388
|
const getWorkerEntries = (environment, normalizedConfig, appContext)=>{
|
|
207
389
|
const configuredEntries = environment.source?.entry;
|
|
208
|
-
if (!configuredEntries) return;
|
|
209
|
-
const entries = rewriteWorkerEntries(configuredEntries);
|
|
210
390
|
const effectApiEntry = getEffectBffEntry(normalizedConfig, appContext);
|
|
391
|
+
if (!configuredEntries && !effectApiEntry) return;
|
|
392
|
+
const entries = configuredEntries ? {
|
|
393
|
+
...rewriteWorkerEntries(configuredEntries),
|
|
394
|
+
...getWorkerRouteDataEntries(appContext)
|
|
395
|
+
} : {};
|
|
211
396
|
return effectApiEntry ? {
|
|
212
397
|
...entries,
|
|
213
398
|
[BFF_EFFECT_WORKER_ENTRY_NAME]: [
|
|
@@ -220,9 +405,6 @@ const createCloudflareBundlerChain = (appContext, workerEntryNames)=>{
|
|
|
220
405
|
appContext.appDirectory,
|
|
221
406
|
process.cwd()
|
|
222
407
|
];
|
|
223
|
-
const tanstackRouterSsrServerFile = resolvePackageFile('@tanstack/router-core', 'dist/esm/ssr/ssr-server.js', resolvePaths);
|
|
224
|
-
const runtimeRscWorkerFile = resolvePackageFile('@modern-js/runtime', 'dist/esm/rsc/server.worker.mjs', resolvePaths);
|
|
225
|
-
const renderRscWorkerFile = resolvePackageFile('@modern-js/render', 'dist/esm/rscWorker.mjs', resolvePaths);
|
|
226
408
|
const reactFile = resolvePackageFile('react', 'index.js', resolvePaths);
|
|
227
409
|
const reactJsxRuntimeFile = resolvePackageFile('react', 'jsx-runtime.js', resolvePaths);
|
|
228
410
|
const reactJsxDevRuntimeFile = resolvePackageFile('react', 'jsx-dev-runtime.js', resolvePaths);
|
|
@@ -232,62 +414,49 @@ const createCloudflareBundlerChain = (appContext, workerEntryNames)=>{
|
|
|
232
414
|
...resolvePaths,
|
|
233
415
|
getTemplatePath('')
|
|
234
416
|
]);
|
|
235
|
-
const loadableServerWorkerFile = getTemplatePath('cloudflare-worker-loadable-server.mjs');
|
|
236
|
-
const fsPromisesWorkerFile = getTemplatePath('cloudflare-worker-fs-promises.mjs');
|
|
237
|
-
const pathWorkerFile = getTemplatePath('cloudflare-worker-path.mjs');
|
|
238
417
|
const entryNames = [
|
|
239
418
|
...workerEntryNames
|
|
240
419
|
];
|
|
241
420
|
return (chain)=>{
|
|
242
421
|
applyCloudflareWorkerRspackConfig(chain, entryNames);
|
|
422
|
+
removeCloudflareWorkerDataLoaderClientTransform(chain);
|
|
243
423
|
chain.output.module(true).library({
|
|
244
424
|
type: 'module'
|
|
245
425
|
}).publicPath('/').chunkFormat('module').chunkLoading('import').workerChunkLoading('import');
|
|
426
|
+
chain.node.set('__dirname', 'mock').set('__filename', 'mock');
|
|
246
427
|
for (const condition of [
|
|
247
428
|
'workerd',
|
|
248
429
|
'worker',
|
|
249
430
|
'webpack',
|
|
250
431
|
isProd() ? 'production' : 'development',
|
|
251
|
-
'import',
|
|
252
|
-
'require',
|
|
253
432
|
'module'
|
|
254
433
|
])chain.resolve.conditionNames.add(condition);
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
if (renderRscWorkerFile) {
|
|
265
|
-
chain.resolve.alias.set('@modern-js/render/rsc$', renderRscWorkerFile);
|
|
266
|
-
chain.resolve.alias.set('@modern-js/render/rsc', renderRscWorkerFile);
|
|
267
|
-
chain.resolve.alias.set('@modern-js/render/rsc-worker$', renderRscWorkerFile);
|
|
268
|
-
}
|
|
434
|
+
for (const [dependencyType, condition] of WORKER_DEPENDENCY_CONDITIONS)chain.resolve.byDependency.set(dependencyType, {
|
|
435
|
+
conditionNames: [
|
|
436
|
+
condition,
|
|
437
|
+
'...'
|
|
438
|
+
]
|
|
439
|
+
});
|
|
440
|
+
chain.plugin('cloudflare-worker-absent-optional-dependencies').use(AbsentOptionalDependencyPlugin);
|
|
441
|
+
chain.plugins.delete('plugin-module-federation');
|
|
269
442
|
setAliasIfPresent(chain.resolve.alias, 'react$', reactFile);
|
|
270
443
|
setAliasIfPresent(chain.resolve.alias, 'react/jsx-runtime$', reactJsxRuntimeFile);
|
|
271
444
|
setAliasIfPresent(chain.resolve.alias, 'react/jsx-dev-runtime$', reactJsxDevRuntimeFile);
|
|
272
445
|
setAliasIfPresent(chain.resolve.alias, 'react-dom$', reactDomFile);
|
|
273
446
|
setAliasIfPresent(chain.resolve.alias, 'react-dom/server.edge$', reactDomServerEdgeFile);
|
|
274
447
|
setAliasIfPresent(chain.resolve.alias, '@loadable/component$', loadableComponentFile);
|
|
275
|
-
setAliasIfPresent(chain.resolve.alias, '@loadable/server$', loadableServerWorkerFile);
|
|
276
|
-
setAliasIfPresent(chain.resolve.alias, 'fs/promises$', fsPromisesWorkerFile);
|
|
277
|
-
setAliasIfPresent(chain.resolve.alias, 'node:fs/promises$', fsPromisesWorkerFile);
|
|
278
|
-
setAliasIfPresent(chain.resolve.alias, 'path$', pathWorkerFile);
|
|
279
|
-
setAliasIfPresent(chain.resolve.alias, 'node:path$', pathWorkerFile);
|
|
280
|
-
chain.resolve.alias.set('react-server-dom-rspack/server.node$', 'react-server-dom-rspack/server.edge');
|
|
281
|
-
chain.resolve.alias.set('react-server-dom-rspack/server.node', 'react-server-dom-rspack/server.edge');
|
|
282
|
-
chain.resolve.alias.set('react-server-dom-rspack/client.node$', 'react-server-dom-rspack/client.edge');
|
|
283
|
-
chain.resolve.alias.set('react-server-dom-rspack/client.node', 'react-server-dom-rspack/client.edge');
|
|
284
|
-
chain.resolve.fallback.set('fs', false);
|
|
285
|
-
chain.resolve.fallback.set('node:fs', false);
|
|
286
448
|
};
|
|
287
449
|
};
|
|
288
|
-
function getCloudflareBuilderEnvironments({ appContext, environments, normalizedConfig
|
|
289
|
-
if (
|
|
290
|
-
const workerEnvironment = environments[SERVICE_WORKER_ENVIRONMENT_NAME]
|
|
450
|
+
function getCloudflareBuilderEnvironments({ appContext, environments, normalizedConfig }) {
|
|
451
|
+
if (appContext.deployTarget?.target !== 'cloudflare') return environments;
|
|
452
|
+
const workerEnvironment = environments[SERVICE_WORKER_ENVIRONMENT_NAME] ?? (appContext.apiOnly ? {
|
|
453
|
+
output: {
|
|
454
|
+
target: 'web-worker'
|
|
455
|
+
},
|
|
456
|
+
source: {
|
|
457
|
+
entry: {}
|
|
458
|
+
}
|
|
459
|
+
} : void 0);
|
|
291
460
|
if (!workerEnvironment) return environments;
|
|
292
461
|
const workerEntries = getWorkerEntries(workerEnvironment, normalizedConfig, appContext);
|
|
293
462
|
if (!workerEntries) return environments;
|
|
@@ -303,6 +472,9 @@ function getCloudflareBuilderEnvironments({ appContext, environments, normalized
|
|
|
303
472
|
entry: workerEntries
|
|
304
473
|
}
|
|
305
474
|
}, createCloudflareBundlerChain(appContext, Object.keys(workerEntries)));
|
|
475
|
+
if (appContext.apiOnly) return {
|
|
476
|
+
[SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment
|
|
477
|
+
};
|
|
306
478
|
return {
|
|
307
479
|
...environments,
|
|
308
480
|
[SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment
|
|
@@ -313,15 +485,14 @@ function applyCloudflareBuilderEnvironments(options) {
|
|
|
313
485
|
environments: getCloudflareBuilderEnvironments(options)
|
|
314
486
|
};
|
|
315
487
|
}
|
|
316
|
-
const createCloudflareBuilderPlugin = (
|
|
488
|
+
const createCloudflareBuilderPlugin = ()=>({
|
|
317
489
|
name: '@modern-js/cloudflare-builder',
|
|
318
490
|
setup (api) {
|
|
319
491
|
api.modifyBuilderEnvironments(({ environments })=>applyCloudflareBuilderEnvironments({
|
|
320
492
|
appContext: api.getAppContext(),
|
|
321
493
|
environments,
|
|
322
|
-
normalizedConfig: api.getNormalizedConfig()
|
|
323
|
-
resolveDeployProvider
|
|
494
|
+
normalizedConfig: api.getNormalizedConfig()
|
|
324
495
|
}));
|
|
325
496
|
}
|
|
326
497
|
});
|
|
327
|
-
export { applyCloudflareBuilderEnvironments,
|
|
498
|
+
export { applyCloudflareBuilderEnvironments, applyCloudflareWorkerRspackConfig, claimsByFunctionExternal, createAbsentOptionalDependencyFilter, createCloudflareBuilderPlugin, createRequestRedirectMatcher, getCloudflareBuilderEnvironments, getCloudflareWorkerRspackConfig };
|
|
@@ -10,22 +10,79 @@ const CLOUDFLARE_RUNTIME_TYPE = 'cloudflare-module-worker';
|
|
|
10
10
|
const CLOUDFLARE_OUTPUT_PACKAGE_TYPE = 'module';
|
|
11
11
|
const CLOUDFLARE_WORKER_PACKAGE_TYPE = 'commonjs';
|
|
12
12
|
const CLOUDFLARE_WORKER_BUNDLE_FORMAT = 'commonjs';
|
|
13
|
+
const CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT = 'handleRouteDataRequest';
|
|
14
|
+
const getCloudflareWorkerRouteDataEntryName = (entryName)=>`${entryName}-server-loaders`;
|
|
13
15
|
const CLOUDFLARE_WORKER_NODE_BUILTINS = [
|
|
16
|
+
'_http_agent',
|
|
17
|
+
'_http_client',
|
|
18
|
+
'_http_common',
|
|
19
|
+
'_http_incoming',
|
|
20
|
+
'_http_outgoing',
|
|
21
|
+
'_http_server',
|
|
22
|
+
'_tls_common',
|
|
23
|
+
'_tls_wrap',
|
|
24
|
+
'assert',
|
|
25
|
+
'assert/strict',
|
|
14
26
|
'async_hooks',
|
|
15
27
|
'buffer',
|
|
28
|
+
'child_process',
|
|
29
|
+
'cluster',
|
|
30
|
+
'console',
|
|
31
|
+
'constants',
|
|
16
32
|
'crypto',
|
|
33
|
+
'dgram',
|
|
34
|
+
'diagnostics_channel',
|
|
35
|
+
'dns',
|
|
36
|
+
'dns/promises',
|
|
37
|
+
'domain',
|
|
17
38
|
'events',
|
|
39
|
+
'fs',
|
|
18
40
|
'fs/promises',
|
|
41
|
+
'http',
|
|
42
|
+
'http2',
|
|
43
|
+
'https',
|
|
44
|
+
'inspector',
|
|
45
|
+
'inspector/promises',
|
|
19
46
|
'module',
|
|
47
|
+
'net',
|
|
48
|
+
'os',
|
|
20
49
|
'path',
|
|
50
|
+
'path/posix',
|
|
51
|
+
'path/win32',
|
|
52
|
+
'perf_hooks',
|
|
21
53
|
'process',
|
|
54
|
+
'punycode',
|
|
55
|
+
'querystring',
|
|
56
|
+
'readline',
|
|
57
|
+
'readline/promises',
|
|
58
|
+
'repl',
|
|
59
|
+
'sqlite',
|
|
22
60
|
'stream',
|
|
61
|
+
'stream/consumers',
|
|
62
|
+
'stream/promises',
|
|
63
|
+
'stream/web',
|
|
23
64
|
'string_decoder',
|
|
65
|
+
'sys',
|
|
66
|
+
'test',
|
|
67
|
+
'timers',
|
|
68
|
+
'timers/promises',
|
|
69
|
+
'tls',
|
|
70
|
+
'trace_events',
|
|
71
|
+
'tty',
|
|
24
72
|
'url',
|
|
25
|
-
'util'
|
|
73
|
+
'util',
|
|
74
|
+
'util/types',
|
|
75
|
+
'v8',
|
|
76
|
+
'vm',
|
|
77
|
+
'wasi',
|
|
78
|
+
'worker_threads',
|
|
79
|
+
'zlib'
|
|
80
|
+
];
|
|
81
|
+
const CLOUDFLARE_WORKER_PLATFORM_MODULES = [
|
|
82
|
+
'cloudflare:sockets'
|
|
26
83
|
];
|
|
27
84
|
const CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS = [
|
|
28
85
|
'nodejs_compat',
|
|
29
86
|
'global_fetch_strictly_public'
|
|
30
87
|
];
|
|
31
|
-
export { CLOUDFLARE_ASSETS_BINDING, CLOUDFLARE_OUTPUT_PACKAGE_FILE, CLOUDFLARE_OUTPUT_PACKAGE_TYPE, CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY, CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS, CLOUDFLARE_RUNTIME_TYPE, CLOUDFLARE_WORKER_BUNDLE_DIRECTORY, CLOUDFLARE_WORKER_BUNDLE_FORMAT, CLOUDFLARE_WORKER_ENTRY, CLOUDFLARE_WORKER_MANIFEST, CLOUDFLARE_WORKER_NODE_BUILTINS, CLOUDFLARE_WORKER_PACKAGE_FILE, CLOUDFLARE_WORKER_PACKAGE_TYPE, CLOUDFLARE_WRANGLER_CONFIG_FILE };
|
|
88
|
+
export { CLOUDFLARE_ASSETS_BINDING, CLOUDFLARE_OUTPUT_PACKAGE_FILE, CLOUDFLARE_OUTPUT_PACKAGE_TYPE, CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY, CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS, CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT, CLOUDFLARE_RUNTIME_TYPE, CLOUDFLARE_WORKER_BUNDLE_DIRECTORY, CLOUDFLARE_WORKER_BUNDLE_FORMAT, CLOUDFLARE_WORKER_ENTRY, CLOUDFLARE_WORKER_MANIFEST, CLOUDFLARE_WORKER_NODE_BUILTINS, CLOUDFLARE_WORKER_PACKAGE_FILE, CLOUDFLARE_WORKER_PACKAGE_TYPE, CLOUDFLARE_WORKER_PLATFORM_MODULES, CLOUDFLARE_WRANGLER_CONFIG_FILE, getCloudflareWorkerRouteDataEntryName };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DELIVERY_UNIT_IDENTITY_FIELDS, deliveryUnitIdentityFieldValue } from "@modern-js/
|
|
1
|
+
import { DELIVERY_UNIT_IDENTITY_FIELDS, deliveryUnitIdentityFieldValue } from "@modern-js/backend-federation-contracts";
|
|
2
2
|
import { addIssue, assertEqual } from "./issues.mjs";
|
|
3
3
|
const verifyDeliveryUnitIdentity = (issues, manifest, manifestPath, declared)=>{
|
|
4
4
|
const stamped = manifest?.deliveryUnit;
|
|
@@ -24,30 +24,32 @@ const verifyDeliveryUnitIdentity = (issues, manifest, manifestPath, declared)=>{
|
|
|
24
24
|
]){
|
|
25
25
|
const marker = stamped.surfaces[surface];
|
|
26
26
|
const expected = declared?.surfaces?.[surface];
|
|
27
|
-
if (
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
27
|
+
if (expected || marker) {
|
|
28
|
+
if (declared?.surfaces && !expected) {
|
|
29
|
+
if (marker) addIssue(issues, {
|
|
30
|
+
code: 'delivery-unit-drift',
|
|
31
|
+
message: `Cloudflare worker manifest declares an unexpected ${surface} delivery-unit surface for this topology profile.`,
|
|
32
|
+
path: manifestPath
|
|
33
|
+
});
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (!marker || 'object' != typeof marker) {
|
|
37
|
+
addIssue(issues, {
|
|
38
|
+
code: 'missing-delivery-unit',
|
|
39
|
+
message: `Cloudflare worker manifest is missing the ${surface} delivery-unit surface marker.`,
|
|
40
|
+
path: manifestPath
|
|
41
|
+
});
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
45
|
+
const markerValue = deliveryUnitIdentityFieldValue(marker, field);
|
|
46
|
+
const stampedValue = deliveryUnitIdentityFieldValue(stamped, field);
|
|
47
|
+
assertEqual(issues, markerValue, stampedValue, {
|
|
48
|
+
code: 'delivery-unit-drift',
|
|
49
|
+
message: `Cloudflare worker manifest ${surface} surface deliveryUnit.${field} must derive from one delivery-unit record (expected ${stampedValue ?? 'undefined'}, received ${markerValue ?? 'undefined'}).`,
|
|
50
|
+
path: manifestPath
|
|
51
|
+
});
|
|
52
|
+
}
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
};
|
|
@@ -72,6 +72,16 @@ const verifyCloudflareOutput = async (options)=>{
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
if (wrangler) {
|
|
75
|
+
if ('string' != typeof wrangler.name || 0 === wrangler.name.trim().length) addIssue(issues, {
|
|
76
|
+
code: 'invalid-wrangler',
|
|
77
|
+
message: 'wrangler.json name must be a non-empty worker name.',
|
|
78
|
+
path: wranglerPath
|
|
79
|
+
});
|
|
80
|
+
if ('string' != typeof wrangler.compatibility_date || !/^\d{4}-\d{2}-\d{2}$/u.test(wrangler.compatibility_date)) addIssue(issues, {
|
|
81
|
+
code: 'invalid-wrangler',
|
|
82
|
+
message: 'wrangler.json compatibility_date must use YYYY-MM-DD.',
|
|
83
|
+
path: wranglerPath
|
|
84
|
+
});
|
|
75
85
|
assertEqual(issues, wrangler.main, outputPlan.wrangler.main, {
|
|
76
86
|
code: 'invalid-wrangler',
|
|
77
87
|
message: `wrangler.json main must be ${outputPlan.wrangler.main}.`,
|
|
@@ -42,6 +42,52 @@ const verifyManifestShape = (issues, manifest, manifestPath)=>{
|
|
|
42
42
|
message: 'Cloudflare output manifest routeSpec.routes must be array.',
|
|
43
43
|
path: manifestPath
|
|
44
44
|
});
|
|
45
|
+
const security = manifest.security;
|
|
46
|
+
if (security && 'object' == typeof security && 'boolean' == typeof security.enabled) {
|
|
47
|
+
const cors = security.cors;
|
|
48
|
+
if (!cors || 'object' != typeof cors || 'boolean' != typeof cors.assets || !Array.isArray(cors.allowedOrigins) || !Array.isArray(cors.allowedMethods) || !Array.isArray(cors.allowedHeaders)) addIssue(issues, {
|
|
49
|
+
code: 'invalid-manifest',
|
|
50
|
+
message: 'Cloudflare output manifest security.cors is incomplete.',
|
|
51
|
+
path: manifestPath
|
|
52
|
+
});
|
|
53
|
+
if (security.enabled) {
|
|
54
|
+
const headers = security.headers;
|
|
55
|
+
const csp = security.contentSecurityPolicy;
|
|
56
|
+
const noindex = security.noindex;
|
|
57
|
+
if (!headers || 'object' != typeof headers || ![
|
|
58
|
+
'string',
|
|
59
|
+
'boolean'
|
|
60
|
+
].includes(typeof headers.referrerPolicy) || ![
|
|
61
|
+
'string',
|
|
62
|
+
'boolean'
|
|
63
|
+
].includes(typeof headers.contentTypeOptions) || ![
|
|
64
|
+
'string',
|
|
65
|
+
'boolean'
|
|
66
|
+
].includes(typeof headers.permissionsPolicy)) addIssue(issues, {
|
|
67
|
+
code: 'invalid-manifest',
|
|
68
|
+
message: 'Cloudflare output manifest security.headers is incomplete.',
|
|
69
|
+
path: manifestPath
|
|
70
|
+
});
|
|
71
|
+
if (!csp || ![
|
|
72
|
+
'off',
|
|
73
|
+
'report-only',
|
|
74
|
+
'enforce'
|
|
75
|
+
].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))) addIssue(issues, {
|
|
76
|
+
code: 'invalid-manifest',
|
|
77
|
+
message: 'Cloudflare output manifest security.contentSecurityPolicy is invalid.',
|
|
78
|
+
path: manifestPath
|
|
79
|
+
});
|
|
80
|
+
if (!noindex || 'boolean' != typeof noindex.workersDev || 'boolean' != typeof noindex.localhost || !Array.isArray(noindex.previewHostnames)) addIssue(issues, {
|
|
81
|
+
code: 'invalid-manifest',
|
|
82
|
+
message: 'Cloudflare output manifest security.noindex is incomplete.',
|
|
83
|
+
path: manifestPath
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
} else addIssue(issues, {
|
|
87
|
+
code: 'invalid-manifest',
|
|
88
|
+
message: 'Cloudflare output manifest security.enabled must be a boolean.',
|
|
89
|
+
path: manifestPath
|
|
90
|
+
});
|
|
45
91
|
if (manifest.bff?.runtimeFramework === 'effect') assertEqual(issues, manifest.bff.dispatcherExport, BFF_EFFECT_WORKER_DISPATCHER_EXPORT, {
|
|
46
92
|
code: 'invalid-manifest',
|
|
47
93
|
message: `Cloudflare Effect BFF manifest dispatcherExport must be ${BFF_EFFECT_WORKER_DISPATCHER_EXPORT}.`,
|
|
@@ -84,7 +84,13 @@ const verifyCloudflareOutputMutationPolicy = async (options)=>{
|
|
|
84
84
|
const files = (await Promise.all(options.scanRoots.map((scanRoot)=>walkFiles(node_path.resolve(scanRoot))))).flat();
|
|
85
85
|
for (const file of files){
|
|
86
86
|
if (excludedFiles.has(file)) continue;
|
|
87
|
-
|
|
87
|
+
let source;
|
|
88
|
+
try {
|
|
89
|
+
source = await promises.readFile(file, 'utf-8');
|
|
90
|
+
} catch (error) {
|
|
91
|
+
if ('ENOENT' === error.code) continue;
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
88
94
|
for (const forbidden of FORBIDDEN_MUTATION_PATTERNS)if (forbidden.pattern.test(source)) addIssue(issues, {
|
|
89
95
|
code: forbidden.code,
|
|
90
96
|
message: forbidden.message,
|