@bleedingdev/modern-js-app-tools-extensions 3.9.0-ultramodern.13 → 3.9.0-ultramodern.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cloudflare/worker-manifest.js +13 -4
- package/dist/cjs/cloudflare/wrangler-config.js +35 -7
- package/dist/cjs/cloudflare-builder.js +235 -14
- package/dist/cjs/cloudflare-output-contract.js +31 -2
- package/dist/cjs/cloudflare-output-verifier/worker-bundles.js +10 -5
- package/dist/cjs/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/cjs/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/cjs/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/cjs/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm/cloudflare-builder.mjs +229 -17
- package/dist/esm/cloudflare-output-contract.mjs +24 -1
- package/dist/esm/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/esm/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/esm/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/esm-node/cloudflare/worker-manifest.mjs +13 -4
- package/dist/esm-node/cloudflare/wrangler-config.mjs +35 -7
- package/dist/esm-node/cloudflare-builder.mjs +229 -17
- package/dist/esm-node/cloudflare-output-contract.mjs +24 -1
- package/dist/esm-node/cloudflare-output-verifier/worker-bundles.mjs +11 -6
- package/dist/esm-node/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/dist/esm-node/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/dist/esm-node/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/dist/esm-node/templates/cloudflare-worker-route-data.mjs +1069 -0
- package/dist/types/cloudflare/wrangler-config.d.ts +6 -0
- package/dist/types/cloudflare-builder.d.ts +44 -1
- package/dist/types/cloudflare-output-contract.d.ts +3 -1
- package/dist/types/cloudflare-output-verifier/worker-bundles.d.ts +2 -2
- package/dist/types/templates/cloudflare-worker-route-data.d.mts +14 -0
- package/package.json +17 -13
- package/src/cloudflare/worker-manifest.ts +19 -3
- package/src/cloudflare/wrangler-config.ts +86 -10
- package/src/cloudflare-builder.ts +447 -12
- package/src/cloudflare-output-contract.ts +34 -2
- package/src/cloudflare-output-verifier/worker-bundles.ts +27 -11
- package/src/templates/cloudflare-entry.004-rendering-css.mjs +4 -0
- package/src/templates/cloudflare-entry.005-worker-dispatch.mjs +46 -0
- package/src/templates/cloudflare-entry.006-fetch-handler.mjs +9 -2
- package/src/templates/cloudflare-worker-route-data.mjs +1069 -0
|
@@ -34,6 +34,12 @@ export declare const createWranglerConfig: (appDirectory: string, modernConfig:
|
|
|
34
34
|
binding: string;
|
|
35
35
|
run_worker_first: boolean;
|
|
36
36
|
};
|
|
37
|
+
env?: {
|
|
38
|
+
[k: string]: {
|
|
39
|
+
compatibility_date?: string | undefined;
|
|
40
|
+
compatibility_flags?: JsonValue[] | undefined;
|
|
41
|
+
};
|
|
42
|
+
} | undefined;
|
|
37
43
|
d1_databases?: {
|
|
38
44
|
binding: string;
|
|
39
45
|
database_name: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BffUserConfig } from '@modern-js/server-core';
|
|
2
|
-
import type { EnvironmentConfig, ModifyBundlerChainFn } from '@rsbuild/core';
|
|
2
|
+
import type { EnvironmentConfig, ModifyBundlerChainFn, Rspack } from '@rsbuild/core';
|
|
3
3
|
export interface CloudflareBuilderNormalizedConfig {
|
|
4
4
|
bff?: BffUserConfig;
|
|
5
5
|
deploy?: {
|
|
@@ -10,6 +10,10 @@ export interface CloudflareBuilderAppContext {
|
|
|
10
10
|
apiOnly?: boolean;
|
|
11
11
|
apiDirectory: string;
|
|
12
12
|
appDirectory: string;
|
|
13
|
+
entrypoints?: ReadonlyArray<{
|
|
14
|
+
entryName: string;
|
|
15
|
+
}>;
|
|
16
|
+
internalDirectory?: string;
|
|
13
17
|
}
|
|
14
18
|
export interface CloudflareBuilderEnvironmentsOptions {
|
|
15
19
|
appContext: CloudflareBuilderAppContext;
|
|
@@ -52,9 +56,48 @@ export interface CloudflareBuilderPlugin {
|
|
|
52
56
|
name: string;
|
|
53
57
|
setup(api: CloudflareBuilderPluginApi): void;
|
|
54
58
|
}
|
|
59
|
+
type AliasField = string | readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Leaves an absent optional dependency missing at runtime, exactly as Node
|
|
62
|
+
* does, instead of failing the worker build. It applies only when the
|
|
63
|
+
* importing package itself declares the request as an optional peer
|
|
64
|
+
* (`peerDependenciesMeta.<name>.optional`) or an `optionalDependencies`
|
|
65
|
+
* entry, the package is not found in any `resolve.modules` directory, and
|
|
66
|
+
* neither the app (`resolve.alias`, `resolve.fallback`, `externals`) nor the
|
|
67
|
+
* importing package (an enabled `resolve.aliasFields` entry such as
|
|
68
|
+
* `browser`) redirects the request. The import
|
|
69
|
+
* then rejects with "Cannot find module" so the library's own fallback
|
|
70
|
+
* handles it (for example `@redis/client` guards `import('@node-rs/xxhash')`).
|
|
71
|
+
*/
|
|
72
|
+
export declare const createAbsentOptionalDependencyFilter: (isRedirected?: (request: string) => boolean, moduleDirectories?: readonly string[], aliasFields?: readonly AliasField[]) => (request: string, context: string) => boolean;
|
|
73
|
+
type AliasOption = Record<string, unknown> | {
|
|
74
|
+
name: string;
|
|
75
|
+
onlyModule?: boolean;
|
|
76
|
+
}[] | false | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Reads the final resolved `resolve.alias`, `resolve.fallback` and
|
|
79
|
+
* `externals` so an app's own
|
|
80
|
+
* replacement for an optional package still wins over the absent-module
|
|
81
|
+
* fallback (the fallback runs before resolution).
|
|
82
|
+
*/
|
|
83
|
+
export declare const createRequestRedirectMatcher: (options: {
|
|
84
|
+
externals?: unknown;
|
|
85
|
+
resolve?: {
|
|
86
|
+
alias?: AliasOption;
|
|
87
|
+
fallback?: AliasOption;
|
|
88
|
+
};
|
|
89
|
+
}) => (request: string) => boolean;
|
|
90
|
+
type FunctionExternal = (data: Rspack.ExternalItemFunctionData, callback: (error?: Error | null, result?: unknown) => void) => unknown;
|
|
91
|
+
/**
|
|
92
|
+
* Reports whether any function external claims the request. A function that
|
|
93
|
+
* throws is treated as claiming it, so the request goes through ordinary
|
|
94
|
+
* external processing and surfaces that error instead of being ignored.
|
|
95
|
+
*/
|
|
96
|
+
export declare const claimsByFunctionExternal: (externals: readonly FunctionExternal[], data: Rspack.ExternalItemFunctionData) => Promise<boolean>;
|
|
55
97
|
export declare function getCloudflareWorkerRspackConfig(workerEntryNames: Iterable<string>): CloudflareWorkerRspackConfig;
|
|
56
98
|
export declare function applyCloudflareWorkerRspackConfig(chain: Parameters<ModifyBundlerChainFn>[0], workerEntryNames: Iterable<string>): void;
|
|
57
99
|
export declare function applyCloudflareWorkerMfRuntimeBoundary(chain: Parameters<ModifyBundlerChainFn>[0]): void;
|
|
58
100
|
export declare function getCloudflareBuilderEnvironments({ appContext, environments, normalizedConfig, resolveDeployProvider, }: CloudflareBuilderEnvironmentsOptions): Record<string, EnvironmentConfig>;
|
|
59
101
|
export declare function applyCloudflareBuilderEnvironments(options: CloudflareBuilderEnvironmentsOptions): CloudflareBuilderEnvironmentsResult;
|
|
60
102
|
export declare const createCloudflareBuilderPlugin: (resolveDeployProvider?: ResolveCloudflareDeployProvider) => CloudflareBuilderPlugin;
|
|
103
|
+
export {};
|
|
@@ -10,6 +10,8 @@ export declare const CLOUDFLARE_RUNTIME_TYPE = "cloudflare-module-worker";
|
|
|
10
10
|
export declare const CLOUDFLARE_OUTPUT_PACKAGE_TYPE = "module";
|
|
11
11
|
export declare const CLOUDFLARE_WORKER_PACKAGE_TYPE = "commonjs";
|
|
12
12
|
export declare const CLOUDFLARE_WORKER_BUNDLE_FORMAT = "commonjs";
|
|
13
|
-
export declare const
|
|
13
|
+
export declare const CLOUDFLARE_ROUTE_DATA_HANDLER_EXPORT = "handleRouteDataRequest";
|
|
14
|
+
export declare const getCloudflareWorkerRouteDataEntryName: (entryName: string) => string;
|
|
15
|
+
export declare const CLOUDFLARE_WORKER_NODE_BUILTINS: readonly ['_http_agent', '_http_client', '_http_common', '_http_incoming', '_http_outgoing', '_http_server', '_tls_common', '_tls_wrap', 'assert', 'assert/strict', 'async_hooks', 'buffer', 'child_process', 'cluster', 'console', 'constants', 'crypto', 'dgram', 'diagnostics_channel', 'dns', 'dns/promises', 'domain', 'events', 'fs', 'fs/promises', 'http', 'http2', 'https', 'inspector', 'inspector/promises', 'module', 'net', 'os', 'path', 'path/posix', 'path/win32', 'perf_hooks', 'process', 'punycode', 'querystring', 'readline', 'readline/promises', 'repl', 'sqlite', 'stream', 'stream/consumers', 'stream/promises', 'stream/web', 'string_decoder', 'sys', 'test', 'timers', 'timers/promises', 'tls', 'trace_events', 'tty', 'url', 'util', 'util/types', 'v8', 'vm', 'wasi', 'worker_threads', 'zlib'];
|
|
14
16
|
export declare const CLOUDFLARE_WORKER_PLATFORM_MODULES: readonly ['cloudflare:sockets'];
|
|
15
17
|
export declare const CLOUDFLARE_REQUIRED_COMPATIBILITY_FLAGS: readonly ['nodejs_compat', 'global_fetch_strictly_public'];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CloudflareOutputVerifierIssue, JsonObject } from './issues.js';
|
|
2
2
|
interface WorkerBundleReference {
|
|
3
3
|
dispatcherExport?: string;
|
|
4
|
-
kind: 'effect-bff' | 'route';
|
|
4
|
+
kind: 'effect-bff' | 'route' | 'route-data';
|
|
5
5
|
reference: string;
|
|
6
6
|
}
|
|
7
7
|
interface ResolvedWorkerBundleReference extends WorkerBundleReference {
|
|
@@ -10,7 +10,7 @@ interface ResolvedWorkerBundleReference extends WorkerBundleReference {
|
|
|
10
10
|
export declare const getEffectBffWorker: (manifest: JsonObject) => any;
|
|
11
11
|
export declare const getWorkerBundleReferences: (manifest: JsonObject) => WorkerBundleReference[];
|
|
12
12
|
export declare const resolveWorkerBundleReference: (issues: CloudflareOutputVerifierIssue[], outputDirectory: string, reference: WorkerBundleReference, manifestPath: string) => ResolvedWorkerBundleReference | null;
|
|
13
|
-
export declare const missingWorkerBundleMessage: (reference: WorkerBundleReference) => "Cloudflare Effect BFF manifest points to a missing worker bundle." | "Cloudflare route worker manifest points to a missing worker bundle.";
|
|
13
|
+
export declare const missingWorkerBundleMessage: (reference: WorkerBundleReference) => "Cloudflare Effect BFF manifest points to a missing worker bundle." | "Cloudflare route data worker manifest points to a missing worker bundle." | "Cloudflare route worker manifest points to a missing worker bundle.";
|
|
14
14
|
interface WorkerBundleVerificationContract {
|
|
15
15
|
providedPackages: ReadonlySet<string>;
|
|
16
16
|
workerRoot: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create the worker route data request handler for an entry's route loaders
|
|
3
|
+
* (the `routes` export of its generated `route-server-loaders.js`).
|
|
4
|
+
*
|
|
5
|
+
* The handler takes the Node data handler's options and resolves to
|
|
6
|
+
* `undefined` for requests that are not route data requests of a known entry,
|
|
7
|
+
* so the caller renders the page instead.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createRouteDataRequestHandler(routes: any): ({ request, serverRoutes, context, onTiming }: {
|
|
10
|
+
context?: {} | undefined;
|
|
11
|
+
onTiming: any;
|
|
12
|
+
request: any;
|
|
13
|
+
serverRoutes: any;
|
|
14
|
+
}) => Promise<any>;
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/solutions/app-tools-extensions"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"version": "3.9.0-ultramodern.
|
|
14
|
+
"version": "3.9.0-ultramodern.14",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"src"
|
|
@@ -145,15 +145,16 @@
|
|
|
145
145
|
"@babel/parser": "^8.0.6",
|
|
146
146
|
"@babel/traverse": "^8.0.6",
|
|
147
147
|
"@loadable/component": "5.16.7",
|
|
148
|
-
"@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.0-ultramodern.
|
|
149
|
-
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.0-ultramodern.
|
|
150
|
-
"@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.9.0-ultramodern.
|
|
151
|
-
"@modern-js/runtime-renderer-extensions": "npm:@bleedingdev/modern-js-runtime-renderer-extensions@3.9.0-ultramodern.
|
|
152
|
-
"@modern-js/
|
|
153
|
-
"@modern-js/server-
|
|
154
|
-
"@modern-js/
|
|
155
|
-
"@modern-js/
|
|
156
|
-
"@modern-js/
|
|
148
|
+
"@modern-js/backend-federation-contracts": "npm:@bleedingdev/modern-js-backend-federation-contracts@3.9.0-ultramodern.14",
|
|
149
|
+
"@modern-js/builder": "npm:@bleedingdev/modern-js-builder@3.9.0-ultramodern.14",
|
|
150
|
+
"@modern-js/prod-server": "npm:@bleedingdev/modern-js-prod-server@3.9.0-ultramodern.14",
|
|
151
|
+
"@modern-js/runtime-renderer-extensions": "npm:@bleedingdev/modern-js-runtime-renderer-extensions@3.9.0-ultramodern.14",
|
|
152
|
+
"@modern-js/runtime-utils": "npm:@bleedingdev/modern-js-runtime-utils@3.9.0-ultramodern.14",
|
|
153
|
+
"@modern-js/server-core": "npm:@bleedingdev/modern-js-server-core@3.9.0-ultramodern.14",
|
|
154
|
+
"@modern-js/server-runtime-extensions": "npm:@bleedingdev/modern-js-server-runtime-extensions@3.9.0-ultramodern.14",
|
|
155
|
+
"@modern-js/surface-resolution": "npm:@bleedingdev/modern-js-surface-resolution@3.9.0-ultramodern.14",
|
|
156
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.9.0-ultramodern.14",
|
|
157
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.9.0-ultramodern.14",
|
|
157
158
|
"@swc/helpers": "^0.5.23",
|
|
158
159
|
"compression-webpack-plugin": "^12.0.0",
|
|
159
160
|
"esbuild": "^0.28.2",
|
|
@@ -163,8 +164,9 @@
|
|
|
163
164
|
"@rsbuild/core": "2.2.9"
|
|
164
165
|
},
|
|
165
166
|
"devDependencies": {
|
|
166
|
-
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.
|
|
167
|
-
"@modern-js/plugin-bff-extensions": "npm:@bleedingdev/modern-js-plugin-bff-extensions@3.9.0-ultramodern.
|
|
167
|
+
"@modern-js/plugin": "npm:@bleedingdev/modern-js-plugin@3.9.0-ultramodern.14",
|
|
168
|
+
"@modern-js/plugin-bff-extensions": "npm:@bleedingdev/modern-js-plugin-bff-extensions@3.9.0-ultramodern.14",
|
|
169
|
+
"@modern-js/plugin-data-loader": "npm:@bleedingdev/modern-js-plugin-data-loader@3.9.0-ultramodern.14",
|
|
168
170
|
"@module-federation/runtime-tools": "npm:@bleedingdev/mf-runtime-tools@2.9.1",
|
|
169
171
|
"@rsbuild/core": "2.2.9",
|
|
170
172
|
"@rslib/core": "1.0.2",
|
|
@@ -174,7 +176,9 @@
|
|
|
174
176
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
175
177
|
"core-js": "^3.50.0",
|
|
176
178
|
"effect": "npm:@bleedingdev/effect@4.0.0-rc.117",
|
|
177
|
-
"
|
|
179
|
+
"miniflare": "5.20260921.0-alpha",
|
|
180
|
+
"ndepe": "^0.1.13",
|
|
181
|
+
"pg": "8.23.0"
|
|
178
182
|
},
|
|
179
183
|
"sideEffects": false,
|
|
180
184
|
"publishConfig": {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import type {} from '@modern-js/server-runtime-extensions/server-config';
|
|
3
3
|
import { fs as fse } from '@modern-js/utils';
|
|
4
|
+
import { getCloudflareWorkerRouteDataEntryName } from '../cloudflare-output-contract';
|
|
4
5
|
import { readRouteSpec } from './artifacts';
|
|
5
6
|
import {
|
|
6
7
|
ASSETS_BINDING,
|
|
@@ -132,6 +133,15 @@ export const createWorkerManifest = async (
|
|
|
132
133
|
routeSpec.routes.map(async (route: Record<string, any>) => {
|
|
133
134
|
const worker =
|
|
134
135
|
typeof route.worker === 'string' ? route.worker : undefined;
|
|
136
|
+
const routeDataWorker =
|
|
137
|
+
route.isSSR && typeof route.entryName === 'string'
|
|
138
|
+
? `${WORKER_BUNDLE_DIRECTORY}/${getCloudflareWorkerRouteDataEntryName(
|
|
139
|
+
route.entryName,
|
|
140
|
+
)}.js`
|
|
141
|
+
: undefined;
|
|
142
|
+
const hasRouteDataWorker = routeDataWorker
|
|
143
|
+
? await fse.pathExists(path.join(outputDirectory, routeDataWorker))
|
|
144
|
+
: false;
|
|
135
145
|
|
|
136
146
|
return {
|
|
137
147
|
urlPath: route.urlPath,
|
|
@@ -142,6 +152,7 @@ export const createWorkerManifest = async (
|
|
|
142
152
|
workerExists: worker
|
|
143
153
|
? await fse.pathExists(path.join(outputDirectory, worker))
|
|
144
154
|
: false,
|
|
155
|
+
...(hasRouteDataWorker ? { routeDataWorker } : {}),
|
|
145
156
|
};
|
|
146
157
|
}),
|
|
147
158
|
);
|
|
@@ -218,9 +229,14 @@ export const createWorkerModuleLoaders = (manifest: any) => {
|
|
|
218
229
|
const imports = new Map<string, string>();
|
|
219
230
|
|
|
220
231
|
for (const route of manifest.routeSpec.routes) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
for (const worker of [
|
|
233
|
+
route.workerExists ? route.worker : undefined,
|
|
234
|
+
route.routeDataWorker,
|
|
235
|
+
]) {
|
|
236
|
+
if (worker) {
|
|
237
|
+
const importPath = `../${String(worker).replace(/^\/+/u, '')}`;
|
|
238
|
+
imports.set(worker, `() => import(${JSON.stringify(importPath)})`);
|
|
239
|
+
}
|
|
224
240
|
}
|
|
225
241
|
}
|
|
226
242
|
|
|
@@ -15,21 +15,51 @@ import {
|
|
|
15
15
|
import type { CloudflareModernConfig } from './types';
|
|
16
16
|
import { isJsonRecord, normalizeRelativePath } from './utils';
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
// Workers only add Node.js built-ins at later dates, and the bundler
|
|
19
|
+
// externalizes the set probed at DEFAULT_COMPATIBILITY_DATE; an earlier date
|
|
20
|
+
// could leave an externalized built-in unresolvable at deploy time.
|
|
21
|
+
const assertSupportedCompatibilityDate = (
|
|
22
|
+
compatibilityDate: JsonValue | undefined,
|
|
23
|
+
label: string,
|
|
24
|
+
) => {
|
|
25
|
+
if (typeof compatibilityDate !== 'string') {
|
|
26
|
+
throw new Error(`${label} must be a YYYY-MM-DD string.`);
|
|
27
|
+
}
|
|
22
28
|
if (!COMPATIBILITY_DATE_PATTERN.test(compatibilityDate)) {
|
|
23
29
|
throw new Error(
|
|
24
|
-
|
|
30
|
+
`${label} must use YYYY-MM-DD, received ${JSON.stringify(
|
|
31
|
+
compatibilityDate,
|
|
32
|
+
)}.`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (compatibilityDate < DEFAULT_COMPATIBILITY_DATE) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`${label} must be ${DEFAULT_COMPATIBILITY_DATE} or later, the date the Cloudflare worker Node.js built-in contract is verified against; received ${JSON.stringify(
|
|
25
38
|
compatibilityDate,
|
|
26
39
|
)}.`,
|
|
27
40
|
);
|
|
28
41
|
}
|
|
29
|
-
|
|
30
42
|
return compatibilityDate;
|
|
31
43
|
};
|
|
32
44
|
|
|
45
|
+
const getCompatibilityDate = (
|
|
46
|
+
modernConfig: CloudflareModernConfig,
|
|
47
|
+
wranglerCompatibilityDate: JsonValue | undefined,
|
|
48
|
+
) => {
|
|
49
|
+
if (wranglerCompatibilityDate !== undefined) {
|
|
50
|
+
// A raw Wrangler override is the effective date, so it is validated too.
|
|
51
|
+
return assertSupportedCompatibilityDate(
|
|
52
|
+
wranglerCompatibilityDate,
|
|
53
|
+
'deploy.worker.wrangler.compatibility_date',
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return assertSupportedCompatibilityDate(
|
|
57
|
+
modernConfig.deploy?.worker?.compatibilityDate?.trim() ||
|
|
58
|
+
DEFAULT_COMPATIBILITY_DATE,
|
|
59
|
+
'deploy.worker.compatibilityDate',
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
33
63
|
const getWorkerName = (appDirectory: string) => {
|
|
34
64
|
const basename = path.basename(appDirectory);
|
|
35
65
|
return basename.replace(/[^a-zA-Z0-9-_]/g, '-') || 'modern-cloudflare-worker';
|
|
@@ -59,6 +89,7 @@ const getConfiguredWrangler = (modernConfig: CloudflareModernConfig) => {
|
|
|
59
89
|
|
|
60
90
|
const createWranglerCompatibilityFlags = (
|
|
61
91
|
configuredFlags: JsonValue | undefined,
|
|
92
|
+
label = 'deploy.worker.wrangler.compatibility_flags',
|
|
62
93
|
) => {
|
|
63
94
|
if (configuredFlags === undefined) {
|
|
64
95
|
return [...REQUIRED_COMPATIBILITY_FLAGS];
|
|
@@ -68,14 +99,54 @@ const createWranglerCompatibilityFlags = (
|
|
|
68
99
|
!Array.isArray(configuredFlags) ||
|
|
69
100
|
configuredFlags.some(flag => typeof flag !== 'string')
|
|
70
101
|
) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
'deploy.worker.wrangler.compatibility_flags must be an array of strings.',
|
|
73
|
-
);
|
|
102
|
+
throw new Error(`${label} must be an array of strings.`);
|
|
74
103
|
}
|
|
75
104
|
|
|
76
105
|
return [...new Set([...configuredFlags, ...REQUIRED_COMPATIBILITY_FLAGS])];
|
|
77
106
|
};
|
|
78
107
|
|
|
108
|
+
// `wrangler deploy --env <name>` uses an environment's own compatibility_date
|
|
109
|
+
// and compatibility_flags instead of the top-level values, so each override
|
|
110
|
+
// is held to the same verified date floor and required flags.
|
|
111
|
+
const createWranglerEnvironments = (wranglerEnv: JsonValue | undefined) => {
|
|
112
|
+
if (wranglerEnv === undefined) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
if (!isJsonRecord(wranglerEnv)) {
|
|
116
|
+
throw new Error('deploy.worker.wrangler.env must be an object.');
|
|
117
|
+
}
|
|
118
|
+
return Object.fromEntries(
|
|
119
|
+
Object.entries(wranglerEnv).map(([name, environment]) => {
|
|
120
|
+
const label = `deploy.worker.wrangler.env.${name}`;
|
|
121
|
+
if (!isJsonRecord(environment)) {
|
|
122
|
+
throw new Error(`${label} must be an object.`);
|
|
123
|
+
}
|
|
124
|
+
return [
|
|
125
|
+
name,
|
|
126
|
+
{
|
|
127
|
+
...environment,
|
|
128
|
+
...(environment.compatibility_date === undefined
|
|
129
|
+
? {}
|
|
130
|
+
: {
|
|
131
|
+
compatibility_date: assertSupportedCompatibilityDate(
|
|
132
|
+
environment.compatibility_date,
|
|
133
|
+
`${label}.compatibility_date`,
|
|
134
|
+
),
|
|
135
|
+
}),
|
|
136
|
+
...(environment.compatibility_flags === undefined
|
|
137
|
+
? {}
|
|
138
|
+
: {
|
|
139
|
+
compatibility_flags: createWranglerCompatibilityFlags(
|
|
140
|
+
environment.compatibility_flags,
|
|
141
|
+
`${label}.compatibility_flags`,
|
|
142
|
+
),
|
|
143
|
+
}),
|
|
144
|
+
},
|
|
145
|
+
];
|
|
146
|
+
}),
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
79
150
|
const createWranglerAssetsConfig = (
|
|
80
151
|
configuredAssets: JsonValue | undefined,
|
|
81
152
|
) => {
|
|
@@ -312,6 +383,7 @@ export const createWranglerConfig = (
|
|
|
312
383
|
modernConfig: CloudflareModernConfig,
|
|
313
384
|
) => {
|
|
314
385
|
const wrangler = getConfiguredWrangler(modernConfig);
|
|
386
|
+
const environments = createWranglerEnvironments(wrangler.env);
|
|
315
387
|
const d1Databases = createWranglerD1Databases(
|
|
316
388
|
modernConfig,
|
|
317
389
|
wrangler.d1_databases,
|
|
@@ -325,13 +397,17 @@ export const createWranglerConfig = (
|
|
|
325
397
|
return {
|
|
326
398
|
$schema: 'node_modules/wrangler/config-schema.json',
|
|
327
399
|
name: getConfiguredWorkerName(appDirectory, modernConfig),
|
|
328
|
-
compatibility_date: getCompatibilityDate(modernConfig),
|
|
329
400
|
...wrangler,
|
|
401
|
+
compatibility_date: getCompatibilityDate(
|
|
402
|
+
modernConfig,
|
|
403
|
+
wrangler.compatibility_date,
|
|
404
|
+
),
|
|
330
405
|
main: WORKER_ENTRY,
|
|
331
406
|
compatibility_flags: createWranglerCompatibilityFlags(
|
|
332
407
|
wrangler.compatibility_flags,
|
|
333
408
|
),
|
|
334
409
|
assets: createWranglerAssetsConfig(wrangler.assets),
|
|
410
|
+
...(environments === undefined ? {} : { env: environments }),
|
|
335
411
|
...(d1Databases === undefined ? {} : { d1_databases: d1Databases }),
|
|
336
412
|
...(wranglerServices === undefined ? {} : { services: wranglerServices }),
|
|
337
413
|
};
|