@bleedingdev/modern-js-app-tools-extensions 3.8.3-ultramodern.2
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/cjs/cloudflare/artifacts.js +127 -0
- package/dist/cjs/cloudflare/constants.js +141 -0
- package/dist/cjs/cloudflare/delivery-unit.js +161 -0
- package/dist/cjs/cloudflare/i18n-worker.js +135 -0
- package/dist/cjs/cloudflare/index.js +156 -0
- package/dist/cjs/cloudflare/security-policies.js +205 -0
- package/dist/cjs/cloudflare/types.js +18 -0
- package/dist/cjs/cloudflare/utils.js +66 -0
- package/dist/cjs/cloudflare/worker-manifest.js +239 -0
- package/dist/cjs/cloudflare/wrangler-config.js +205 -0
- package/dist/cjs/cloudflare-builder.js +394 -0
- package/dist/cjs/cloudflare-output-contract.js +108 -0
- package/dist/cjs/cloudflare-output-plan.js +93 -0
- package/dist/cjs/cloudflare-output-verifier/identity.js +92 -0
- package/dist/cjs/cloudflare-output-verifier/index.js +188 -0
- package/dist/cjs/cloudflare-output-verifier/issues.js +54 -0
- package/dist/cjs/cloudflare-output-verifier/manifest.js +89 -0
- package/dist/cjs/cloudflare-output-verifier/mutation-policy.js +151 -0
- package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +378 -0
- package/dist/cjs/config.js +18 -0
- package/dist/cjs/css-extract-runtime-plugin.js +74 -0
- package/dist/cjs/index.js +125 -0
- package/dist/cjs/read-template.js +56 -0
- package/dist/cjs/release-envelope/canonical.js +68 -0
- package/dist/cjs/release-envelope/framework-output.js +649 -0
- package/dist/cjs/release-envelope/index.js +399 -0
- package/dist/cjs/release-envelope/plugin.js +102 -0
- package/dist/cjs/release-envelope/types.js +51 -0
- package/dist/cjs/release-identity.js +110 -0
- package/dist/cjs/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
- package/dist/cjs/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/cjs/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
- package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/cjs/templates/cloudflare-worker-fs-promises.mjs +11 -0
- package/dist/cjs/templates/cloudflare-worker-loadable-server.mjs +281 -0
- package/dist/cjs/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
- package/dist/cjs/templates/cloudflare-worker-path.mjs +98 -0
- package/dist/esm/cloudflare/artifacts.mjs +64 -0
- package/dist/esm/cloudflare/constants.mjs +34 -0
- package/dist/esm/cloudflare/delivery-unit.mjs +110 -0
- package/dist/esm/cloudflare/i18n-worker.mjs +97 -0
- package/dist/esm/cloudflare/index.mjs +108 -0
- package/dist/esm/cloudflare/security-policies.mjs +167 -0
- package/dist/esm/cloudflare/types.mjs +0 -0
- package/dist/esm/cloudflare/utils.mjs +12 -0
- package/dist/esm/cloudflare/worker-manifest.mjs +179 -0
- package/dist/esm/cloudflare/wrangler-config.mjs +151 -0
- package/dist/esm/cloudflare-builder.mjs +327 -0
- package/dist/esm/cloudflare-output-contract.mjs +31 -0
- package/dist/esm/cloudflare-output-plan.mjs +45 -0
- package/dist/esm/cloudflare-output-verifier/identity.mjs +54 -0
- package/dist/esm/cloudflare-output-verifier/index.mjs +133 -0
- package/dist/esm/cloudflare-output-verifier/issues.mjs +10 -0
- package/dist/esm/cloudflare-output-verifier/manifest.mjs +51 -0
- package/dist/esm/cloudflare-output-verifier/mutation-policy.mjs +99 -0
- package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +313 -0
- package/dist/esm/config.mjs +0 -0
- package/dist/esm/css-extract-runtime-plugin.mjs +32 -0
- package/dist/esm/index.mjs +10 -0
- package/dist/esm/read-template.mjs +5 -0
- package/dist/esm/release-envelope/canonical.mjs +21 -0
- package/dist/esm/release-envelope/framework-output.mjs +573 -0
- package/dist/esm/release-envelope/index.mjs +335 -0
- package/dist/esm/release-envelope/plugin.mjs +54 -0
- package/dist/esm/release-envelope/types.mjs +7 -0
- package/dist/esm/release-identity.mjs +66 -0
- package/dist/esm/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
- package/dist/esm/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/esm/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
- package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/esm/templates/cloudflare-worker-fs-promises.mjs +11 -0
- package/dist/esm/templates/cloudflare-worker-loadable-server.mjs +281 -0
- package/dist/esm/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
- package/dist/esm/templates/cloudflare-worker-path.mjs +98 -0
- package/dist/esm-node/cloudflare/artifacts.mjs +65 -0
- package/dist/esm-node/cloudflare/constants.mjs +35 -0
- package/dist/esm-node/cloudflare/delivery-unit.mjs +111 -0
- package/dist/esm-node/cloudflare/i18n-worker.mjs +98 -0
- package/dist/esm-node/cloudflare/index.mjs +109 -0
- package/dist/esm-node/cloudflare/security-policies.mjs +168 -0
- package/dist/esm-node/cloudflare/types.mjs +1 -0
- package/dist/esm-node/cloudflare/utils.mjs +13 -0
- package/dist/esm-node/cloudflare/worker-manifest.mjs +180 -0
- package/dist/esm-node/cloudflare/wrangler-config.mjs +152 -0
- package/dist/esm-node/cloudflare-builder.mjs +328 -0
- package/dist/esm-node/cloudflare-output-contract.mjs +32 -0
- package/dist/esm-node/cloudflare-output-plan.mjs +46 -0
- package/dist/esm-node/cloudflare-output-verifier/identity.mjs +55 -0
- package/dist/esm-node/cloudflare-output-verifier/index.mjs +134 -0
- package/dist/esm-node/cloudflare-output-verifier/issues.mjs +11 -0
- package/dist/esm-node/cloudflare-output-verifier/manifest.mjs +52 -0
- package/dist/esm-node/cloudflare-output-verifier/mutation-policy.mjs +100 -0
- package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +314 -0
- package/dist/esm-node/config.mjs +1 -0
- package/dist/esm-node/css-extract-runtime-plugin.mjs +33 -0
- package/dist/esm-node/index.mjs +11 -0
- package/dist/esm-node/read-template.mjs +9 -0
- package/dist/esm-node/release-envelope/canonical.mjs +22 -0
- package/dist/esm-node/release-envelope/framework-output.mjs +574 -0
- package/dist/esm-node/release-envelope/index.mjs +336 -0
- package/dist/esm-node/release-envelope/plugin.mjs +55 -0
- package/dist/esm-node/release-envelope/types.mjs +8 -0
- package/dist/esm-node/release-identity.mjs +67 -0
- package/dist/esm-node/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
- package/dist/esm-node/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/dist/esm-node/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
- package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/dist/esm-node/templates/cloudflare-worker-fs-promises.mjs +11 -0
- package/dist/esm-node/templates/cloudflare-worker-loadable-server.mjs +281 -0
- package/dist/esm-node/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
- package/dist/esm-node/templates/cloudflare-worker-path.mjs +98 -0
- package/dist/types/cloudflare/artifacts.d.ts +15 -0
- package/dist/types/cloudflare/constants.d.ts +24 -0
- package/dist/types/cloudflare/delivery-unit.d.ts +23 -0
- package/dist/types/cloudflare/i18n-worker.d.ts +22 -0
- package/dist/types/cloudflare/index.d.ts +2 -0
- package/dist/types/cloudflare/security-policies.d.ts +52 -0
- package/dist/types/cloudflare/types.d.ts +28 -0
- package/dist/types/cloudflare/utils.d.ts +6 -0
- package/dist/types/cloudflare/worker-manifest.d.ts +149 -0
- package/dist/types/cloudflare/wrangler-config.d.ts +51 -0
- package/dist/types/cloudflare-builder.d.ts +59 -0
- package/dist/types/cloudflare-output-contract.d.ts +14 -0
- package/dist/types/cloudflare-output-plan.d.ts +34 -0
- package/dist/types/cloudflare-output-verifier/identity.d.ts +8 -0
- package/dist/types/cloudflare-output-verifier/index.d.ts +18 -0
- package/dist/types/cloudflare-output-verifier/issues.d.ts +14 -0
- package/dist/types/cloudflare-output-verifier/manifest.d.ts +2 -0
- package/dist/types/cloudflare-output-verifier/mutation-policy.d.ts +14 -0
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +20 -0
- package/dist/types/config.d.ts +175 -0
- package/dist/types/css-extract-runtime-plugin.d.ts +6 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/read-template.d.ts +2 -0
- package/dist/types/release-envelope/canonical.d.ts +5 -0
- package/dist/types/release-envelope/framework-output.d.ts +32 -0
- package/dist/types/release-envelope/index.d.ts +6 -0
- package/dist/types/release-envelope/plugin.d.ts +30 -0
- package/dist/types/release-envelope/types.d.ts +62 -0
- package/dist/types/release-identity.d.ts +16 -0
- package/dist/types/templates/cloudflare-entry.001-bootstrap-security.d.mts +1 -0
- package/dist/types/templates/cloudflare-entry.002-assets-routes.d.mts +1 -0
- package/dist/types/templates/cloudflare-entry.003-i18n-locales.d.mts +1 -0
- package/dist/types/templates/cloudflare-entry.004-rendering-css.d.mts +1 -0
- package/dist/types/templates/cloudflare-entry.005-worker-dispatch.d.mts +1 -0
- package/dist/types/templates/cloudflare-entry.006-fetch-handler.d.mts +4 -0
- package/dist/types/templates/cloudflare-worker-fs-promises.d.mts +5 -0
- package/dist/types/templates/cloudflare-worker-loadable-server.d.mts +48 -0
- package/dist/types/templates/cloudflare-worker-mf-ssr-runtime-plugin.d.mts +13 -0
- package/dist/types/templates/cloudflare-worker-path.d.mts +21 -0
- package/package.json +131 -0
- package/src/cloudflare/artifacts.ts +165 -0
- package/src/cloudflare/constants.ts +50 -0
- package/src/cloudflare/delivery-unit.ts +195 -0
- package/src/cloudflare/i18n-worker.ts +197 -0
- package/src/cloudflare/index.ts +259 -0
- package/src/cloudflare/security-policies.ts +194 -0
- package/src/cloudflare/types.ts +33 -0
- package/src/cloudflare/utils.ts +40 -0
- package/src/cloudflare/worker-manifest.ts +313 -0
- package/src/cloudflare/wrangler-config.ts +338 -0
- package/src/cloudflare-builder.ts +653 -0
- package/src/cloudflare-output-contract.ts +30 -0
- package/src/cloudflare-output-plan.ts +108 -0
- package/src/cloudflare-output-verifier/identity.ts +87 -0
- package/src/cloudflare-output-verifier/index.ts +277 -0
- package/src/cloudflare-output-verifier/issues.ts +54 -0
- package/src/cloudflare-output-verifier/manifest.ts +76 -0
- package/src/cloudflare-output-verifier/mutation-policy.ts +159 -0
- package/src/cloudflare-output-verifier/worker-bundles.ts +664 -0
- package/src/config.ts +196 -0
- package/src/css-extract-runtime-plugin.ts +70 -0
- package/src/index.ts +10 -0
- package/src/read-template.ts +8 -0
- package/src/release-envelope/canonical.ts +58 -0
- package/src/release-envelope/framework-output.ts +1121 -0
- package/src/release-envelope/index.ts +656 -0
- package/src/release-envelope/plugin.ts +125 -0
- package/src/release-envelope/types.ts +83 -0
- package/src/release-identity.ts +134 -0
- package/src/templates/cloudflare-entry.001-bootstrap-security.mjs +251 -0
- package/src/templates/cloudflare-entry.002-assets-routes.mjs +191 -0
- package/src/templates/cloudflare-entry.003-i18n-locales.mjs +514 -0
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +1194 -0
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +421 -0
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +93 -0
- package/src/templates/cloudflare-worker-fs-promises.mjs +11 -0
- package/src/templates/cloudflare-worker-loadable-server.mjs +281 -0
- package/src/templates/cloudflare-worker-mf-ssr-runtime-plugin.mjs +14 -0
- package/src/templates/cloudflare-worker-path.mjs +98 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { ASSETS_BINDING, COMPATIBILITY_DATE_PATTERN, DEFAULT_COMPATIBILITY_DATE, PUBLIC_ASSETS_DIRECTORY, REQUIRED_COMPATIBILITY_FLAGS, WORKER_ENTRY } from "./constants.mjs";
|
|
3
|
+
import { isJsonRecord, normalizeRelativePath } from "./utils.mjs";
|
|
4
|
+
const getCompatibilityDate = (modernConfig)=>{
|
|
5
|
+
const configuredDate = modernConfig.deploy?.worker?.compatibilityDate?.trim();
|
|
6
|
+
const compatibilityDate = configuredDate || DEFAULT_COMPATIBILITY_DATE;
|
|
7
|
+
if (!COMPATIBILITY_DATE_PATTERN.test(compatibilityDate)) throw new Error(`deploy.worker.compatibilityDate must use YYYY-MM-DD, received ${JSON.stringify(compatibilityDate)}.`);
|
|
8
|
+
return compatibilityDate;
|
|
9
|
+
};
|
|
10
|
+
const getWorkerName = (appDirectory)=>{
|
|
11
|
+
const basename = node_path.basename(appDirectory);
|
|
12
|
+
return basename.replace(/[^a-zA-Z0-9-_]/g, '-') || 'modern-cloudflare-worker';
|
|
13
|
+
};
|
|
14
|
+
const getConfiguredWorkerName = (appDirectory, modernConfig)=>{
|
|
15
|
+
const configuredName = modernConfig.deploy?.worker?.name?.trim();
|
|
16
|
+
return configuredName || getWorkerName(appDirectory);
|
|
17
|
+
};
|
|
18
|
+
const getConfiguredWrangler = (modernConfig)=>{
|
|
19
|
+
const wrangler = modernConfig.deploy?.worker?.wrangler;
|
|
20
|
+
if (void 0 === wrangler) return {};
|
|
21
|
+
if (!isJsonRecord(wrangler)) throw new Error('deploy.worker.wrangler must be a JSON object.');
|
|
22
|
+
return wrangler;
|
|
23
|
+
};
|
|
24
|
+
const createWranglerCompatibilityFlags = (configuredFlags)=>{
|
|
25
|
+
if (void 0 === configuredFlags) return [
|
|
26
|
+
...REQUIRED_COMPATIBILITY_FLAGS
|
|
27
|
+
];
|
|
28
|
+
if (!Array.isArray(configuredFlags) || configuredFlags.some((flag)=>'string' != typeof flag)) throw new Error('deploy.worker.wrangler.compatibility_flags must be an array of strings.');
|
|
29
|
+
return [
|
|
30
|
+
...new Set([
|
|
31
|
+
...configuredFlags,
|
|
32
|
+
...REQUIRED_COMPATIBILITY_FLAGS
|
|
33
|
+
])
|
|
34
|
+
];
|
|
35
|
+
};
|
|
36
|
+
const createWranglerAssetsConfig = (configuredAssets)=>{
|
|
37
|
+
if (void 0 !== configuredAssets && !isJsonRecord(configuredAssets)) throw new Error('deploy.worker.wrangler.assets must be an object.');
|
|
38
|
+
return {
|
|
39
|
+
...isJsonRecord(configuredAssets) ? configuredAssets : {},
|
|
40
|
+
directory: `./${PUBLIC_ASSETS_DIRECTORY}`,
|
|
41
|
+
binding: ASSETS_BINDING,
|
|
42
|
+
run_worker_first: true
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
const assertNonEmptyString = (value, label)=>{
|
|
46
|
+
if ('string' != typeof value || 0 === value.trim().length) throw new Error(`${label} must be a non-empty string.`);
|
|
47
|
+
return value.trim();
|
|
48
|
+
};
|
|
49
|
+
const normalizeD1Database = (database, index)=>{
|
|
50
|
+
const binding = assertNonEmptyString(database.binding, `deploy.worker.d1Databases[${index}].binding`);
|
|
51
|
+
const databaseName = assertNonEmptyString(database.databaseName, `deploy.worker.d1Databases[${index}].databaseName`);
|
|
52
|
+
const databaseId = assertNonEmptyString(database.databaseId, `deploy.worker.d1Databases[${index}].databaseId`);
|
|
53
|
+
const migrationsDir = void 0 === database.migrationsDir ? void 0 : normalizeRelativePath(database.migrationsDir, `deploy.worker.d1Databases[${index}].migrationsDir`, 'app root');
|
|
54
|
+
const previewDatabaseId = void 0 === database.previewDatabaseId ? void 0 : assertNonEmptyString(database.previewDatabaseId, `deploy.worker.d1Databases[${index}].previewDatabaseId`);
|
|
55
|
+
return {
|
|
56
|
+
binding,
|
|
57
|
+
database_name: databaseName,
|
|
58
|
+
database_id: databaseId,
|
|
59
|
+
...void 0 === migrationsDir ? {} : {
|
|
60
|
+
migrations_dir: migrationsDir
|
|
61
|
+
},
|
|
62
|
+
...void 0 === previewDatabaseId ? {} : {
|
|
63
|
+
preview_database_id: previewDatabaseId
|
|
64
|
+
},
|
|
65
|
+
...void 0 === database.remote ? {} : {
|
|
66
|
+
remote: database.remote
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const createWranglerD1Databases = (modernConfig, configuredWranglerD1)=>{
|
|
71
|
+
const d1Databases = modernConfig.deploy?.worker?.d1Databases;
|
|
72
|
+
if (void 0 === d1Databases) return configuredWranglerD1;
|
|
73
|
+
if (void 0 !== configuredWranglerD1) throw new Error('Use deploy.worker.d1Databases or deploy.worker.wrangler.d1_databases, not both.');
|
|
74
|
+
if (!Array.isArray(d1Databases)) throw new Error('deploy.worker.d1Databases must be an array.');
|
|
75
|
+
return d1Databases.map(normalizeD1Database);
|
|
76
|
+
};
|
|
77
|
+
const normalizeServiceBinding = (service, index)=>{
|
|
78
|
+
const binding = assertNonEmptyString(service.binding, `deploy.worker.services[${index}].binding`);
|
|
79
|
+
const serviceName = assertNonEmptyString(service.service, `deploy.worker.services[${index}].service`);
|
|
80
|
+
const prefix = void 0 === service.prefix ? void 0 : assertNonEmptyString(service.prefix, `deploy.worker.services[${index}].prefix`);
|
|
81
|
+
if (void 0 !== service.fragments && !Array.isArray(service.fragments)) throw new Error(`deploy.worker.services[${index}].fragments must be an array.`);
|
|
82
|
+
const fragments = void 0 === service.fragments ? void 0 : service.fragments.map((fragment, fragmentIndex)=>({
|
|
83
|
+
remote: assertNonEmptyString(fragment.remote, `deploy.worker.services[${index}].fragments[${fragmentIndex}].remote`),
|
|
84
|
+
expose: assertNonEmptyString(fragment.expose, `deploy.worker.services[${index}].fragments[${fragmentIndex}].expose`),
|
|
85
|
+
boundaryId: assertNonEmptyString(fragment.boundaryId, `deploy.worker.services[${index}].fragments[${fragmentIndex}].boundaryId`),
|
|
86
|
+
path: assertNonEmptyString(fragment.path, `deploy.worker.services[${index}].fragments[${fragmentIndex}].path`)
|
|
87
|
+
}));
|
|
88
|
+
return {
|
|
89
|
+
binding,
|
|
90
|
+
service: serviceName,
|
|
91
|
+
...void 0 === prefix ? {} : {
|
|
92
|
+
prefix
|
|
93
|
+
},
|
|
94
|
+
...void 0 === fragments ? {} : {
|
|
95
|
+
fragments
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
const createWorkerServiceBindings = (modernConfig, configuredWranglerServices)=>{
|
|
100
|
+
const services = modernConfig.deploy?.worker?.services;
|
|
101
|
+
if (void 0 === services) return configuredWranglerServices;
|
|
102
|
+
if (void 0 !== configuredWranglerServices) throw new Error('Use deploy.worker.services or deploy.worker.wrangler.services, not both.');
|
|
103
|
+
if (!Array.isArray(services)) throw new Error('deploy.worker.services must be an array.');
|
|
104
|
+
return services.map(normalizeServiceBinding);
|
|
105
|
+
};
|
|
106
|
+
const createWranglerServices = (serviceBindings)=>{
|
|
107
|
+
if (!Array.isArray(serviceBindings)) return serviceBindings;
|
|
108
|
+
if (!serviceBindings.every(isJsonRecord)) return serviceBindings;
|
|
109
|
+
return serviceBindings.map((service)=>{
|
|
110
|
+
const { prefix, fragments, ...wranglerService } = service;
|
|
111
|
+
return wranglerService;
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
const createWorkerManifestServiceBindings = (serviceBindings)=>{
|
|
115
|
+
if (!Array.isArray(serviceBindings)) return;
|
|
116
|
+
const bindings = serviceBindings;
|
|
117
|
+
const manifestBindings = bindings.filter((service)=>isJsonRecord(service) && 'string' == typeof service.binding && 'string' == typeof service.service && ('string' == typeof service.prefix || Array.isArray(service.fragments) && service.fragments.length > 0)).map((service)=>({
|
|
118
|
+
binding: service.binding,
|
|
119
|
+
service: service.service,
|
|
120
|
+
interface: 'fetch',
|
|
121
|
+
...void 0 === service.prefix ? {} : {
|
|
122
|
+
prefix: service.prefix
|
|
123
|
+
},
|
|
124
|
+
...void 0 === service.fragments ? {} : {
|
|
125
|
+
fragments: service.fragments
|
|
126
|
+
}
|
|
127
|
+
}));
|
|
128
|
+
return manifestBindings.length > 0 ? manifestBindings : void 0;
|
|
129
|
+
};
|
|
130
|
+
const createWranglerConfig = (appDirectory, modernConfig)=>{
|
|
131
|
+
const wrangler = getConfiguredWrangler(modernConfig);
|
|
132
|
+
const d1Databases = createWranglerD1Databases(modernConfig, wrangler.d1_databases);
|
|
133
|
+
const serviceBindings = createWorkerServiceBindings(modernConfig, wrangler.services);
|
|
134
|
+
const wranglerServices = createWranglerServices(serviceBindings);
|
|
135
|
+
return {
|
|
136
|
+
$schema: 'node_modules/wrangler/config-schema.json',
|
|
137
|
+
name: getConfiguredWorkerName(appDirectory, modernConfig),
|
|
138
|
+
compatibility_date: getCompatibilityDate(modernConfig),
|
|
139
|
+
...wrangler,
|
|
140
|
+
main: WORKER_ENTRY,
|
|
141
|
+
compatibility_flags: createWranglerCompatibilityFlags(wrangler.compatibility_flags),
|
|
142
|
+
assets: createWranglerAssetsConfig(wrangler.assets),
|
|
143
|
+
...void 0 === d1Databases ? {} : {
|
|
144
|
+
d1_databases: d1Databases
|
|
145
|
+
},
|
|
146
|
+
...void 0 === wranglerServices ? {} : {
|
|
147
|
+
services: wranglerServices
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
export { createWorkerManifestServiceBindings, createWorkerServiceBindings, createWranglerConfig };
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
import node_fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import node_path from "node:path";
|
|
4
|
+
import { SERVICE_WORKER_ENVIRONMENT_NAME } from "@modern-js/builder";
|
|
5
|
+
import { isProd } from "@modern-js/utils";
|
|
6
|
+
import { provider } from "std-env";
|
|
7
|
+
import { CLOUDFLARE_WORKER_NODE_BUILTINS } from "./cloudflare-output-contract.mjs";
|
|
8
|
+
import { getTemplatePath } from "./read-template.mjs";
|
|
9
|
+
const moduleRequire = createRequire(import.meta.url);
|
|
10
|
+
const BFF_EFFECT_WORKER_ENTRY_NAME = '__modern_bff_effect';
|
|
11
|
+
const BFF_EFFECT_WORKER_RUNTIME_QUERY = 'modern-bff-runtime';
|
|
12
|
+
const MF_SSR_DATA_FETCH_RUNTIME_PLUGIN = '@module-federation/modern-js-v3/ssr-inject-data-fetch-function-plugin';
|
|
13
|
+
const MF_SSR_DEV_RUNTIME_PLUGIN = '@module-federation/modern-js-v3/ssr-dev-plugin';
|
|
14
|
+
const JS_OR_TS_EXTENSIONS = new Set([
|
|
15
|
+
'.js',
|
|
16
|
+
'.jsx',
|
|
17
|
+
'.ts',
|
|
18
|
+
'.tsx',
|
|
19
|
+
'.mjs',
|
|
20
|
+
'.mts',
|
|
21
|
+
'.cjs',
|
|
22
|
+
'.cts'
|
|
23
|
+
]);
|
|
24
|
+
const findExistingFile = (candidates)=>candidates.find((candidate)=>node_fs.existsSync(candidate));
|
|
25
|
+
const resolveJsOrTsEntry = (entryWithoutOrWithExtension)=>{
|
|
26
|
+
if (JS_OR_TS_EXTENSIONS.has(node_path.extname(entryWithoutOrWithExtension))) return node_fs.existsSync(entryWithoutOrWithExtension) ? entryWithoutOrWithExtension : void 0;
|
|
27
|
+
return findExistingFile([
|
|
28
|
+
...JS_OR_TS_EXTENSIONS
|
|
29
|
+
].map((extension)=>`${entryWithoutOrWithExtension}${extension}`));
|
|
30
|
+
};
|
|
31
|
+
const resolvePackageEntry = (packageName, paths)=>{
|
|
32
|
+
try {
|
|
33
|
+
return node_fs.realpathSync(moduleRequire.resolve(packageName, {
|
|
34
|
+
paths
|
|
35
|
+
}));
|
|
36
|
+
} catch {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const findPackageRoot = (entryFile, packageName)=>{
|
|
41
|
+
let directory = node_path.dirname(entryFile);
|
|
42
|
+
while(directory !== node_path.dirname(directory)){
|
|
43
|
+
const packageJsonPath = node_path.join(directory, 'package.json');
|
|
44
|
+
try {
|
|
45
|
+
const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
46
|
+
if ('object' == typeof packageJson && null !== packageJson && 'name' in packageJson && packageJson.name === packageName) return directory;
|
|
47
|
+
} catch {}
|
|
48
|
+
directory = node_path.dirname(directory);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const resolvePackageFile = (packageName, filePath, paths)=>{
|
|
52
|
+
try {
|
|
53
|
+
return node_fs.realpathSync(moduleRequire.resolve(`${packageName}/${filePath}`, {
|
|
54
|
+
paths
|
|
55
|
+
}));
|
|
56
|
+
} catch {
|
|
57
|
+
try {
|
|
58
|
+
const packageJsonPath = moduleRequire.resolve(`${packageName}/package.json`, {
|
|
59
|
+
paths
|
|
60
|
+
});
|
|
61
|
+
const packageFile = node_path.join(node_path.dirname(packageJsonPath), filePath);
|
|
62
|
+
if (node_fs.existsSync(packageFile)) return node_fs.realpathSync(packageFile);
|
|
63
|
+
} catch {}
|
|
64
|
+
const packageEntry = resolvePackageEntry(packageName, paths);
|
|
65
|
+
const packageRoot = packageEntry ? findPackageRoot(packageEntry, packageName) : void 0;
|
|
66
|
+
const packageFile = packageRoot ? node_path.join(packageRoot, filePath) : void 0;
|
|
67
|
+
return packageFile && node_fs.existsSync(packageFile) ? node_fs.realpathSync(packageFile) : void 0;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const setAliasIfPresent = (alias, name, value)=>{
|
|
71
|
+
if (value) alias.set(name, value);
|
|
72
|
+
};
|
|
73
|
+
const getCloudflareWorkerNodeExternals = ()=>Object.fromEntries(CLOUDFLARE_WORKER_NODE_BUILTINS.flatMap((builtin)=>{
|
|
74
|
+
const nodeBuiltin = `node:${builtin}`;
|
|
75
|
+
return [
|
|
76
|
+
[
|
|
77
|
+
builtin,
|
|
78
|
+
`module-import ${nodeBuiltin}`
|
|
79
|
+
],
|
|
80
|
+
[
|
|
81
|
+
nodeBuiltin,
|
|
82
|
+
`module-import ${nodeBuiltin}`
|
|
83
|
+
]
|
|
84
|
+
];
|
|
85
|
+
}));
|
|
86
|
+
const normalizeWorkerOutputName = (name)=>node_path.posix.normalize(name.replace(/\\/gu, '/')).toLowerCase();
|
|
87
|
+
const reserveWorkerChunkName = (baseName, reservedOutputNames)=>{
|
|
88
|
+
let name = baseName;
|
|
89
|
+
while(reservedOutputNames.has(normalizeWorkerOutputName(name)))name = `${name}_`;
|
|
90
|
+
return name;
|
|
91
|
+
};
|
|
92
|
+
function getCloudflareWorkerRspackConfig(workerEntryNames) {
|
|
93
|
+
const entryNames = [
|
|
94
|
+
...workerEntryNames
|
|
95
|
+
];
|
|
96
|
+
for (const entryName of entryNames){
|
|
97
|
+
const slashName = entryName.replace(/\\/gu, '/');
|
|
98
|
+
const normalizedName = node_path.posix.normalize(slashName);
|
|
99
|
+
if (entryName !== slashName || normalizedName !== slashName || '.' === normalizedName || normalizedName.startsWith('../') || node_path.posix.isAbsolute(normalizedName) || node_path.win32.isAbsolute(slashName) || /^[A-Za-z]:/u.test(slashName)) throw new Error(`Cloudflare worker entry name "${entryName}" must be a canonical relative output path without dot segments or backslashes.`);
|
|
100
|
+
}
|
|
101
|
+
const reservedNames = new Set(entryNames.map(normalizeWorkerOutputName));
|
|
102
|
+
const runtimeName = reserveWorkerChunkName('__modern_worker_runtime', reservedNames);
|
|
103
|
+
reservedNames.add(normalizeWorkerOutputName(runtimeName));
|
|
104
|
+
const sharedName = reserveWorkerChunkName('__modern_worker_shared', reservedNames);
|
|
105
|
+
return {
|
|
106
|
+
externals: getCloudflareWorkerNodeExternals(),
|
|
107
|
+
externalsType: 'module-import',
|
|
108
|
+
module: {
|
|
109
|
+
parser: {
|
|
110
|
+
javascript: {
|
|
111
|
+
dynamicImportMode: 'eager'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
optimization: {
|
|
116
|
+
runtimeChunk: {
|
|
117
|
+
name: runtimeName
|
|
118
|
+
},
|
|
119
|
+
splitChunks: {
|
|
120
|
+
chunks: 'all',
|
|
121
|
+
minSize: 0,
|
|
122
|
+
name: sharedName
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function applyCloudflareWorkerRspackConfig(chain, workerEntryNames) {
|
|
128
|
+
const config = getCloudflareWorkerRspackConfig(workerEntryNames);
|
|
129
|
+
chain.externals(config.externals);
|
|
130
|
+
chain.externalsType(config.externalsType);
|
|
131
|
+
chain.module.parser.merge(config.module.parser);
|
|
132
|
+
chain.optimization.runtimeChunk(config.optimization.runtimeChunk);
|
|
133
|
+
chain.optimization.splitChunks(config.optimization.splitChunks);
|
|
134
|
+
}
|
|
135
|
+
function applyCloudflareWorkerMfRuntimeBoundary(chain) {
|
|
136
|
+
const runtimePlugin = getTemplatePath('cloudflare-worker-mf-ssr-runtime-plugin.mjs');
|
|
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);
|
|
140
|
+
}
|
|
141
|
+
const getEffectBffEntry = (normalizedConfig, appContext)=>{
|
|
142
|
+
if (!normalizedConfig.bff || 'hono' === normalizedConfig.bff.runtimeFramework) return;
|
|
143
|
+
const configuredEntry = normalizedConfig.bff.effect?.entry;
|
|
144
|
+
if (configuredEntry) {
|
|
145
|
+
const entryWithoutOrWithExtension = node_path.isAbsolute(configuredEntry) ? configuredEntry : node_path.resolve(appContext.appDirectory, configuredEntry);
|
|
146
|
+
return resolveJsOrTsEntry(entryWithoutOrWithExtension);
|
|
147
|
+
}
|
|
148
|
+
return resolveJsOrTsEntry(node_path.resolve(appContext.apiDirectory, 'index'));
|
|
149
|
+
};
|
|
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
|
+
const rewriteWorkerEntryPath = (entry)=>entry.replace('index.jsx', 'index.server.jsx').replace('bootstrap.server.jsx', 'index.server.jsx').replace('bootstrap.jsx', 'index.server.jsx');
|
|
163
|
+
const rewriteWorkerEntryDescription = (description)=>{
|
|
164
|
+
const entryImport = description.import;
|
|
165
|
+
if ('string' == typeof entryImport) return {
|
|
166
|
+
...description,
|
|
167
|
+
import: rewriteWorkerEntryPath(entryImport)
|
|
168
|
+
};
|
|
169
|
+
if (Array.isArray(entryImport)) return {
|
|
170
|
+
...description,
|
|
171
|
+
import: entryImport.map(rewriteWorkerEntryPath)
|
|
172
|
+
};
|
|
173
|
+
return description;
|
|
174
|
+
};
|
|
175
|
+
const rewriteWorkerEntries = (entries)=>Object.fromEntries(Object.entries(entries).map(([name, value])=>{
|
|
176
|
+
if ('string' == typeof value) return [
|
|
177
|
+
name,
|
|
178
|
+
rewriteWorkerEntryPath(value)
|
|
179
|
+
];
|
|
180
|
+
if (Array.isArray(value)) return [
|
|
181
|
+
name,
|
|
182
|
+
value.map(rewriteWorkerEntryPath)
|
|
183
|
+
];
|
|
184
|
+
return [
|
|
185
|
+
name,
|
|
186
|
+
rewriteWorkerEntryDescription(value)
|
|
187
|
+
];
|
|
188
|
+
}));
|
|
189
|
+
const prependBundlerChain = (environment, handler)=>{
|
|
190
|
+
const bundlerChain = environment.tools?.bundlerChain;
|
|
191
|
+
return {
|
|
192
|
+
...environment,
|
|
193
|
+
tools: {
|
|
194
|
+
...environment.tools,
|
|
195
|
+
htmlPlugin: false,
|
|
196
|
+
bundlerChain: bundlerChain ? Array.isArray(bundlerChain) ? [
|
|
197
|
+
handler,
|
|
198
|
+
...bundlerChain
|
|
199
|
+
] : [
|
|
200
|
+
handler,
|
|
201
|
+
bundlerChain
|
|
202
|
+
] : handler
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
};
|
|
206
|
+
const getWorkerEntries = (environment, normalizedConfig, appContext)=>{
|
|
207
|
+
const configuredEntries = environment.source?.entry;
|
|
208
|
+
if (!configuredEntries) return;
|
|
209
|
+
const entries = rewriteWorkerEntries(configuredEntries);
|
|
210
|
+
const effectApiEntry = getEffectBffEntry(normalizedConfig, appContext);
|
|
211
|
+
return effectApiEntry ? {
|
|
212
|
+
...entries,
|
|
213
|
+
[BFF_EFFECT_WORKER_ENTRY_NAME]: [
|
|
214
|
+
`${effectApiEntry}?${BFF_EFFECT_WORKER_RUNTIME_QUERY}`
|
|
215
|
+
]
|
|
216
|
+
} : entries;
|
|
217
|
+
};
|
|
218
|
+
const createCloudflareBundlerChain = (appContext, workerEntryNames)=>{
|
|
219
|
+
const resolvePaths = [
|
|
220
|
+
appContext.appDirectory,
|
|
221
|
+
process.cwd()
|
|
222
|
+
];
|
|
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
|
+
const reactFile = resolvePackageFile('react', 'index.js', resolvePaths);
|
|
227
|
+
const reactJsxRuntimeFile = resolvePackageFile('react', 'jsx-runtime.js', resolvePaths);
|
|
228
|
+
const reactJsxDevRuntimeFile = resolvePackageFile('react', 'jsx-dev-runtime.js', resolvePaths);
|
|
229
|
+
const reactDomFile = resolvePackageFile('react-dom', 'index.js', resolvePaths);
|
|
230
|
+
const reactDomServerEdgeFile = resolvePackageFile('react-dom', 'server.edge.js', resolvePaths);
|
|
231
|
+
const loadableComponentFile = resolvePackageFile('@loadable/component', 'dist/esm/loadable.esm.mjs', [
|
|
232
|
+
...resolvePaths,
|
|
233
|
+
getTemplatePath('')
|
|
234
|
+
]);
|
|
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
|
+
const entryNames = [
|
|
239
|
+
...workerEntryNames
|
|
240
|
+
];
|
|
241
|
+
return (chain)=>{
|
|
242
|
+
applyCloudflareWorkerRspackConfig(chain, entryNames);
|
|
243
|
+
chain.output.module(true).library({
|
|
244
|
+
type: 'module'
|
|
245
|
+
}).publicPath('/').chunkFormat('module').chunkLoading('import').workerChunkLoading('import');
|
|
246
|
+
for (const condition of [
|
|
247
|
+
'workerd',
|
|
248
|
+
'worker',
|
|
249
|
+
'webpack',
|
|
250
|
+
isProd() ? 'production' : 'development',
|
|
251
|
+
'import',
|
|
252
|
+
'require',
|
|
253
|
+
'module'
|
|
254
|
+
])chain.resolve.conditionNames.add(condition);
|
|
255
|
+
applyCloudflareWorkerMfRuntimeBoundary(chain);
|
|
256
|
+
if (tanstackRouterSsrServerFile) {
|
|
257
|
+
chain.resolve.alias.set('@tanstack/router-core/ssr/server$', tanstackRouterSsrServerFile);
|
|
258
|
+
chain.resolve.alias.set('@tanstack/router-core/ssr/server', tanstackRouterSsrServerFile);
|
|
259
|
+
}
|
|
260
|
+
if (runtimeRscWorkerFile) {
|
|
261
|
+
chain.resolve.alias.set('@modern-js/runtime/rsc/server$', runtimeRscWorkerFile);
|
|
262
|
+
chain.resolve.alias.set('@modern-js/runtime/rsc/server', runtimeRscWorkerFile);
|
|
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
|
+
}
|
|
269
|
+
setAliasIfPresent(chain.resolve.alias, 'react$', reactFile);
|
|
270
|
+
setAliasIfPresent(chain.resolve.alias, 'react/jsx-runtime$', reactJsxRuntimeFile);
|
|
271
|
+
setAliasIfPresent(chain.resolve.alias, 'react/jsx-dev-runtime$', reactJsxDevRuntimeFile);
|
|
272
|
+
setAliasIfPresent(chain.resolve.alias, 'react-dom$', reactDomFile);
|
|
273
|
+
setAliasIfPresent(chain.resolve.alias, 'react-dom/server.edge$', reactDomServerEdgeFile);
|
|
274
|
+
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
|
+
};
|
|
287
|
+
};
|
|
288
|
+
function getCloudflareBuilderEnvironments({ appContext, environments, normalizedConfig, resolveDeployProvider = resolveStdEnvDeployProvider }) {
|
|
289
|
+
if (!isCloudflareWorkerDeploy(normalizedConfig, resolveDeployProvider)) return environments;
|
|
290
|
+
const workerEnvironment = environments[SERVICE_WORKER_ENVIRONMENT_NAME];
|
|
291
|
+
if (!workerEnvironment) return environments;
|
|
292
|
+
const workerEntries = getWorkerEntries(workerEnvironment, normalizedConfig, appContext);
|
|
293
|
+
if (!workerEntries) return environments;
|
|
294
|
+
const cloudflareWorkerEnvironment = prependBundlerChain({
|
|
295
|
+
...workerEnvironment,
|
|
296
|
+
output: {
|
|
297
|
+
...workerEnvironment.output,
|
|
298
|
+
module: true,
|
|
299
|
+
target: 'web'
|
|
300
|
+
},
|
|
301
|
+
source: {
|
|
302
|
+
...workerEnvironment.source,
|
|
303
|
+
entry: workerEntries
|
|
304
|
+
}
|
|
305
|
+
}, createCloudflareBundlerChain(appContext, Object.keys(workerEntries)));
|
|
306
|
+
return {
|
|
307
|
+
...environments,
|
|
308
|
+
[SERVICE_WORKER_ENVIRONMENT_NAME]: cloudflareWorkerEnvironment
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
function applyCloudflareBuilderEnvironments(options) {
|
|
312
|
+
return {
|
|
313
|
+
environments: getCloudflareBuilderEnvironments(options)
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
const createCloudflareBuilderPlugin = (resolveDeployProvider = resolveStdEnvDeployProvider)=>({
|
|
317
|
+
name: '@modern-js/cloudflare-builder',
|
|
318
|
+
setup (api) {
|
|
319
|
+
api.modifyBuilderEnvironments(({ environments })=>applyCloudflareBuilderEnvironments({
|
|
320
|
+
appContext: api.getAppContext(),
|
|
321
|
+
environments,
|
|
322
|
+
normalizedConfig: api.getNormalizedConfig(),
|
|
323
|
+
resolveDeployProvider
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
export { applyCloudflareBuilderEnvironments, applyCloudflareWorkerMfRuntimeBoundary, applyCloudflareWorkerRspackConfig, createCloudflareBuilderPlugin, getCloudflareBuilderEnvironments, getCloudflareWorkerRspackConfig };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const CLOUDFLARE_WORKER_ENTRY = 'server/index.mjs';
|
|
2
|
+
const CLOUDFLARE_WORKER_MANIFEST = 'server/modern-worker-manifest.json';
|
|
3
|
+
const CLOUDFLARE_WRANGLER_CONFIG_FILE = 'wrangler.json';
|
|
4
|
+
const CLOUDFLARE_OUTPUT_PACKAGE_FILE = 'package.json';
|
|
5
|
+
const CLOUDFLARE_WORKER_PACKAGE_FILE = 'worker/package.json';
|
|
6
|
+
const CLOUDFLARE_ASSETS_BINDING = 'ASSETS';
|
|
7
|
+
const CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY = 'public';
|
|
8
|
+
const CLOUDFLARE_WORKER_BUNDLE_DIRECTORY = 'worker';
|
|
9
|
+
const CLOUDFLARE_RUNTIME_TYPE = 'cloudflare-module-worker';
|
|
10
|
+
const CLOUDFLARE_OUTPUT_PACKAGE_TYPE = 'module';
|
|
11
|
+
const CLOUDFLARE_WORKER_PACKAGE_TYPE = 'commonjs';
|
|
12
|
+
const CLOUDFLARE_WORKER_BUNDLE_FORMAT = 'commonjs';
|
|
13
|
+
const CLOUDFLARE_WORKER_NODE_BUILTINS = [
|
|
14
|
+
'async_hooks',
|
|
15
|
+
'buffer',
|
|
16
|
+
'crypto',
|
|
17
|
+
'events',
|
|
18
|
+
'fs/promises',
|
|
19
|
+
'module',
|
|
20
|
+
'path',
|
|
21
|
+
'process',
|
|
22
|
+
'stream',
|
|
23
|
+
'string_decoder',
|
|
24
|
+
'url',
|
|
25
|
+
'util'
|
|
26
|
+
];
|
|
27
|
+
const CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS = [
|
|
28
|
+
'nodejs_compat',
|
|
29
|
+
'global_fetch_strictly_public'
|
|
30
|
+
];
|
|
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 };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import node_path from "node:path";
|
|
2
|
+
import { CLOUDFLARE_ASSETS_BINDING, CLOUDFLARE_OUTPUT_PACKAGE_FILE, CLOUDFLARE_OUTPUT_PACKAGE_TYPE, CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY, CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS, CLOUDFLARE_WORKER_BUNDLE_DIRECTORY, CLOUDFLARE_WORKER_ENTRY, CLOUDFLARE_WORKER_MANIFEST, CLOUDFLARE_WORKER_PACKAGE_FILE, CLOUDFLARE_WORKER_PACKAGE_TYPE, CLOUDFLARE_WRANGLER_CONFIG_FILE } from "./cloudflare-output-contract.mjs";
|
|
3
|
+
const resolveOutput = (outputDirectory, relativePath)=>node_path.join(outputDirectory, relativePath);
|
|
4
|
+
function createCloudflareOutputPlan(outputDirectory) {
|
|
5
|
+
return {
|
|
6
|
+
outputDirectory,
|
|
7
|
+
requiredFiles: [
|
|
8
|
+
CLOUDFLARE_WORKER_ENTRY,
|
|
9
|
+
CLOUDFLARE_WORKER_MANIFEST,
|
|
10
|
+
CLOUDFLARE_WRANGLER_CONFIG_FILE,
|
|
11
|
+
CLOUDFLARE_OUTPUT_PACKAGE_FILE
|
|
12
|
+
],
|
|
13
|
+
publicLeakDirectories: [
|
|
14
|
+
'server',
|
|
15
|
+
CLOUDFLARE_WORKER_BUNDLE_DIRECTORY
|
|
16
|
+
],
|
|
17
|
+
paths: {
|
|
18
|
+
workerEntry: resolveOutput(outputDirectory, CLOUDFLARE_WORKER_ENTRY),
|
|
19
|
+
workerManifest: resolveOutput(outputDirectory, CLOUDFLARE_WORKER_MANIFEST),
|
|
20
|
+
wranglerConfig: resolveOutput(outputDirectory, CLOUDFLARE_WRANGLER_CONFIG_FILE),
|
|
21
|
+
outputPackage: resolveOutput(outputDirectory, CLOUDFLARE_OUTPUT_PACKAGE_FILE),
|
|
22
|
+
workerPackage: resolveOutput(outputDirectory, CLOUDFLARE_WORKER_PACKAGE_FILE),
|
|
23
|
+
publicAssets: resolveOutput(outputDirectory, CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY),
|
|
24
|
+
workerBundle: resolveOutput(outputDirectory, CLOUDFLARE_WORKER_BUNDLE_DIRECTORY)
|
|
25
|
+
},
|
|
26
|
+
packages: {
|
|
27
|
+
output: {
|
|
28
|
+
type: CLOUDFLARE_OUTPUT_PACKAGE_TYPE
|
|
29
|
+
},
|
|
30
|
+
worker: {
|
|
31
|
+
type: CLOUDFLARE_WORKER_PACKAGE_TYPE
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
wrangler: {
|
|
35
|
+
main: CLOUDFLARE_WORKER_ENTRY,
|
|
36
|
+
assets: {
|
|
37
|
+
binding: CLOUDFLARE_ASSETS_BINDING,
|
|
38
|
+
directory: `./${CLOUDFLARE_PUBLIC_ASSETS_DIRECTORY}`,
|
|
39
|
+
run_worker_first: true
|
|
40
|
+
},
|
|
41
|
+
requiredCompatibilityFlags: CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export { createCloudflareOutputPlan };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { DELIVERY_UNIT_IDENTITY_FIELDS, deliveryUnitIdentityFieldValue } from "@modern-js/utils/universal";
|
|
2
|
+
import { addIssue, assertEqual } from "./issues.mjs";
|
|
3
|
+
const verifyDeliveryUnitIdentity = (issues, manifest, manifestPath, declared)=>{
|
|
4
|
+
const stamped = manifest?.deliveryUnit;
|
|
5
|
+
const hasStamp = Boolean(stamped) && 'object' == typeof stamped;
|
|
6
|
+
if (declared) {
|
|
7
|
+
if (!hasStamp) return void addIssue(issues, {
|
|
8
|
+
code: 'missing-delivery-unit',
|
|
9
|
+
message: `Cloudflare worker manifest is missing the delivery-unit identity declared by the workspace topology (expected unitId ${declared.unitId}, buildMarker ${declared.buildMarker}).`,
|
|
10
|
+
path: manifestPath
|
|
11
|
+
});
|
|
12
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
13
|
+
const stampedValue = deliveryUnitIdentityFieldValue(stamped, field);
|
|
14
|
+
assertEqual(issues, stampedValue, declared[field], {
|
|
15
|
+
code: 'delivery-unit-drift',
|
|
16
|
+
message: `Cloudflare worker manifest deliveryUnit.${field} must match the topology delivery-unit record (expected ${declared[field]}, received ${stampedValue ?? 'undefined'}).`,
|
|
17
|
+
path: manifestPath
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (hasStamp && stamped.surfaces && 'object' == typeof stamped.surfaces) for (const surface of [
|
|
22
|
+
'ui',
|
|
23
|
+
'api'
|
|
24
|
+
]){
|
|
25
|
+
const marker = stamped.surfaces[surface];
|
|
26
|
+
const expected = declared?.surfaces?.[surface];
|
|
27
|
+
if (declared?.surfaces && !expected) {
|
|
28
|
+
if (marker) addIssue(issues, {
|
|
29
|
+
code: 'delivery-unit-drift',
|
|
30
|
+
message: `Cloudflare worker manifest declares an unexpected ${surface} delivery-unit surface for this topology profile.`,
|
|
31
|
+
path: manifestPath
|
|
32
|
+
});
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (!marker || 'object' != typeof marker) {
|
|
36
|
+
addIssue(issues, {
|
|
37
|
+
code: 'missing-delivery-unit',
|
|
38
|
+
message: `Cloudflare worker manifest is missing the ${surface} delivery-unit surface marker.`,
|
|
39
|
+
path: manifestPath
|
|
40
|
+
});
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
for (const field of DELIVERY_UNIT_IDENTITY_FIELDS){
|
|
44
|
+
const markerValue = deliveryUnitIdentityFieldValue(marker, field);
|
|
45
|
+
const stampedValue = deliveryUnitIdentityFieldValue(stamped, field);
|
|
46
|
+
assertEqual(issues, markerValue, stampedValue, {
|
|
47
|
+
code: 'delivery-unit-drift',
|
|
48
|
+
message: `Cloudflare worker manifest ${surface} surface deliveryUnit.${field} must derive from one delivery-unit record (expected ${stampedValue ?? 'undefined'}, received ${markerValue ?? 'undefined'}).`,
|
|
49
|
+
path: manifestPath
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
export { verifyDeliveryUnitIdentity };
|