@vinext/cloudflare 1.0.0-beta.8 → 1.0.0
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/README.md +174 -37
- package/dist/cache/cdn-adapter-config.d.ts +2 -1
- package/dist/cache/cdn-adapter-config.js +13 -5
- package/dist/cache/cdn-adapter.d.ts +5 -56
- package/dist/cache/cdn-adapter.js +3 -61
- package/dist/cache/cdn-adapter.runtime.d.ts +1 -0
- package/dist/cache/cdn-adapter.runtime.js +17 -3
- package/dist/cache/cdn-adapter.worker.d.ts +1 -0
- package/dist/cache/cdn-adapter.worker.js +6 -4
- package/dist/cache/cdn-build-id.d.ts +1 -1
- package/dist/cache/cdn-build-id.js +1 -1
- package/dist/cache/config.d.ts +137 -0
- package/dist/cache/config.js +87 -0
- package/dist/cache/kv-data-adapter.d.ts +5 -1
- package/dist/cache/kv-data-adapter.js +6 -2
- package/dist/cache/kv-data-adapter.runtime.js +13 -9
- package/dist/cache/kv-key.d.ts +7 -4
- package/dist/cache/kv-key.js +16 -5
- package/dist/cache/response-store-adapter.d.ts +36 -0
- package/dist/cache/response-store-adapter.js +26 -1
- package/dist/cache/response-store-adapter.self-contained.worker.d.ts +1 -0
- package/dist/cache/response-store-adapter.self-contained.worker.js +3 -1
- package/dist/cache/response-store-adapter.service-binding.worker.d.ts +1 -0
- package/dist/cache/response-store-adapter.service-binding.worker.js +3 -1
- package/dist/cache/response-store-adapter.worker.d.ts +1 -1
- package/dist/cache/response-store-adapter.worker.js +148 -81
- package/dist/cache/response-store-cdn.runtime.js +1 -0
- package/dist/cache/response-store-data.runtime.js +53 -31
- package/dist/cache/static-assets-adapter.build.d.ts +6 -0
- package/dist/cache/static-assets-adapter.build.js +65 -0
- package/dist/cache/static-assets-adapter.d.ts +27 -0
- package/dist/cache/static-assets-adapter.js +26 -0
- package/dist/cache/static-assets-adapter.runtime.d.ts +26 -0
- package/dist/cache/static-assets-adapter.runtime.js +77 -0
- package/dist/cache/static-assets-adapter.shared.d.ts +12 -0
- package/dist/cache/static-assets-adapter.shared.js +4 -0
- package/dist/cache/workers-cache-cdn-adapter.d.ts +58 -0
- package/dist/cache/workers-cache-cdn-adapter.js +65 -0
- package/dist/cacheability-artifact.d.ts +7 -1
- package/dist/cacheability-artifact.js +60 -21
- package/dist/cacheability-probe.d.ts +2 -0
- package/dist/cacheability-probe.js +107 -13
- package/dist/cdn-warm.d.ts +2 -1
- package/dist/cdn-warm.js +25 -8
- package/dist/deploy-config.d.ts +3 -8
- package/dist/deploy-config.js +5 -23
- package/dist/deploy-help.js +58 -47
- package/dist/deploy.d.ts +31 -21
- package/dist/deploy.js +501 -286
- package/dist/tpr.d.ts +29 -72
- package/dist/tpr.js +52 -601
- package/dist/version-deploy.d.ts +27 -0
- package/dist/version-deploy.js +125 -5
- package/dist/wrangler-config.d.ts +19 -0
- package/dist/wrangler-config.js +294 -0
- package/dist/wrangler-version-metadata.js +1 -1
- package/package.json +16 -9
- package/dist/prerender-kv-populate.d.ts +0 -24
- package/dist/prerender-kv-populate.js +0 -153
package/dist/deploy.js
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { writeCacheabilityManifestArtifact } from "./cacheability-artifact.js";
|
|
2
2
|
import { DEFAULT_CACHEABILITY_PROBE_RETRY_DELAY_MS, probeStagedWorkerCacheability, readPrerenderSecret } from "./cacheability-probe.js";
|
|
3
3
|
import { CdnOperationProgress, createCdnWarmTargets, createPrerenderWarmPlan, waitForCdnWarmTargetReadiness, warmCdnCache } from "./cdn-warm.js";
|
|
4
|
-
import { parseWranglerConfig
|
|
4
|
+
import { parseWranglerConfig } from "./wrangler-config.js";
|
|
5
|
+
import { resolveTPRRoutes, selectRoutes } from "./tpr.js";
|
|
5
6
|
import { VINEXT_EXPECTED_WORKER_VERSION_HEADER } from "./version-headers.js";
|
|
6
|
-
import { formatImageOptimizationHint, formatMissingCacheAdapterError, resolveCdnAdapterConfig,
|
|
7
|
+
import { formatImageOptimizationHint, formatMissingCacheAdapterError, resolveCdnAdapterConfig, viteConfigHasCacheAdapter, viteConfigHasCloudflarePlugin, viteConfigHasImageAdapter, workerEntryHasCacheHandler } from "./deploy-config.js";
|
|
7
8
|
import { assertCdnVersionMetadataConfig } from "./wrangler-version-metadata.js";
|
|
8
9
|
import { parseWorkerDeploymentUrl } from "./worker-deployment-url.js";
|
|
9
|
-
import { runWranglerDeploymentStatus, runWranglerTriggersDeploy, runWranglerVersionDeploy, runWranglerVersionUpload } from "./version-deploy.js";
|
|
10
|
-
import { buildPrerenderKVPairs } from "./prerender-kv-populate.js";
|
|
10
|
+
import { readBuildOutputWorkerName, runCfDeploymentStatus, runCfTriggersDeploy, runCfVersionDeploy, runCfVersionUpload, runWranglerDeploymentStatus, runWranglerTriggersDeploy, runWranglerVersionDeploy, runWranglerVersionUpload } from "./version-deploy.js";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
import { cacheabilityRoutePathname } from "vinext/internal/server/cacheability-manifest";
|
|
15
15
|
import { setTimeout } from "node:timers/promises";
|
|
16
16
|
import { DEFAULT_REMOTE_PATH_DISCOVERY_PHASE_TIMEOUT_MS, DEFAULT_REMOTE_PATH_DISCOVERY_RETRY_DELAY_MS, discoverPrerenderPathManifest, emitPrerenderPathManifest } from "vinext/internal/build/prerender-paths";
|
|
17
|
-
import
|
|
17
|
+
import { normalizePathTrailingSlash } from "vinext/shims/url-utils";
|
|
18
18
|
import { spawn } from "node:child_process";
|
|
19
19
|
import { parseArgs } from "node:util";
|
|
20
20
|
import { pathToFileURL } from "node:url";
|
|
21
|
+
import { VINEXT_BUILD_LIFECYCLE_CONFIG } from "vinext/internal/build/lifecycle";
|
|
21
22
|
import { runPrerender } from "vinext/internal/build/run-prerender";
|
|
23
|
+
import { printBuildReport } from "vinext/internal/build/report";
|
|
22
24
|
import { loadDotenv } from "vinext/internal/config/dotenv";
|
|
23
25
|
import { findVinextNextConfigInPlugins, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "vinext/internal/config/next-config";
|
|
24
|
-
import { findVinextCacheConfigInPlugins, findVinextPrerenderConfigInPlugins, findVinextRouteRootConfigInPlugins, formatVinextPrerenderLabel, hasBuildIdentityResponseHeader, hasUncachedRequestRouting, hasVerbatimResponseVary, isConfiguredCdnResponsePolicyHeader, requiresRouteCacheabilityProbeManifest, resolveVinextPrerenderDecision, supportsCanonicalRscWarmup
|
|
26
|
+
import { cacheWarmupStatusSource, finalizeCacheAdapterPrerenderOutput, findVinextCacheConfigInPlugins, findVinextPrerenderConfigInPlugins, findVinextRouteRootConfigInPlugins, formatVinextPrerenderLabel, hasBuildIdentityResponseHeader, hasCacheAdapterPrerenderOutput, hasUncachedRequestRouting, hasVerbatimResponseVary, isConfiguredCdnResponsePolicyHeader, requiresRouteCacheabilityProbeManifest, resolveVinextPrerenderDecision, supportsCanonicalRscWarmup } from "vinext/internal/config/prerender";
|
|
25
27
|
import { detectProject, findInNodeModules, formatMissingCloudflarePluginError, getMissingDeps } from "vinext/internal/utils/project";
|
|
26
28
|
import { PHASE_PRODUCTION_BUILD } from "vinext/shims/constants";
|
|
27
29
|
//#region src/deploy.ts
|
|
@@ -35,6 +37,17 @@ import { PHASE_PRODUCTION_BUILD } from "vinext/shims/constants";
|
|
|
35
37
|
* 3. Deploys to Cloudflare Workers via Wrangler
|
|
36
38
|
*/
|
|
37
39
|
const DEFAULT_CDN_WARM_PROMOTION_DELAY_MS = 15e3;
|
|
40
|
+
/** The typed cf Vite plugin emits Worker and asset bundles into Build Output. */
|
|
41
|
+
function resolvePrerenderOutputDirs(root, deploymentTool, configured) {
|
|
42
|
+
if (deploymentTool !== "cf") return configured;
|
|
43
|
+
const workerDir = path.join(root, ".cloudflare", "output", "v0", "workers", "default");
|
|
44
|
+
if (!fs.existsSync(path.join(workerDir, "worker.config.json"))) return configured;
|
|
45
|
+
return {
|
|
46
|
+
...configured,
|
|
47
|
+
rscOutDir: path.join(workerDir, "bundle"),
|
|
48
|
+
clientOutDir: path.join(workerDir, "assets")
|
|
49
|
+
};
|
|
50
|
+
}
|
|
38
51
|
function parsePositiveIntegerArg(raw, flag) {
|
|
39
52
|
if (raw === "") throw new Error(`${flag} requires a value, but none was provided.`);
|
|
40
53
|
const parsed = Number(raw);
|
|
@@ -54,7 +67,7 @@ function validateTimerDelay(value, flag, raw = String(value)) {
|
|
|
54
67
|
return value;
|
|
55
68
|
}
|
|
56
69
|
function validatePromotionDelay(value, raw = String(value)) {
|
|
57
|
-
return validateTimerDelay(value, "--warm-
|
|
70
|
+
return validateTimerDelay(value, "--warm-cache-promotion-delay", raw);
|
|
58
71
|
}
|
|
59
72
|
function validateCdnWarmTarget(raw) {
|
|
60
73
|
const value = raw.trim();
|
|
@@ -62,15 +75,16 @@ function validateCdnWarmTarget(raw) {
|
|
|
62
75
|
try {
|
|
63
76
|
url = new URL(value);
|
|
64
77
|
} catch {
|
|
65
|
-
throw new Error(`--warm-
|
|
78
|
+
throw new Error(`--warm-cache-target expects an HTTPS origin, but got "${raw}".`);
|
|
66
79
|
}
|
|
67
|
-
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") throw new Error(`--warm-
|
|
80
|
+
if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.port !== "" || url.pathname !== "/" || url.search !== "" || url.hash !== "") throw new Error(`--warm-cache-target expects an HTTPS origin without a path, query, credentials, or port, but got "${raw}".`);
|
|
68
81
|
return url.origin;
|
|
69
82
|
}
|
|
70
83
|
function formatUnknownError(error) {
|
|
71
84
|
if (error instanceof Error && error.message) return error.message;
|
|
72
85
|
return String(error);
|
|
73
86
|
}
|
|
87
|
+
var StagedWarmupError = class extends Error {};
|
|
74
88
|
/** Deploy command flag definitions for util.parseArgs. */
|
|
75
89
|
const deployArgOptions = {
|
|
76
90
|
help: {
|
|
@@ -102,6 +116,54 @@ const deployArgOptions = {
|
|
|
102
116
|
default: false
|
|
103
117
|
},
|
|
104
118
|
"prerender-concurrency": { type: "string" },
|
|
119
|
+
"warm-cache": {
|
|
120
|
+
type: "boolean",
|
|
121
|
+
default: false
|
|
122
|
+
},
|
|
123
|
+
"warm-cache-target": { type: "string" },
|
|
124
|
+
"warm-cache-concurrency": { type: "string" },
|
|
125
|
+
"warm-cache-timeout": { type: "string" },
|
|
126
|
+
"warm-cache-retries": { type: "string" },
|
|
127
|
+
"warm-cache-discovery-timeout": { type: "string" },
|
|
128
|
+
"warm-cache-discovery-retries": { type: "string" },
|
|
129
|
+
"warm-cache-probe-timeout": { type: "string" },
|
|
130
|
+
"warm-cache-probe-retries": { type: "string" },
|
|
131
|
+
"warm-cache-certify": {
|
|
132
|
+
type: "boolean",
|
|
133
|
+
default: false
|
|
134
|
+
},
|
|
135
|
+
"warm-cache-readiness-timeout": { type: "string" },
|
|
136
|
+
"warm-cache-readiness-retries": { type: "string" },
|
|
137
|
+
"warm-cache-readiness-probes": { type: "string" },
|
|
138
|
+
"warm-cache-readiness-probe-delay": { type: "string" },
|
|
139
|
+
"dangerously-promote-on-warm-cache-error": {
|
|
140
|
+
type: "boolean",
|
|
141
|
+
default: false
|
|
142
|
+
},
|
|
143
|
+
"no-promote": {
|
|
144
|
+
type: "boolean",
|
|
145
|
+
default: false
|
|
146
|
+
},
|
|
147
|
+
"warm-cache-no-promote": {
|
|
148
|
+
type: "boolean",
|
|
149
|
+
default: false
|
|
150
|
+
},
|
|
151
|
+
"warm-cache-promotion-delay": { type: "string" },
|
|
152
|
+
"warm-cache-include-fallbacks": {
|
|
153
|
+
type: "boolean",
|
|
154
|
+
default: false
|
|
155
|
+
},
|
|
156
|
+
"traffic-aware-warm-cache": {
|
|
157
|
+
type: "boolean",
|
|
158
|
+
default: false
|
|
159
|
+
},
|
|
160
|
+
"traffic-aware-coverage": { type: "string" },
|
|
161
|
+
"traffic-aware-limit": { type: "string" },
|
|
162
|
+
"traffic-aware-window": { type: "string" },
|
|
163
|
+
"dangerously-promote-on-cdn-warm-error": {
|
|
164
|
+
type: "boolean",
|
|
165
|
+
default: false
|
|
166
|
+
},
|
|
105
167
|
"experimental-warm-cdn-cache": {
|
|
106
168
|
type: "boolean",
|
|
107
169
|
default: false
|
|
@@ -122,10 +184,6 @@ const deployArgOptions = {
|
|
|
122
184
|
"warm-cdn-readiness-retries": { type: "string" },
|
|
123
185
|
"warm-cdn-readiness-probes": { type: "string" },
|
|
124
186
|
"warm-cdn-readiness-probe-delay": { type: "string" },
|
|
125
|
-
"dangerously-promote-on-cdn-warm-error": {
|
|
126
|
-
type: "boolean",
|
|
127
|
-
default: false
|
|
128
|
-
},
|
|
129
187
|
"warm-cdn-no-promote": {
|
|
130
188
|
type: "boolean",
|
|
131
189
|
default: false
|
|
@@ -135,6 +193,10 @@ const deployArgOptions = {
|
|
|
135
193
|
type: "boolean",
|
|
136
194
|
default: false
|
|
137
195
|
},
|
|
196
|
+
"experimental-traffic-aware-warm-cache": {
|
|
197
|
+
type: "boolean",
|
|
198
|
+
default: false
|
|
199
|
+
},
|
|
138
200
|
"experimental-tpr": {
|
|
139
201
|
type: "boolean",
|
|
140
202
|
default: false
|
|
@@ -149,8 +211,29 @@ function parseDeployArgs(args) {
|
|
|
149
211
|
options: deployArgOptions,
|
|
150
212
|
strict: true
|
|
151
213
|
});
|
|
152
|
-
|
|
153
|
-
|
|
214
|
+
values["dangerously-promote-on-warm-cache-error"] ||= values["dangerously-promote-on-cdn-warm-error"];
|
|
215
|
+
values["warm-cache"] ||= values["experimental-warm-cdn-cache"];
|
|
216
|
+
values["warm-cache-target"] ??= values["warm-cdn-target"];
|
|
217
|
+
values["warm-cache-concurrency"] ??= values["warm-cdn-concurrency"];
|
|
218
|
+
values["warm-cache-timeout"] ??= values["warm-cdn-timeout"];
|
|
219
|
+
values["warm-cache-retries"] ??= values["warm-cdn-retries"];
|
|
220
|
+
values["warm-cache-discovery-timeout"] ??= values["warm-cdn-discovery-timeout"];
|
|
221
|
+
values["warm-cache-discovery-retries"] ??= values["warm-cdn-discovery-retries"];
|
|
222
|
+
values["warm-cache-probe-timeout"] ??= values["warm-cdn-probe-timeout"];
|
|
223
|
+
values["warm-cache-probe-retries"] ??= values["warm-cdn-probe-retries"];
|
|
224
|
+
values["warm-cache-certify"] ||= values["warm-cdn-certify"];
|
|
225
|
+
values["warm-cache-readiness-timeout"] ??= values["warm-cdn-readiness-timeout"];
|
|
226
|
+
values["warm-cache-readiness-retries"] ??= values["warm-cdn-readiness-retries"];
|
|
227
|
+
values["warm-cache-readiness-probes"] ??= values["warm-cdn-readiness-probes"];
|
|
228
|
+
values["warm-cache-readiness-probe-delay"] ??= values["warm-cdn-readiness-probe-delay"];
|
|
229
|
+
values["warm-cache-no-promote"] ||= values["warm-cdn-no-promote"];
|
|
230
|
+
values["warm-cache-promotion-delay"] ??= values["warm-cdn-promotion-delay"];
|
|
231
|
+
values["warm-cache-include-fallbacks"] ||= values["warm-cdn-include-fallbacks"];
|
|
232
|
+
values["traffic-aware-warm-cache"] ||= values["experimental-traffic-aware-warm-cache"];
|
|
233
|
+
const trafficAwareWarmCache = values["traffic-aware-warm-cache"] || values["experimental-tpr"];
|
|
234
|
+
const warming = values["warm-cache"] || trafficAwareWarmCache;
|
|
235
|
+
if (values["warm-cache-certify"] && !warming) throw new Error("--warm-cache-certify requires --warm-cache or --traffic-aware-warm-cache.");
|
|
236
|
+
if (values["warm-cache-target"] && !warming) throw new Error("--warm-cache-target requires --warm-cache or --traffic-aware-warm-cache.");
|
|
154
237
|
function parseIntArg(name, raw) {
|
|
155
238
|
if (!raw) return void 0;
|
|
156
239
|
const n = parseInt(raw, 10);
|
|
@@ -171,28 +254,28 @@ function parseDeployArgs(args) {
|
|
|
171
254
|
verbose: values.verbose,
|
|
172
255
|
prerenderAll: values["prerender-all"],
|
|
173
256
|
prerenderConcurrency: values["prerender-concurrency"] === void 0 ? void 0 : parsePositiveIntegerArg(values["prerender-concurrency"], "--prerender-concurrency"),
|
|
174
|
-
warmCdnCache: values["
|
|
175
|
-
warmCdnTarget: values["warm-
|
|
176
|
-
warmCdnConcurrency: values["warm-
|
|
177
|
-
warmCdnTimeout: values["warm-
|
|
178
|
-
warmCdnRetries: values["warm-
|
|
179
|
-
warmCdnDiscoveryTimeout: values["warm-
|
|
180
|
-
warmCdnDiscoveryRetries: values["warm-
|
|
181
|
-
warmCdnProbeTimeout: values["warm-
|
|
182
|
-
warmCdnProbeRetries: values["warm-
|
|
183
|
-
warmCdnCertify: values["warm-
|
|
184
|
-
warmCdnReadinessTimeout: values["warm-
|
|
185
|
-
warmCdnReadinessRetries: values["warm-
|
|
186
|
-
warmCdnReadinessProbes: values["warm-
|
|
187
|
-
warmCdnReadinessProbeDelay: values["warm-
|
|
188
|
-
dangerouslyPromoteOnCdnWarmError: values["dangerously-promote-on-
|
|
189
|
-
warmCdnPromote: !values["warm-
|
|
190
|
-
warmCdnPromotionDelay: values["warm-
|
|
191
|
-
warmCdnIncludeFallbacks: values["warm-
|
|
192
|
-
experimentalTPR:
|
|
193
|
-
tprCoverage: parseIntArg("
|
|
194
|
-
tprLimit: parseIntArg("
|
|
195
|
-
tprWindow: parseIntArg("
|
|
257
|
+
warmCdnCache: values["warm-cache"],
|
|
258
|
+
warmCdnTarget: values["warm-cache-target"] === void 0 ? void 0 : validateCdnWarmTarget(values["warm-cache-target"]),
|
|
259
|
+
warmCdnConcurrency: values["warm-cache-concurrency"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-concurrency"], "--warm-cache-concurrency"),
|
|
260
|
+
warmCdnTimeout: values["warm-cache-timeout"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-timeout"], "--warm-cache-timeout"),
|
|
261
|
+
warmCdnRetries: values["warm-cache-retries"] === void 0 ? void 0 : parseNonNegativeIntegerArg(values["warm-cache-retries"], "--warm-cache-retries"),
|
|
262
|
+
warmCdnDiscoveryTimeout: values["warm-cache-discovery-timeout"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-discovery-timeout"], "--warm-cache-discovery-timeout"),
|
|
263
|
+
warmCdnDiscoveryRetries: values["warm-cache-discovery-retries"] === void 0 ? void 0 : parseNonNegativeIntegerArg(values["warm-cache-discovery-retries"], "--warm-cache-discovery-retries"),
|
|
264
|
+
warmCdnProbeTimeout: values["warm-cache-probe-timeout"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-probe-timeout"], "--warm-cache-probe-timeout"),
|
|
265
|
+
warmCdnProbeRetries: values["warm-cache-probe-retries"] === void 0 ? void 0 : parseNonNegativeIntegerArg(values["warm-cache-probe-retries"], "--warm-cache-probe-retries"),
|
|
266
|
+
warmCdnCertify: values["warm-cache-certify"],
|
|
267
|
+
warmCdnReadinessTimeout: values["warm-cache-readiness-timeout"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-readiness-timeout"], "--warm-cache-readiness-timeout"),
|
|
268
|
+
warmCdnReadinessRetries: values["warm-cache-readiness-retries"] === void 0 ? void 0 : parseNonNegativeIntegerArg(values["warm-cache-readiness-retries"], "--warm-cache-readiness-retries"),
|
|
269
|
+
warmCdnReadinessProbes: values["warm-cache-readiness-probes"] === void 0 ? void 0 : parsePositiveIntegerArg(values["warm-cache-readiness-probes"], "--warm-cache-readiness-probes"),
|
|
270
|
+
warmCdnReadinessProbeDelay: values["warm-cache-readiness-probe-delay"] === void 0 ? void 0 : validateTimerDelay(parseNonNegativeIntegerArg(values["warm-cache-readiness-probe-delay"], "--warm-cache-readiness-probe-delay"), "--warm-cache-readiness-probe-delay", values["warm-cache-readiness-probe-delay"]),
|
|
271
|
+
dangerouslyPromoteOnCdnWarmError: values["dangerously-promote-on-warm-cache-error"],
|
|
272
|
+
warmCdnPromote: !values["no-promote"] && !values["warm-cache-no-promote"],
|
|
273
|
+
warmCdnPromotionDelay: values["warm-cache-promotion-delay"] === void 0 ? void 0 : validatePromotionDelay(parseNonNegativeIntegerArg(values["warm-cache-promotion-delay"], "--warm-cache-promotion-delay"), values["warm-cache-promotion-delay"]),
|
|
274
|
+
warmCdnIncludeFallbacks: values["warm-cache-include-fallbacks"],
|
|
275
|
+
experimentalTPR: trafficAwareWarmCache,
|
|
276
|
+
tprCoverage: parseIntArg("traffic-aware-coverage", values["traffic-aware-coverage"] ?? values["tpr-coverage"]),
|
|
277
|
+
tprLimit: parseIntArg("traffic-aware-limit", values["traffic-aware-limit"] ?? values["tpr-limit"]),
|
|
278
|
+
tprWindow: parseIntArg("traffic-aware-window", values["traffic-aware-window"] ?? values["tpr-window"])
|
|
196
279
|
};
|
|
197
280
|
}
|
|
198
281
|
/**
|
|
@@ -242,10 +325,13 @@ async function loadProjectWranglerApi(root) {
|
|
|
242
325
|
pathToFileURL(wranglerPath).href
|
|
243
326
|
);
|
|
244
327
|
}
|
|
245
|
-
|
|
328
|
+
function resolveViteBuildMode(deploymentTool, env) {
|
|
329
|
+
return deploymentTool === "cf" ? env ?? "production" : "production";
|
|
330
|
+
}
|
|
331
|
+
async function loadDeployViteConfigMetadata(root, mode) {
|
|
246
332
|
const plugins = (await (await loadProjectViteApi(root)).loadConfigFromFile({
|
|
247
333
|
command: "build",
|
|
248
|
-
mode
|
|
334
|
+
mode
|
|
249
335
|
}, void 0, root))?.config.plugins;
|
|
250
336
|
return {
|
|
251
337
|
cacheConfig: await findVinextCacheConfigInPlugins(plugins),
|
|
@@ -254,32 +340,22 @@ async function loadDeployViteConfigMetadata(root) {
|
|
|
254
340
|
routeRootConfig: await findVinextRouteRootConfigInPlugins(plugins)
|
|
255
341
|
};
|
|
256
342
|
}
|
|
257
|
-
async function runBuild(info, env) {
|
|
343
|
+
async function runBuild(info, env, mode) {
|
|
258
344
|
console.log("\n Building for Cloudflare Workers...\n");
|
|
259
345
|
const { createBuilder } = await loadProjectViteApi(info.root);
|
|
346
|
+
let completed = false;
|
|
260
347
|
await withCloudflareEnv(env, async () => {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
ttlSeconds: kvConfig.ttlSeconds
|
|
270
|
-
});
|
|
271
|
-
if (pairs.length === 0) {
|
|
272
|
-
console.log(" KV cache: Skipping prerender upload (no App Router prerendered cache entries found).");
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
await runWranglerKVBulkPut(root, {
|
|
276
|
-
binding: kvConfig.binding,
|
|
277
|
-
env: wranglerEnv,
|
|
278
|
-
pairs
|
|
348
|
+
const invocation = { onComplete() {
|
|
349
|
+
completed = true;
|
|
350
|
+
} };
|
|
351
|
+
await (await createBuilder({
|
|
352
|
+
root: info.root,
|
|
353
|
+
mode,
|
|
354
|
+
[VINEXT_BUILD_LIFECYCLE_CONFIG]: invocation
|
|
355
|
+
})).buildApp();
|
|
279
356
|
});
|
|
280
|
-
|
|
357
|
+
if (!completed) throw new Error("[vinext] The Cloudflare build lifecycle did not complete.");
|
|
281
358
|
}
|
|
282
|
-
const KV_BULK_PUT_CHUNK_SIZE = 25;
|
|
283
359
|
function validateWranglerEnvName(env) {
|
|
284
360
|
if (env.includes("\0")) throw new Error("Wrangler environment names cannot contain null bytes.");
|
|
285
361
|
return env;
|
|
@@ -295,21 +371,25 @@ function buildWranglerDeployArgs(options) {
|
|
|
295
371
|
env
|
|
296
372
|
};
|
|
297
373
|
}
|
|
298
|
-
function
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
"
|
|
304
|
-
|
|
305
|
-
"
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
374
|
+
function resolveDeploymentTool(root) {
|
|
375
|
+
return fs.existsSync(path.join(root, "cloudflare.config.ts")) ? "cf" : "wrangler";
|
|
376
|
+
}
|
|
377
|
+
function isCfCliInstalled(root, resolvePackageJson = (projectRoot) => {
|
|
378
|
+
try {
|
|
379
|
+
return createRequire(path.join(projectRoot, "package.json")).resolve("cf/package.json");
|
|
380
|
+
} catch {
|
|
381
|
+
return findInNodeModules(projectRoot, "cf/package.json");
|
|
382
|
+
}
|
|
383
|
+
}) {
|
|
384
|
+
return resolvePackageJson(root) !== null;
|
|
385
|
+
}
|
|
386
|
+
function buildCfDeployArgs(options) {
|
|
387
|
+
const mode = options.env || (options.preview ? "preview" : void 0);
|
|
388
|
+
const args = ["deploy", "--prebuilt"];
|
|
389
|
+
if (mode) args.push("--mode", validateWranglerEnvName(mode));
|
|
310
390
|
return {
|
|
311
391
|
args,
|
|
312
|
-
|
|
392
|
+
mode
|
|
313
393
|
};
|
|
314
394
|
}
|
|
315
395
|
/**
|
|
@@ -333,6 +413,21 @@ function resolveWranglerBin(root, resolvePackageJson = (projectRoot) => {
|
|
|
333
413
|
}
|
|
334
414
|
return path.join(root, "node_modules", "wrangler", "bin", "wrangler.js");
|
|
335
415
|
}
|
|
416
|
+
function resolveCfBin(root, resolvePackageJson = (projectRoot) => {
|
|
417
|
+
try {
|
|
418
|
+
return createRequire(path.join(projectRoot, "package.json")).resolve("cf/package.json");
|
|
419
|
+
} catch {
|
|
420
|
+
return findInNodeModules(projectRoot, "cf/package.json");
|
|
421
|
+
}
|
|
422
|
+
}) {
|
|
423
|
+
const packageJsonPath = resolvePackageJson(root);
|
|
424
|
+
if (packageJsonPath) {
|
|
425
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
426
|
+
const bin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.cf;
|
|
427
|
+
if (bin) return path.resolve(path.dirname(packageJsonPath), bin);
|
|
428
|
+
}
|
|
429
|
+
return path.join(root, "node_modules", "cf", "bin", "cf");
|
|
430
|
+
}
|
|
336
431
|
function buildNodeCliInvocation(scriptPath, args, nodeExecutable = process.execPath) {
|
|
337
432
|
return {
|
|
338
433
|
file: nodeExecutable,
|
|
@@ -347,46 +442,8 @@ function buildWranglerInvocation(root, options, nodeExecutable = process.execPat
|
|
|
347
442
|
env
|
|
348
443
|
};
|
|
349
444
|
}
|
|
350
|
-
async function runWranglerKVBulkPut(root, options, execute = spawn, nodeExecutable = process.execPath) {
|
|
351
|
-
const tempDir = fs.mkdtempSync(path.join(options.tempDir ?? os.tmpdir(), "vinext-kv-bulk-"));
|
|
352
|
-
try {
|
|
353
|
-
const wranglerBin = resolveWranglerBin(root);
|
|
354
|
-
const totalChunks = Math.ceil(options.pairs.length / KV_BULK_PUT_CHUNK_SIZE);
|
|
355
|
-
for (let i = 0; i < totalChunks; i++) {
|
|
356
|
-
const filePath = path.join(tempDir, `prerender-kv-${i}.json`);
|
|
357
|
-
const chunk = options.pairs.slice(i * KV_BULK_PUT_CHUNK_SIZE, (i + 1) * KV_BULK_PUT_CHUNK_SIZE);
|
|
358
|
-
fs.writeFileSync(filePath, JSON.stringify(chunk), "utf-8");
|
|
359
|
-
const { args } = buildWranglerKVBulkPutArgs({
|
|
360
|
-
binding: options.binding,
|
|
361
|
-
env: options.env,
|
|
362
|
-
filePath
|
|
363
|
-
});
|
|
364
|
-
const invocation = buildNodeCliInvocation(wranglerBin, args, nodeExecutable);
|
|
365
|
-
const child = execute(invocation.file, invocation.args, {
|
|
366
|
-
cwd: root,
|
|
367
|
-
stdio: "inherit",
|
|
368
|
-
shell: false
|
|
369
|
-
});
|
|
370
|
-
await new Promise((resolve, reject) => {
|
|
371
|
-
child.once("error", reject);
|
|
372
|
-
child.once("close", (code, signal) => {
|
|
373
|
-
if (code === 0) {
|
|
374
|
-
resolve();
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
const exitReason = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
|
|
378
|
-
reject(/* @__PURE__ */ new Error(`Wrangler KV bulk put failed with ${exitReason}.`));
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
} finally {
|
|
383
|
-
fs.rmSync(tempDir, {
|
|
384
|
-
recursive: true,
|
|
385
|
-
force: true
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
445
|
async function runWranglerDeploy(root, options, execute = spawn) {
|
|
446
|
+
if (options.promote === false) return runWranglerVersionUpload(root, options).previewUrl ?? "(Preview URL not detected in wrangler output)";
|
|
390
447
|
const spawnOptions = {
|
|
391
448
|
cwd: root,
|
|
392
449
|
stdio: [
|
|
@@ -424,12 +481,95 @@ async function runWranglerDeploy(root, options, execute = spawn) {
|
|
|
424
481
|
});
|
|
425
482
|
return parseWorkerDeploymentUrl(output) ?? "(URL not detected in wrangler output)";
|
|
426
483
|
}
|
|
484
|
+
async function runCfDeploy(root, options, execute = spawn) {
|
|
485
|
+
const { args, mode } = buildCfDeployArgs(options);
|
|
486
|
+
console.log(mode ? `\n Deploying Build Output in mode: ${mode}...` : "\n Deploying Build Output...");
|
|
487
|
+
const child = execute(process.execPath, [resolveCfBin(root), ...args], {
|
|
488
|
+
cwd: root,
|
|
489
|
+
stdio: [
|
|
490
|
+
"inherit",
|
|
491
|
+
"pipe",
|
|
492
|
+
"pipe"
|
|
493
|
+
],
|
|
494
|
+
shell: false
|
|
495
|
+
});
|
|
496
|
+
let output = "";
|
|
497
|
+
child.stdout?.on("data", (chunk) => {
|
|
498
|
+
const text = chunk.toString();
|
|
499
|
+
output += text;
|
|
500
|
+
process.stdout.write(text);
|
|
501
|
+
});
|
|
502
|
+
child.stderr?.on("data", (chunk) => {
|
|
503
|
+
const text = chunk.toString();
|
|
504
|
+
output += text;
|
|
505
|
+
process.stderr.write(text);
|
|
506
|
+
});
|
|
507
|
+
await new Promise((resolve, reject) => {
|
|
508
|
+
child.once("error", reject);
|
|
509
|
+
child.once("close", (code, signal) => {
|
|
510
|
+
if (code === 0) resolve();
|
|
511
|
+
else reject(/* @__PURE__ */ new Error(`cf deploy failed with ${signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`}.`));
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
return parseWorkerDeploymentUrl(output) ?? "(URL not detected in cf output)";
|
|
515
|
+
}
|
|
427
516
|
function hasCdnWarmRequests(plan) {
|
|
428
517
|
return plan.paths.length + (plan.pagesDataPaths?.length ?? 0) + (plan.routeHandlerPaths?.length ?? 0) + plan.rscPaths.length + plan.loadingShellPaths.length > 0;
|
|
429
518
|
}
|
|
519
|
+
function selectTPRWarmPlan(plan, traffic, coverage, limit) {
|
|
520
|
+
const canonical = (pathname) => normalizePathTrailingSlash(pathname, false);
|
|
521
|
+
const resolved = new Set(Object.entries(plan.routePatterns ?? {}).map(([pathname, route]) => canonical(route.cacheabilityProbe?.concretePathname ?? pathname)));
|
|
522
|
+
const requestsByPath = /* @__PURE__ */ new Map();
|
|
523
|
+
for (const { path, requests } of traffic) {
|
|
524
|
+
const pathname = canonical(path);
|
|
525
|
+
if (!resolved.has(pathname)) continue;
|
|
526
|
+
requestsByPath.set(pathname, (requestsByPath.get(pathname) ?? 0) + requests);
|
|
527
|
+
}
|
|
528
|
+
const selected = new Set(selectRoutes(Array.from(requestsByPath, ([path, requests]) => ({
|
|
529
|
+
path,
|
|
530
|
+
requests
|
|
531
|
+
})).sort((a, b) => b.requests - a.requests), coverage, limit).routes.map(({ path }) => path));
|
|
532
|
+
const includes = (pathname) => selected.has(canonical(plan.routePatterns?.[pathname]?.cacheabilityProbe?.concretePathname ?? pathname));
|
|
533
|
+
const filter = (pathnames) => pathnames?.filter(includes);
|
|
534
|
+
return {
|
|
535
|
+
...plan,
|
|
536
|
+
appPaths: filter(plan.appPaths),
|
|
537
|
+
loadingShellPaths: filter(plan.loadingShellPaths) ?? [],
|
|
538
|
+
pagesDataPaths: filter(plan.pagesDataPaths),
|
|
539
|
+
pagesPaths: filter(plan.pagesPaths),
|
|
540
|
+
paths: filter(plan.paths) ?? [],
|
|
541
|
+
routeHandlerPaths: filter(plan.routeHandlerPaths),
|
|
542
|
+
routePatterns: plan.routePatterns ? Object.fromEntries(Object.entries(plan.routePatterns).filter(([pathname]) => includes(pathname))) : void 0,
|
|
543
|
+
rscPaths: filter(plan.rscPaths) ?? []
|
|
544
|
+
};
|
|
545
|
+
}
|
|
430
546
|
function projectRequiresRouteCacheabilityProbeManifest(project, cacheConfig) {
|
|
431
547
|
return (project.isAppRouter || project.isPagesRouter) && requiresRouteCacheabilityProbeManifest(cacheConfig);
|
|
432
548
|
}
|
|
549
|
+
function deploymentWorkerName(options) {
|
|
550
|
+
if (!options.name) throw new Error("Could not detect the Worker name for its deployment.");
|
|
551
|
+
return options.name;
|
|
552
|
+
}
|
|
553
|
+
function runDeploymentStatus(root, options) {
|
|
554
|
+
return options.deploymentTool === "cf" ? runCfDeploymentStatus(root, {
|
|
555
|
+
name: deploymentWorkerName(options),
|
|
556
|
+
env: options.env,
|
|
557
|
+
verbose: options.verbose
|
|
558
|
+
}) : runWranglerDeploymentStatus(root, options);
|
|
559
|
+
}
|
|
560
|
+
function runVersionDeploy(root, traffic, options, phase) {
|
|
561
|
+
return options.deploymentTool === "cf" ? runCfVersionDeploy(root, traffic, {
|
|
562
|
+
name: deploymentWorkerName(options),
|
|
563
|
+
env: options.env,
|
|
564
|
+
verbose: options.verbose
|
|
565
|
+
}, phase) : runWranglerVersionDeploy(root, traffic, options, phase);
|
|
566
|
+
}
|
|
567
|
+
function runTriggersDeploy(root, options) {
|
|
568
|
+
return options.deploymentTool === "cf" ? runCfTriggersDeploy(root, options) : runWranglerTriggersDeploy(root, options);
|
|
569
|
+
}
|
|
570
|
+
function runVersionUpload(root, options) {
|
|
571
|
+
return options.deploymentTool === "cf" ? runCfVersionUpload(root, options) : runWranglerVersionUpload(root, options);
|
|
572
|
+
}
|
|
433
573
|
function cdnWarmTargetKey(target) {
|
|
434
574
|
return `${target.kind}\0${target.sourcePathname}`;
|
|
435
575
|
}
|
|
@@ -449,14 +589,14 @@ async function deployWithCdnWarmup(root, paths, options) {
|
|
|
449
589
|
...options,
|
|
450
590
|
warmCdnTarget: validateCdnWarmTarget(options.warmCdnTarget)
|
|
451
591
|
};
|
|
452
|
-
if (options.warmCdnDiscoveryTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnDiscoveryTimeout), "--warm-
|
|
453
|
-
if (options.warmCdnDiscoveryRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnDiscoveryRetries), "--warm-
|
|
454
|
-
if (options.warmCdnProbeTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnProbeTimeout), "--warm-
|
|
455
|
-
if (options.warmCdnProbeRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnProbeRetries), "--warm-
|
|
456
|
-
if (options.warmCdnReadinessTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnReadinessTimeout), "--warm-
|
|
457
|
-
if (options.warmCdnReadinessRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnReadinessRetries), "--warm-
|
|
458
|
-
if (options.warmCdnReadinessProbes !== void 0) parsePositiveIntegerArg(String(options.warmCdnReadinessProbes), "--warm-
|
|
459
|
-
if (options.warmCdnReadinessProbeDelay !== void 0) validateTimerDelay(options.warmCdnReadinessProbeDelay, "--warm-
|
|
592
|
+
if (options.warmCdnDiscoveryTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnDiscoveryTimeout), "--warm-cache-discovery-timeout");
|
|
593
|
+
if (options.warmCdnDiscoveryRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnDiscoveryRetries), "--warm-cache-discovery-retries");
|
|
594
|
+
if (options.warmCdnProbeTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnProbeTimeout), "--warm-cache-probe-timeout");
|
|
595
|
+
if (options.warmCdnProbeRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnProbeRetries), "--warm-cache-probe-retries");
|
|
596
|
+
if (options.warmCdnReadinessTimeout !== void 0) parsePositiveIntegerArg(String(options.warmCdnReadinessTimeout), "--warm-cache-readiness-timeout");
|
|
597
|
+
if (options.warmCdnReadinessRetries !== void 0) parseNonNegativeIntegerArg(String(options.warmCdnReadinessRetries), "--warm-cache-readiness-retries");
|
|
598
|
+
if (options.warmCdnReadinessProbes !== void 0) parsePositiveIntegerArg(String(options.warmCdnReadinessProbes), "--warm-cache-readiness-probes");
|
|
599
|
+
if (options.warmCdnReadinessProbeDelay !== void 0) validateTimerDelay(options.warmCdnReadinessProbeDelay, "--warm-cache-readiness-probe-delay");
|
|
460
600
|
if (options.warmCdnPromotionDelay !== void 0) validatePromotionDelay(options.warmCdnPromotionDelay);
|
|
461
601
|
if (options.cacheabilityProbe) return deployWithCacheabilityProbe(root, options);
|
|
462
602
|
return deployUploadedVersionWithCdnWarmup(root, paths, options);
|
|
@@ -481,7 +621,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
481
621
|
if (plan.paths.length === 0 && plan.pagesDataPaths.length === 0 && (plan.routeHandlerPaths?.length ?? 0) === 0 || expectedBuildId !== void 0) return plan;
|
|
482
622
|
if (!allowUnverifiedPromotion) {
|
|
483
623
|
const warmupKind = plan.paths.length > 0 ? "CDN HTML warmup" : plan.pagesDataPaths.length > 0 ? "CDN Pages data warmup" : "CDN Route Handler warmup";
|
|
484
|
-
throw new Error(`${warmupKind} requires a CDN adapter that declares build-identity response headers. Configure that adapter capability or deploy without --
|
|
624
|
+
throw new Error(`${warmupKind} requires a CDN adapter that declares build-identity response headers. Configure that adapter capability or deploy without --warm-cache.`);
|
|
485
625
|
}
|
|
486
626
|
console.warn(` CDN warmup: skipping ${plan.paths.length} HTML, ${plan.pagesDataPaths.length} Pages data, and ${plan.routeHandlerPaths?.length ?? 0} Route Handler request(s) because the CDN adapter does not declare build-identity response headers.`);
|
|
487
627
|
return {
|
|
@@ -493,10 +633,11 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
493
633
|
};
|
|
494
634
|
const discoverWarmPlan = async (targetUrl, headers) => {
|
|
495
635
|
if (!options.discoverWarmPlan) return;
|
|
496
|
-
const
|
|
636
|
+
const discovered = await options.discoverWarmPlan({
|
|
497
637
|
headers,
|
|
498
638
|
targetUrl
|
|
499
639
|
});
|
|
640
|
+
const plan = options.selectWarmPlan?.(discovered) ?? discovered;
|
|
500
641
|
deploymentId = plan.deploymentId;
|
|
501
642
|
expectedBuildId = plan.buildIdentity;
|
|
502
643
|
expectedRscBuildId = plan.rscBuildId;
|
|
@@ -512,7 +653,8 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
512
653
|
warmPlanDiscovered = true;
|
|
513
654
|
};
|
|
514
655
|
if (!options.discoverWarmPlan || hasPreparedWarmPlan) remainingWarmPlan = prepareWarmPlan(remainingWarmPlan);
|
|
515
|
-
const upload = options.uploadedVersion ??
|
|
656
|
+
const upload = options.uploadedVersion ?? runVersionUpload(root, options);
|
|
657
|
+
const wranglerOptions = resolveDeploymentControlPlaneOptions(options, upload);
|
|
516
658
|
const warmUploadedVersion = (targetUrl, headers, propagatingTarget = false, plan = {
|
|
517
659
|
loadingShellPaths: remainingWarmPlan.loadingShellPaths,
|
|
518
660
|
pagesDataPaths: remainingWarmPlan.pagesDataPaths,
|
|
@@ -541,11 +683,17 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
541
683
|
strict: requireCacheHit || !allowUnverifiedPromotion,
|
|
542
684
|
statusSource: options.statusSource
|
|
543
685
|
});
|
|
544
|
-
const wranglerConfig = parseWranglerConfig(root, options.config);
|
|
545
|
-
|
|
546
|
-
|
|
686
|
+
const wranglerConfig = options.deploymentTool === "cf" ? null : parseWranglerConfig(root, options.config);
|
|
687
|
+
let deploymentStatus;
|
|
688
|
+
try {
|
|
689
|
+
deploymentStatus = runDeploymentStatus(root, wranglerOptions);
|
|
690
|
+
} catch (error) {
|
|
691
|
+
if (!hasPreparedWarmPlan) throw error;
|
|
692
|
+
throw new StagedWarmupError(formatUnknownError(error), { cause: error });
|
|
693
|
+
}
|
|
694
|
+
if (options.expectedDeploymentState && !deploymentStateEquals(deploymentStatus, options.expectedDeploymentState)) throw new StagedWarmupError("Two-stage CDN warming stopped because Worker deployment traffic or deployment identity changed before the final version could be staged. No final version was promoted.");
|
|
547
695
|
const stagingTraffic = getZeroPercentStagingTraffic(deploymentStatus, upload.versionId);
|
|
548
|
-
if (hasPreparedWarmPlan && !stagingTraffic) throw new
|
|
696
|
+
if (hasPreparedWarmPlan && !stagingTraffic) throw new StagedWarmupError("Two-stage CDN warming stopped because Worker deployment traffic changed before the final version could be staged. No final version was promoted.");
|
|
549
697
|
let staged = null;
|
|
550
698
|
let triggersDeployedUrl = options.triggersDeployedUrl ?? null;
|
|
551
699
|
let stagedCacheFilled = false;
|
|
@@ -554,14 +702,14 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
554
702
|
let triggersApplied = options.triggersAlreadyApplied === true;
|
|
555
703
|
function applyTriggers() {
|
|
556
704
|
if (triggersApplied) return;
|
|
557
|
-
triggersDeployedUrl =
|
|
705
|
+
triggersDeployedUrl = runTriggersDeploy(root, wranglerOptions).deployedUrl;
|
|
558
706
|
triggersApplied = true;
|
|
559
707
|
}
|
|
560
708
|
if (stagingTraffic) {
|
|
561
709
|
try {
|
|
562
|
-
staged =
|
|
710
|
+
staged = runVersionDeploy(root, stagingTraffic, wranglerOptions, "stage");
|
|
563
711
|
} catch (error) {
|
|
564
|
-
throw reconcileVersionDeployFailure(root,
|
|
712
|
+
throw reconcileVersionDeployFailure(root, wranglerOptions, error, {
|
|
565
713
|
desiredTraffic: stagingTraffic,
|
|
566
714
|
desiredDescription: "The uploaded version is staged at 0% with the previous version still serving 100% traffic; Worker triggers/routes were not changed.",
|
|
567
715
|
priorState: deploymentStatus,
|
|
@@ -570,7 +718,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
570
718
|
}
|
|
571
719
|
try {
|
|
572
720
|
if (hasPreparedWarmPlan) {
|
|
573
|
-
stagedDeploymentState =
|
|
721
|
+
stagedDeploymentState = runDeploymentStatus(root, wranglerOptions);
|
|
574
722
|
if (!deploymentTrafficEquals(stagedDeploymentState.versions, stagingTraffic)) throw new Error("Two-stage CDN warming stopped because Worker deployment traffic changed before production triggers could be applied. No final version was promoted.");
|
|
575
723
|
}
|
|
576
724
|
applyTriggers();
|
|
@@ -578,7 +726,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
578
726
|
throw withStagedVersionCleanupNote(error);
|
|
579
727
|
}
|
|
580
728
|
const targetUrl = resolveCdnWarmupTargetUrl(root, triggersDeployedUrl, options) ?? staged.deployedUrl;
|
|
581
|
-
const headers = buildVersionOverrideHeaders(options.name ?? upload.workerName ?? resolveWorkerNameForVersionOverride(wranglerConfig,
|
|
729
|
+
const headers = buildVersionOverrideHeaders(options.name ?? upload.workerName ?? resolveWorkerNameForVersionOverride(wranglerConfig, wranglerOptions), upload.versionId);
|
|
582
730
|
if (targetUrl && headers) try {
|
|
583
731
|
if (!warmPlanDiscovered) {
|
|
584
732
|
console.log(" CDN warmup: discovering paths from the staged Worker version...");
|
|
@@ -620,7 +768,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
620
768
|
console.log(" CDN warmup: staged Worker version is stable.");
|
|
621
769
|
const warmResult = await warmUploadedVersion(targetUrl, headers, true, stagedWarmPlan);
|
|
622
770
|
const optionalSkipped = options.optionalWarmTargetKeys ? warmResult.skippedTargets.filter((target) => options.optionalWarmTargetKeys.has(cdnWarmTargetKey(target))).length : 0;
|
|
623
|
-
if (hasPreparedWarmPlan && options.warmCdnCertify) {
|
|
771
|
+
if ((hasPreparedWarmPlan || options.selectWarmPlan) && options.warmCdnCertify) {
|
|
624
772
|
if (warmResult.warmed + optionalSkipped !== stagedWarmRequests) throw new Error(`CDN warmup cannot certify the staged cache because only ${warmResult.warmed}/${stagedWarmRequests - optionalSkipped} cacheable entries completed their initial fill.`);
|
|
625
773
|
}
|
|
626
774
|
const requiredSkipped = warmResult.skipped - optionalSkipped;
|
|
@@ -637,7 +785,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
637
785
|
routeHandlerPaths: warmResult.retryPlan.routeHandlerPaths,
|
|
638
786
|
rscPaths: warmResult.retryPlan.rscPaths
|
|
639
787
|
};
|
|
640
|
-
if (
|
|
788
|
+
if (options.warmCdnCertify && warmResult.warmed > 0) {
|
|
641
789
|
console.log(` CDN warmup: certifying ${warmResult.warmed} staged cache entr${warmResult.warmed === 1 ? "y" : "ies"} before promotion...`);
|
|
642
790
|
const certification = await warmUploadedVersion(targetUrl, headers, true, warmResult.warmedPlan, true);
|
|
643
791
|
if (certification.warmed !== warmResult.warmed) throw new Error(`CDN warmup certified ${certification.warmed}/${warmResult.warmed} staged cache entries as reusable.`);
|
|
@@ -649,8 +797,8 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
649
797
|
throw withStagedVersionCleanupNote(error);
|
|
650
798
|
}
|
|
651
799
|
else if (initialWarmRequests > 0) {
|
|
652
|
-
const message = "CDN warmup failed: pre-traffic warmup needs a production URL and Worker name for version overrides. Configure a route/custom domain and Worker name, or deploy without --
|
|
653
|
-
if (!allowUnverifiedPromotion) throw new
|
|
800
|
+
const message = "CDN warmup failed: pre-traffic warmup needs a production URL and Worker name for version overrides. Configure a route/custom domain and Worker name, or deploy without --warm-cache.";
|
|
801
|
+
if (!allowUnverifiedPromotion) throw new StagedWarmupError(`${message} ${getStagedVersionCleanupNote()}`);
|
|
654
802
|
console.warn(` ${message} Promoting because the dangerous override is enabled.`);
|
|
655
803
|
}
|
|
656
804
|
} else {
|
|
@@ -661,23 +809,26 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
661
809
|
}
|
|
662
810
|
console.warn(" CDN warmup: pre-traffic version override skipped because the current deployment is not one version serving 100% traffic.");
|
|
663
811
|
}
|
|
812
|
+
if (options.selectWarmPlan && options.warmCdnCertify && !stagedCacheFilled) {
|
|
813
|
+
const error = /* @__PURE__ */ new Error("CDN warmup cannot succeed because no cache entries were certified.");
|
|
814
|
+
throw staged ? withStagedVersionCleanupNote(error) : error;
|
|
815
|
+
}
|
|
664
816
|
const countRemainingWarmRequests = () => remainingWarmPlan.paths.length + remainingWarmPlan.pagesDataPaths.length + (remainingWarmPlan.routeHandlerPaths?.length ?? 0) + remainingWarmPlan.rscPaths.length + remainingWarmPlan.loadingShellPaths.length;
|
|
665
817
|
if (options.warmCdnPromote === false) {
|
|
666
818
|
if (!staged) throw new Error("CDN warmup cannot skip promotion because the uploaded Worker version could not be staged at 0% traffic. The current deployment must have exactly one version serving 100% traffic.");
|
|
667
819
|
const remainingWarmRequests = countRemainingWarmRequests();
|
|
668
|
-
if (!hasPreparedWarmPlan && options.discoverWarmPlan && discoveredWarmRequests === 0) throw withStagedVersionCleanupNote(/* @__PURE__ */ new Error("CDN warmup cannot skip promotion because no build-discovered requests were found to warm."));
|
|
820
|
+
if (!options.allowEmptyWarmPlan && !hasPreparedWarmPlan && options.discoverWarmPlan && discoveredWarmRequests === 0) throw withStagedVersionCleanupNote(/* @__PURE__ */ new Error("CDN warmup cannot skip promotion because no build-discovered requests were found to warm."));
|
|
669
821
|
if (remainingWarmRequests > 0) throw withStagedVersionCleanupNote(/* @__PURE__ */ new Error(`CDN warmup cannot skip promotion because ${remainingWarmRequests} request(s) remain unwarmed.`));
|
|
670
822
|
if (hasPreparedWarmPlan && stagedDeploymentState) {
|
|
671
823
|
let currentDeployment;
|
|
672
824
|
try {
|
|
673
|
-
currentDeployment =
|
|
825
|
+
currentDeployment = runDeploymentStatus(root, wranglerOptions);
|
|
674
826
|
} catch (error) {
|
|
675
|
-
|
|
676
|
-
throw new Error(`${message} CDN warmup cannot confirm that the uploaded Worker remains staged at 0% traffic; production Worker triggers/routes remain applied. Inspect \`wrangler deployments status\` before continuing.`, { cause: error });
|
|
827
|
+
throw new StagedWarmupError(`${error instanceof Error ? error.message : String(error)} CDN warmup cannot confirm that the uploaded Worker remains staged at 0% traffic; production Worker triggers/routes remain applied. Inspect the active Worker deployment before continuing.`, { cause: error });
|
|
677
828
|
}
|
|
678
|
-
if (!deploymentStateEquals(currentDeployment, stagedDeploymentState)) throw new
|
|
829
|
+
if (!deploymentStateEquals(currentDeployment, stagedDeploymentState)) throw new StagedWarmupError("Two-stage CDN warming stopped because Worker deployment traffic or deployment identity changed before the no-promote handoff. The uploaded Worker is not confirmed staged at 0% traffic; production Worker triggers/routes remain applied.");
|
|
679
830
|
}
|
|
680
|
-
console.log(
|
|
831
|
+
console.log(` CDN warmup: promotion disabled; uploaded Worker version ${upload.versionId} remains staged at 0% traffic and production Worker triggers/routes remain applied.`);
|
|
681
832
|
return staged.deployedUrl ?? triggersDeployedUrl ?? upload.previewUrl ?? "(URL not detected in wrangler output)";
|
|
682
833
|
}
|
|
683
834
|
let deployed;
|
|
@@ -696,13 +847,13 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
696
847
|
}
|
|
697
848
|
}
|
|
698
849
|
if (hasPreparedWarmPlan && stagingTraffic) {
|
|
699
|
-
prePromotionState =
|
|
850
|
+
prePromotionState = runDeploymentStatus(root, wranglerOptions);
|
|
700
851
|
if (!deploymentTrafficEquals(prePromotionState.versions, stagingTraffic) || stagedDeploymentState && !deploymentStateEquals(prePromotionState, stagedDeploymentState)) throw new Error("Two-stage CDN warming stopped because Worker deployment traffic or deployment identity changed before the final version could be promoted. No final version was promoted.");
|
|
701
852
|
}
|
|
702
853
|
promotionAttempted = true;
|
|
703
|
-
deployed =
|
|
854
|
+
deployed = runVersionDeploy(root, promotionTraffic, wranglerOptions, stagedCacheFilled ? "promote-warmed" : "promote-uploaded");
|
|
704
855
|
} catch (error) {
|
|
705
|
-
if (promotionAttempted) throw reconcileVersionDeployFailure(root,
|
|
856
|
+
if (promotionAttempted) throw reconcileVersionDeployFailure(root, wranglerOptions, error, {
|
|
706
857
|
desiredTraffic: promotionTraffic,
|
|
707
858
|
desiredDescription: "The uploaded version is already promoted to 100%; Worker triggers/routes may already have changed.",
|
|
708
859
|
priorState: prePromotionState ?? (stagingTraffic ? {
|
|
@@ -734,7 +885,7 @@ async function deployUploadedVersionWithCdnWarmup(root, paths, options) {
|
|
|
734
885
|
} catch (error) {
|
|
735
886
|
throw withPromotedVersionWarmupNote(error);
|
|
736
887
|
}
|
|
737
|
-
else if (!allowUnverifiedPromotion) throw withPromotedVersionWarmupNote(/* @__PURE__ */ new Error("CDN warmup failed: no production URL could be inferred from wrangler config or output. Configure a route/custom domain, ensure Wrangler prints a workers.dev URL, or deploy without --
|
|
888
|
+
else if (!allowUnverifiedPromotion) throw withPromotedVersionWarmupNote(/* @__PURE__ */ new Error("CDN warmup failed: no production URL could be inferred from wrangler config or output. Configure a route/custom domain, ensure Wrangler prints a workers.dev URL, or deploy without --warm-cache."));
|
|
738
889
|
else console.warn(" CDN warmup skipped: no production URL could be inferred after promotion; the dangerous override was enabled.");
|
|
739
890
|
}
|
|
740
891
|
return deployed.deployedUrl ?? triggersDeployedUrl ?? staged?.deployedUrl ?? upload.previewUrl ?? "(URL not detected in wrangler output)";
|
|
@@ -752,31 +903,36 @@ function deploymentStateEquals(actual, expected) {
|
|
|
752
903
|
function reconcileVersionDeployFailure(root, options, error, expected) {
|
|
753
904
|
const message = error instanceof Error ? error.message : String(error);
|
|
754
905
|
let reconciliation;
|
|
906
|
+
let mayNeedCleanup = true;
|
|
755
907
|
try {
|
|
756
|
-
const current =
|
|
908
|
+
const current = runDeploymentStatus(root, options);
|
|
757
909
|
if (deploymentTrafficEquals(current.versions, expected.desiredTraffic)) reconciliation = expected.desiredDescription;
|
|
758
|
-
else if (deploymentStateEquals(current, expected.priorState))
|
|
759
|
-
|
|
910
|
+
else if (deploymentStateEquals(current, expected.priorState)) {
|
|
911
|
+
reconciliation = expected.priorDescription;
|
|
912
|
+
mayNeedCleanup = false;
|
|
913
|
+
} else reconciliation = "Worker deployment state differs from both the requested and prior state, so the deployment outcome is unknown or another deployment changed it.";
|
|
760
914
|
} catch (reconciliationError) {
|
|
761
915
|
reconciliation = `Worker deployment status could not be read after the command failed, so the deployment outcome is unknown (${reconciliationError instanceof Error ? reconciliationError.message : String(reconciliationError)}).`;
|
|
762
916
|
}
|
|
763
|
-
|
|
917
|
+
const detail = `${message} ${reconciliation}`;
|
|
918
|
+
return mayNeedCleanup ? new StagedWarmupError(detail, { cause: error }) : new Error(detail, { cause: error });
|
|
764
919
|
}
|
|
765
920
|
function assertDeploymentStateUnchanged(root, options, expected, message) {
|
|
766
|
-
if (!deploymentStateEquals(
|
|
921
|
+
if (!deploymentStateEquals(runDeploymentStatus(root, options), expected)) throw new Error(message);
|
|
767
922
|
}
|
|
768
923
|
async function deployWithCacheabilityProbe(root, options) {
|
|
769
924
|
if (!options.discoverWarmPlan) throw new Error("Two-stage CDN warming requires staged Worker route discovery before cacheability probing.");
|
|
770
925
|
const prerenderSecret = readPrerenderSecret(root);
|
|
771
|
-
const probeUpload =
|
|
772
|
-
const
|
|
926
|
+
const probeUpload = runVersionUpload(root, options);
|
|
927
|
+
const wranglerOptions = resolveDeploymentControlPlaneOptions(options, probeUpload);
|
|
928
|
+
const initialDeployment = runDeploymentStatus(root, wranglerOptions);
|
|
773
929
|
const probeTraffic = getZeroPercentStagingTraffic(initialDeployment, probeUpload.versionId);
|
|
774
930
|
if (!probeTraffic) throw new Error("Two-stage CDN warming cannot stage the probe Worker at 0% because the current deployment is not exactly one version serving 100% traffic. No traffic or triggers were changed.");
|
|
775
931
|
let stagedProbe;
|
|
776
932
|
try {
|
|
777
|
-
stagedProbe =
|
|
933
|
+
stagedProbe = runVersionDeploy(root, probeTraffic, wranglerOptions, "stage");
|
|
778
934
|
} catch (error) {
|
|
779
|
-
throw reconcileVersionDeployFailure(root,
|
|
935
|
+
throw reconcileVersionDeployFailure(root, wranglerOptions, error, {
|
|
780
936
|
desiredTraffic: probeTraffic,
|
|
781
937
|
desiredDescription: "The probe version is staged at 0% with the previous version still serving 100% traffic; production Worker triggers/routes were not changed.",
|
|
782
938
|
priorState: initialDeployment,
|
|
@@ -785,17 +941,16 @@ async function deployWithCacheabilityProbe(root, options) {
|
|
|
785
941
|
}
|
|
786
942
|
let stagedProbeDeployment;
|
|
787
943
|
try {
|
|
788
|
-
stagedProbeDeployment =
|
|
944
|
+
stagedProbeDeployment = runDeploymentStatus(root, wranglerOptions);
|
|
789
945
|
if (!deploymentTrafficEquals(stagedProbeDeployment.versions, probeTraffic)) throw new Error("Two-stage CDN warming stopped because Worker deployment traffic changed immediately after the probe version was staged.");
|
|
790
946
|
} catch (error) {
|
|
791
|
-
|
|
792
|
-
throw new Error(`${message} The probe staging command completed, but its current deployment state could not be confirmed; production Worker triggers/routes were not changed. Inspect \`wrangler deployments status\` and remove the staged probe version if necessary.`, { cause: error });
|
|
947
|
+
throw new StagedWarmupError(`${error instanceof Error ? error.message : String(error)} The probe staging command completed, but its current deployment state could not be confirmed; production Worker triggers/routes were not changed. Inspect the active Worker deployment and remove the staged probe version if necessary.`, { cause: error });
|
|
793
948
|
}
|
|
794
949
|
let prepared;
|
|
795
950
|
try {
|
|
796
951
|
const targetUrl = resolveCdnWarmupTargetUrl(root, stagedProbe.deployedUrl ?? probeUpload.previewUrl, options);
|
|
797
|
-
const wranglerConfig = parseWranglerConfig(root,
|
|
798
|
-
const headers = buildVersionOverrideHeaders(options.name ?? probeUpload.workerName ?? resolveWorkerNameForVersionOverride(wranglerConfig,
|
|
952
|
+
const wranglerConfig = options.deploymentTool === "cf" ? null : parseWranglerConfig(root, wranglerOptions.config);
|
|
953
|
+
const headers = buildVersionOverrideHeaders(options.name ?? probeUpload.workerName ?? resolveWorkerNameForVersionOverride(wranglerConfig, wranglerOptions), probeUpload.versionId);
|
|
799
954
|
if (!targetUrl || !headers) throw new Error("Two-stage CDN warming needs a production URL and Worker name for version-overridden cacheability probes.");
|
|
800
955
|
console.log(" CDN warmup: discovering paths from the staged probe Worker...");
|
|
801
956
|
const discovered = await options.discoverWarmPlan({
|
|
@@ -861,6 +1016,7 @@ async function deployWithCacheabilityProbe(root, options) {
|
|
|
861
1016
|
concurrency: options.warmCdnConcurrency,
|
|
862
1017
|
expectedResponseBuildId: plan.buildIdentity,
|
|
863
1018
|
fallbackRoutePatterns: plan.fallbackRoutePatterns,
|
|
1019
|
+
loadingBoundaryRoutePatterns: plan.loadingBoundaryRoutePatterns,
|
|
864
1020
|
phaseTimeoutMs: options.warmCdnProbeTimeout ?? 12e4,
|
|
865
1021
|
retries: options.warmCdnProbeRetries ?? options.warmCdnRetries ?? 2,
|
|
866
1022
|
retryDelayMs: DEFAULT_CACHEABILITY_PROBE_RETRY_DELAY_MS,
|
|
@@ -885,19 +1041,17 @@ async function deployWithCacheabilityProbe(root, options) {
|
|
|
885
1041
|
routeHandlerPaths: probe.cacheableTargets.filter((target) => target.kind === "app-route").map((target) => target.sourcePathname),
|
|
886
1042
|
rscPaths: probe.cacheableTargets.filter((target) => target.kind === "rsc-full").map((target) => target.sourcePathname)
|
|
887
1043
|
};
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
preview: options.preview,
|
|
895
|
-
verbose: options.verbose
|
|
1044
|
+
const selectedFinalPlan = options.selectWarmPlan?.(finalPlan) ?? finalPlan;
|
|
1045
|
+
assertDeploymentStateUnchanged(root, wranglerOptions, stagedProbeDeployment, "Two-stage CDN warming stopped because Worker deployment traffic or deployment identity changed while cacheability was being probed. No final version was promoted.");
|
|
1046
|
+
const finalConfig = writeCacheabilityManifestArtifact(root, options.config, probe.manifest, options.deploymentTool);
|
|
1047
|
+
const finalUpload = runVersionUpload(root, {
|
|
1048
|
+
...options,
|
|
1049
|
+
config: options.deploymentTool === "cf" ? options.config : finalConfig
|
|
896
1050
|
});
|
|
897
1051
|
prepared = {
|
|
898
1052
|
optionalWarmTargetKeys: new Set(probe.speculativeTargets.map(cdnWarmTargetKey)),
|
|
899
1053
|
prerenderSecret,
|
|
900
|
-
plan:
|
|
1054
|
+
plan: selectedFinalPlan,
|
|
901
1055
|
upload: finalUpload
|
|
902
1056
|
};
|
|
903
1057
|
} catch (error) {
|
|
@@ -934,6 +1088,15 @@ function getZeroPercentStagingTraffic(deployment, versionId) {
|
|
|
934
1088
|
function getWranglerTargetEnv(options) {
|
|
935
1089
|
return options.env || (options.preview ? "preview" : void 0);
|
|
936
1090
|
}
|
|
1091
|
+
function resolveDeploymentControlPlaneOptions(options, upload) {
|
|
1092
|
+
if (options.deploymentTool !== "cf") return options;
|
|
1093
|
+
const name = upload.workerName ?? options.name;
|
|
1094
|
+
if (!name) throw new Error("Could not detect the uploaded Worker name needed for staged CDN warming.");
|
|
1095
|
+
return {
|
|
1096
|
+
...options,
|
|
1097
|
+
name
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
937
1100
|
function resolveWorkerNameForVersionOverride(config, options) {
|
|
938
1101
|
if (options.name) return options.name;
|
|
939
1102
|
const env = getWranglerTargetEnv(options);
|
|
@@ -952,32 +1115,35 @@ function buildVersionOverrideHeaders(workerName, versionId) {
|
|
|
952
1115
|
};
|
|
953
1116
|
}
|
|
954
1117
|
function withStagedVersionCleanupNote(error) {
|
|
955
|
-
|
|
956
|
-
return new Error(`${message} ${getStagedVersionCleanupNote()}`, { cause: error });
|
|
1118
|
+
return new StagedWarmupError(`${error instanceof Error ? error.message : String(error)} ${getStagedVersionCleanupNote()}`, { cause: error });
|
|
957
1119
|
}
|
|
958
1120
|
function withStagedProbeVersionCleanupNote(error) {
|
|
959
|
-
|
|
960
|
-
return new Error(`${message} The probe version may remain staged at 0% with the previous version still serving 100% traffic; production Worker triggers/routes were not changed.`, { cause: error });
|
|
1121
|
+
return new StagedWarmupError(`${error instanceof Error ? error.message : String(error)} The probe version may remain staged at 0% with the previous version still serving 100% traffic; production Worker triggers/routes were not changed.`, { cause: error });
|
|
961
1122
|
}
|
|
962
1123
|
function getStagedVersionCleanupNote() {
|
|
963
|
-
return "The uploaded version may remain staged at 0% with the previous version still serving 100% traffic; Worker triggers/routes may also have changed because trigger deployment runs before warming. Rerun deploy to promote it or
|
|
1124
|
+
return "The uploaded version may remain staged at 0% with the previous version still serving 100% traffic; Worker triggers/routes may also have changed because trigger deployment runs before warming. Rerun deploy to promote it or create a deployment with the desired version split.";
|
|
964
1125
|
}
|
|
965
1126
|
function withPromotedVersionTriggerNote(error) {
|
|
966
1127
|
const message = error instanceof Error ? error.message : String(error);
|
|
967
|
-
return new Error(`${message} The uploaded version may already be promoted to 100%, but Worker triggers/routes may not be updated; rerun deploy or
|
|
1128
|
+
return new Error(`${message} The uploaded version may already be promoted to 100%, but Worker triggers/routes may not be updated; rerun deploy or apply the Worker triggers after fixing the trigger error.`, { cause: error });
|
|
968
1129
|
}
|
|
969
1130
|
function withPromotedVersionWarmupNote(error) {
|
|
970
1131
|
const message = error instanceof Error ? error.message : String(error);
|
|
971
|
-
return new Error(`${message} The uploaded version is already promoted to 100% and its Worker triggers/routes were updated; rerun deploy to retry cache warming or
|
|
1132
|
+
return new Error(`${message} The uploaded version is already promoted to 100% and its Worker triggers/routes were updated; rerun deploy to retry cache warming or create a deployment for the previous version.`, { cause: error });
|
|
972
1133
|
}
|
|
973
1134
|
async function deploy(options) {
|
|
974
|
-
if (options.warmCdnTarget !== void 0 && !options.warmCdnCache) throw new Error("--warm-
|
|
1135
|
+
if (options.warmCdnTarget !== void 0 && !options.warmCdnCache && !options.experimentalTPR) throw new Error("--warm-cache-target requires --warm-cache or --traffic-aware-warm-cache.");
|
|
975
1136
|
const warmCdnTarget = options.warmCdnTarget === void 0 ? void 0 : validateCdnWarmTarget(options.warmCdnTarget);
|
|
976
|
-
const deployEnv =
|
|
1137
|
+
const deployEnv = options.env || (options.preview ? "preview" : void 0);
|
|
1138
|
+
if (deployEnv) validateWranglerEnvName(deployEnv);
|
|
977
1139
|
const root = path.resolve(options.root);
|
|
1140
|
+
const deploymentTool = resolveDeploymentTool(root);
|
|
1141
|
+
if (deploymentTool === "cf" && options.name) throw new Error("--name is not supported for cloudflare.config.ts projects. Set `name` in cloudflare.config.ts instead.");
|
|
1142
|
+
const viteMode = resolveViteBuildMode(deploymentTool, deployEnv);
|
|
1143
|
+
const wranglerFallbackEnv = deploymentTool === "cf" ? void 0 : deployEnv;
|
|
978
1144
|
loadDotenv({
|
|
979
1145
|
root,
|
|
980
|
-
mode:
|
|
1146
|
+
mode: viteMode
|
|
981
1147
|
});
|
|
982
1148
|
console.log("\n vinext-cloudflare deploy\n");
|
|
983
1149
|
const info = detectProject(root);
|
|
@@ -995,20 +1161,20 @@ async function deploy(options) {
|
|
|
995
1161
|
if (missingScaffolding.length > 0) throw new Error(`Missing Cloudflare deployment setup: ${missingScaffolding.join(", ")}. Run \`vinext init --platform=cloudflare\` first.`);
|
|
996
1162
|
const missingDeps = getMissingDeps(info);
|
|
997
1163
|
if (missingDeps.length > 0) throw new Error(`Missing deployment dependencies: ${missingDeps.map((dependency) => dependency.name).join(", ")}. Run \`vinext init --platform=cloudflare\` first.`);
|
|
1164
|
+
if (deploymentTool === "cf" && !isCfCliInstalled(root)) throw new Error("Missing deployment dependencies: cf. Run `vinext init --platform=cloudflare` first.");
|
|
998
1165
|
if (info.hasViteConfig && !viteConfigHasCloudflarePlugin(root)) throw new Error(formatMissingCloudflarePluginError({ isAppRouter: info.isAppRouter }));
|
|
999
|
-
if (info.hasISR && !viteConfigHasCacheAdapter(root) && !workerEntryHasCacheHandler(root)) throw new Error(formatMissingCacheAdapterError({}));
|
|
1166
|
+
if (info.hasISR && !viteConfigHasCacheAdapter(root) && !workerEntryHasCacheHandler(root)) throw new Error(formatMissingCacheAdapterError({ typedConfig: deploymentTool === "cf" }));
|
|
1000
1167
|
if (!viteConfigHasImageAdapter(root)) {
|
|
1001
1168
|
console.log();
|
|
1002
|
-
console.log(formatImageOptimizationHint());
|
|
1169
|
+
console.log(formatImageOptimizationHint(deploymentTool === "cf"));
|
|
1003
1170
|
}
|
|
1004
1171
|
if (options.dryRun) {
|
|
1005
1172
|
console.log("\n Dry run complete. No build or deploy performed.\n");
|
|
1006
1173
|
return;
|
|
1007
1174
|
}
|
|
1008
|
-
const
|
|
1009
|
-
const viteConfigMetadata = await withCloudflareEnv(buildEnv, () => loadDeployViteConfigMetadata(info.root));
|
|
1175
|
+
const viteConfigMetadata = await withCloudflareEnv(deployEnv, () => loadDeployViteConfigMetadata(info.root, viteMode));
|
|
1010
1176
|
const cdnAdapterConfig = resolveCdnAdapterConfig(viteConfigMetadata.cacheConfig);
|
|
1011
|
-
const nextConfig = await withCloudflareEnv(
|
|
1177
|
+
const nextConfig = await withCloudflareEnv(deployEnv, async () => {
|
|
1012
1178
|
const inlineNextConfig = viteConfigMetadata.nextConfig;
|
|
1013
1179
|
const rawNextConfig = inlineNextConfig ? await resolveNextConfigInput(inlineNextConfig, PHASE_PRODUCTION_BUILD) : await loadNextConfig(info.root, PHASE_PRODUCTION_BUILD);
|
|
1014
1180
|
return resolveNextConfig(rawNextConfig, info.root);
|
|
@@ -1019,35 +1185,82 @@ async function deploy(options) {
|
|
|
1019
1185
|
vinextPrerenderConfig,
|
|
1020
1186
|
nextOutput: nextConfig.output
|
|
1021
1187
|
});
|
|
1188
|
+
const shouldPrerenderLocally = Boolean(prerenderDecision && (nextConfig.output === "export" || hasCacheAdapterPrerenderOutput(viteConfigMetadata.cacheConfig)));
|
|
1022
1189
|
const hasStrictResponseVary = hasVerbatimResponseVary(viteConfigMetadata.cacheConfig);
|
|
1023
|
-
const
|
|
1190
|
+
const warmupStatusSource = cacheWarmupStatusSource(viteConfigMetadata.cacheConfig);
|
|
1191
|
+
const hasStagedRequestRouting = hasUncachedRequestRouting(viteConfigMetadata.cacheConfig) || warmupStatusSource === "data-cache";
|
|
1024
1192
|
const hasBuildIdentityHeader = hasBuildIdentityResponseHeader(viteConfigMetadata.cacheConfig);
|
|
1025
1193
|
const hasCanonicalRscWarmup = supportsCanonicalRscWarmup(viteConfigMetadata.cacheConfig);
|
|
1026
|
-
const hasVinextCacheWarmupStatus = usesVinextCacheWarmupStatus(viteConfigMetadata.cacheConfig);
|
|
1027
1194
|
const needsCacheabilityProbeManifest = projectRequiresRouteCacheabilityProbeManifest(info, viteConfigMetadata.cacheConfig);
|
|
1028
|
-
const shouldEmitPrerenderPathManifest = !options.skipBuild &&
|
|
1029
|
-
if (!
|
|
1195
|
+
const shouldEmitPrerenderPathManifest = !options.skipBuild && shouldPrerenderLocally;
|
|
1196
|
+
if (prerenderDecision && !shouldPrerenderLocally) {
|
|
1197
|
+
const trigger = prerenderDecision.reason === "flag" ? "--prerender-all" : "vinext prerender config";
|
|
1198
|
+
const replacement = options.warmCdnCache ? "Routes will be rendered and warmed through the staged Worker instead." : "Use --warm-cache to render and warm routes through the deployed Worker instead.";
|
|
1199
|
+
console.warn(`\n Warning: ${trigger} is ignored by Cloudflare deploy. ${replacement}`);
|
|
1200
|
+
}
|
|
1201
|
+
if (!options.skipBuild) await runBuild(info, deployEnv, viteMode);
|
|
1030
1202
|
else console.log("\n Skipping build (--skip-build)");
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1203
|
+
const prerenderOutputDirs = resolvePrerenderOutputDirs(info.root, deploymentTool, viteConfigMetadata.routeRootConfig);
|
|
1204
|
+
const canWarmTpr = options.experimentalTPR && !shouldPrerenderLocally && hasBuildIdentityHeader;
|
|
1205
|
+
if (options.experimentalTPR && shouldPrerenderLocally) console.log(" TPR: Skipping route selection (all-route prerendering configured)");
|
|
1206
|
+
else if (options.experimentalTPR && !hasBuildIdentityHeader) console.log(workerEntryHasCacheHandler(root) ? " TPR: Skipping pre-warm (legacy imperative cache handlers must migrate to declarative vinext({ cache }) for standard warming)" : " TPR: Skipping pre-warm (configured cache does not expose build identity)");
|
|
1207
|
+
const tpr = canWarmTpr ? await resolveTPRRoutes({
|
|
1208
|
+
root,
|
|
1209
|
+
config: options.config,
|
|
1210
|
+
env: wranglerFallbackEnv,
|
|
1211
|
+
hostname: warmCdnTarget ? new URL(warmCdnTarget).hostname : void 0,
|
|
1212
|
+
typedConfig: deploymentTool === "cf",
|
|
1213
|
+
window: Math.max(1, options.tprWindow ?? 24)
|
|
1214
|
+
}) : null;
|
|
1215
|
+
if (tpr?.skipped) console.log(` TPR: Skipped (${tpr.skipped})`);
|
|
1216
|
+
const tprRoutes = tpr?.routes ?? [];
|
|
1217
|
+
const wranglerOptions = {
|
|
1218
|
+
env: deploymentTool === "cf" ? viteMode : deployEnv,
|
|
1219
|
+
name: deploymentTool === "cf" ? readBuildOutputWorkerName(root) : options.name,
|
|
1220
|
+
config: options.config,
|
|
1221
|
+
verbose: options.verbose,
|
|
1222
|
+
deploymentTool
|
|
1223
|
+
};
|
|
1224
|
+
let shouldWarmTpr = tprRoutes.length > 0;
|
|
1225
|
+
if (shouldWarmTpr && !options.warmCdnCache) {
|
|
1034
1226
|
try {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1227
|
+
shouldWarmTpr = getZeroPercentStagingTraffic(runDeploymentStatus(root, wranglerOptions), "tpr-preflight") !== null;
|
|
1228
|
+
} catch {
|
|
1229
|
+
shouldWarmTpr = false;
|
|
1230
|
+
}
|
|
1231
|
+
if (!shouldWarmTpr) console.log(" TPR: Skipping pre-warm (current deployment cannot be staged safely)");
|
|
1232
|
+
}
|
|
1233
|
+
const shouldWarmCdnCache = options.warmCdnCache || shouldWarmTpr;
|
|
1234
|
+
if (options.warmCdnCertify && !shouldWarmCdnCache) throw new Error("Cannot certify traffic-aware warming because pre-warming was skipped.");
|
|
1235
|
+
const shouldSelectTpr = shouldWarmTpr && !options.warmCdnCache;
|
|
1236
|
+
const candidatePathsOnly = shouldSelectTpr && !needsCacheabilityProbeManifest;
|
|
1237
|
+
if (shouldWarmCdnCache && cdnAdapterConfig) {
|
|
1238
|
+
if (deploymentTool === "cf") {
|
|
1239
|
+
const configPath = path.join(root, ".cloudflare/output/v0/workers/default/worker.config.json");
|
|
1240
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
1241
|
+
const binding = cdnAdapterConfig.versionMetadataBinding;
|
|
1242
|
+
if (config.env?.[binding]?.type !== "version-metadata") throw new Error(`[vinext] Cloudflare CDN warmup requires version metadata binding ${JSON.stringify(binding)} in the generated Build Output Worker config ${configPath}.`);
|
|
1243
|
+
} else {
|
|
1244
|
+
const wrangler = await loadProjectWranglerApi(info.root);
|
|
1245
|
+
const previousCwd = process.cwd();
|
|
1246
|
+
try {
|
|
1247
|
+
process.chdir(info.root);
|
|
1248
|
+
const config = wrangler.unstable_readConfig({
|
|
1249
|
+
config: options.config,
|
|
1250
|
+
env: wranglerFallbackEnv
|
|
1251
|
+
}, {
|
|
1252
|
+
hideWarnings: true,
|
|
1253
|
+
preserveOriginalMain: true,
|
|
1254
|
+
useRedirectIfAvailable: true
|
|
1255
|
+
});
|
|
1256
|
+
assertCdnVersionMetadataConfig({
|
|
1257
|
+
binding: cdnAdapterConfig.versionMetadataBinding,
|
|
1258
|
+
configuredBinding: config.version_metadata?.binding,
|
|
1259
|
+
configPath: config.configPath
|
|
1260
|
+
});
|
|
1261
|
+
} finally {
|
|
1262
|
+
process.chdir(previousCwd);
|
|
1263
|
+
}
|
|
1051
1264
|
}
|
|
1052
1265
|
}
|
|
1053
1266
|
if (shouldEmitPrerenderPathManifest) await emitPrerenderPathManifest({
|
|
@@ -1057,100 +1270,102 @@ async function deploy(options) {
|
|
|
1057
1270
|
requestRouting: hasStagedRequestRouting ? "uncached-stage" : void 0,
|
|
1058
1271
|
responseVary: hasStrictResponseVary ? "verbatim" : void 0,
|
|
1059
1272
|
isResponsePolicyHeader: (name) => isConfiguredCdnResponsePolicyHeader(viteConfigMetadata.cacheConfig, name),
|
|
1060
|
-
routeRootConfig:
|
|
1273
|
+
routeRootConfig: prerenderOutputDirs
|
|
1061
1274
|
});
|
|
1062
|
-
let
|
|
1063
|
-
if (prerenderDecision) {
|
|
1275
|
+
let prerenderResult = void 0;
|
|
1276
|
+
if (shouldPrerenderLocally && prerenderDecision) {
|
|
1064
1277
|
console.log(`\n ${formatVinextPrerenderLabel(prerenderDecision)}`);
|
|
1065
1278
|
if (nextConfig.enablePrerenderSourceMaps) {
|
|
1066
1279
|
process.setSourceMapsEnabled(true);
|
|
1067
1280
|
Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 50);
|
|
1068
1281
|
}
|
|
1069
|
-
await runPrerender({
|
|
1282
|
+
prerenderResult = await runPrerender({
|
|
1070
1283
|
root: info.root,
|
|
1071
|
-
concurrency: options.prerenderConcurrency,
|
|
1284
|
+
concurrency: options.prerenderConcurrency ?? viteConfigMetadata.prerenderConfig?.concurrency,
|
|
1072
1285
|
nextConfig,
|
|
1073
|
-
routeRootConfig:
|
|
1286
|
+
routeRootConfig: prerenderOutputDirs
|
|
1287
|
+
});
|
|
1288
|
+
if (nextConfig.output !== "export") await finalizeCacheAdapterPrerenderOutput(viteConfigMetadata.cacheConfig, info.root, { clientOutDir: prerenderOutputDirs?.clientOutDir });
|
|
1289
|
+
}
|
|
1290
|
+
if (!options.skipBuild) {
|
|
1291
|
+
await printBuildReport({
|
|
1292
|
+
root: info.root,
|
|
1293
|
+
pageExtensions: nextConfig.pageExtensions,
|
|
1294
|
+
prerenderResult: prerenderResult ?? void 0
|
|
1074
1295
|
});
|
|
1075
|
-
|
|
1296
|
+
console.log("\n Build complete.\n");
|
|
1076
1297
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1298
|
+
let url;
|
|
1299
|
+
if (shouldWarmCdnCache) try {
|
|
1300
|
+
url = await deployWithCdnWarmup(root, [], {
|
|
1301
|
+
...wranglerOptions,
|
|
1302
|
+
allowEmptyWarmPlan: tprRoutes.length > 0 && !options.warmCdnCache,
|
|
1303
|
+
cacheabilityProbe: needsCacheabilityProbeManifest,
|
|
1304
|
+
discoverWarmPlan: async ({ headers, targetUrl }) => {
|
|
1305
|
+
const discovery = await discoverPrerenderPathManifest({
|
|
1306
|
+
root: info.root,
|
|
1307
|
+
candidatePaths: tprRoutes.map(({ path }) => path),
|
|
1308
|
+
candidatePathsOnly,
|
|
1309
|
+
nextConfig,
|
|
1310
|
+
buildIdentity: hasBuildIdentityHeader ? "response-header" : void 0,
|
|
1311
|
+
includeCanonicalRsc: hasCanonicalRscWarmup,
|
|
1312
|
+
requestRouting: hasStagedRequestRouting ? "uncached-stage" : void 0,
|
|
1313
|
+
responseVary: hasStrictResponseVary ? "verbatim" : void 0,
|
|
1314
|
+
isResponsePolicyHeader: (name) => isConfiguredCdnResponsePolicyHeader(viteConfigMetadata.cacheConfig, name),
|
|
1315
|
+
routeRootConfig: viteConfigMetadata.routeRootConfig,
|
|
1316
|
+
pathDiscoveryTarget: {
|
|
1317
|
+
baseUrl: targetUrl,
|
|
1318
|
+
headers,
|
|
1319
|
+
phaseTimeoutMs: options.warmCdnDiscoveryTimeout ?? DEFAULT_REMOTE_PATH_DISCOVERY_PHASE_TIMEOUT_MS,
|
|
1320
|
+
retries: options.warmCdnDiscoveryRetries,
|
|
1321
|
+
retryDelayMs: DEFAULT_REMOTE_PATH_DISCOVERY_RETRY_DELAY_MS
|
|
1322
|
+
}
|
|
1323
|
+
});
|
|
1324
|
+
if (!discovery) return {
|
|
1325
|
+
loadingShellPaths: [],
|
|
1326
|
+
paths: [],
|
|
1327
|
+
rscPaths: []
|
|
1328
|
+
};
|
|
1329
|
+
return createPrerenderWarmPlan(root, discovery, {
|
|
1330
|
+
includeCanonicalRsc: hasCanonicalRscWarmup,
|
|
1331
|
+
includeFallbackShells: options.warmCdnIncludeFallbacks,
|
|
1332
|
+
strict: options.warmCdnCertify === true || !options.dangerouslyPromoteOnCdnWarmError
|
|
1333
|
+
});
|
|
1334
|
+
},
|
|
1335
|
+
selectWarmPlan: shouldSelectTpr ? (plan) => selectTPRWarmPlan(plan, tprRoutes, Math.max(1, Math.min(100, options.tprCoverage ?? 90)), Math.max(1, options.tprLimit ?? 1e3)) : void 0,
|
|
1336
|
+
statusSource: warmupStatusSource,
|
|
1337
|
+
warmCdnConcurrency: options.warmCdnConcurrency,
|
|
1338
|
+
warmCdnTarget: warmCdnTarget ?? tpr?.targetUrl,
|
|
1339
|
+
warmCdnTimeout: options.warmCdnTimeout,
|
|
1340
|
+
warmCdnRetries: options.warmCdnRetries,
|
|
1341
|
+
warmCdnDiscoveryTimeout: options.warmCdnDiscoveryTimeout,
|
|
1342
|
+
warmCdnDiscoveryRetries: options.warmCdnDiscoveryRetries,
|
|
1343
|
+
warmCdnProbeTimeout: options.warmCdnProbeTimeout,
|
|
1344
|
+
warmCdnProbeRetries: options.warmCdnProbeRetries,
|
|
1345
|
+
warmCdnCertify: options.warmCdnCertify,
|
|
1346
|
+
warmCdnReadinessTimeout: options.warmCdnReadinessTimeout,
|
|
1347
|
+
warmCdnReadinessRetries: options.warmCdnReadinessRetries,
|
|
1348
|
+
warmCdnReadinessProbes: options.warmCdnReadinessProbes,
|
|
1349
|
+
warmCdnReadinessProbeDelay: options.warmCdnReadinessProbeDelay,
|
|
1350
|
+
dangerouslyPromoteOnCdnWarmError: options.dangerouslyPromoteOnCdnWarmError,
|
|
1351
|
+
warmCdnPromote: options.warmCdnPromote,
|
|
1352
|
+
warmCdnPromotionDelay: options.warmCdnPromotionDelay
|
|
1353
|
+
});
|
|
1079
1354
|
} catch (error) {
|
|
1080
|
-
|
|
1355
|
+
if (options.warmCdnCache || options.warmCdnCertify || options.warmCdnPromote === false && error instanceof StagedWarmupError) throw error;
|
|
1356
|
+
console.log(` TPR: Skipping pre-warm (${formatUnknownError(error)}). Continuing with deploy.`);
|
|
1081
1357
|
}
|
|
1082
|
-
if (
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
limit: Math.max(1, options.tprLimit ?? 1e3),
|
|
1089
|
-
window: Math.max(1, options.tprWindow ?? 24)
|
|
1358
|
+
if (url === void 0) {
|
|
1359
|
+
if (deploymentTool === "cf" && options.warmCdnPromote === false) url = runCfVersionUpload(root, wranglerOptions).previewUrl ?? "(Preview URL not detected in cf output)";
|
|
1360
|
+
else if (deploymentTool === "cf") url = await runCfDeploy(root, wranglerOptions);
|
|
1361
|
+
else url = await runWranglerDeploy(root, {
|
|
1362
|
+
...wranglerOptions,
|
|
1363
|
+
promote: options.warmCdnPromote
|
|
1090
1364
|
});
|
|
1091
|
-
if (tprResult.skipped) console.log(` TPR: Skipped (${tprResult.skipped})`);
|
|
1092
1365
|
}
|
|
1093
|
-
const wranglerOptions = {
|
|
1094
|
-
env: deployEnv === "production" && !options.env ? void 0 : deployEnv,
|
|
1095
|
-
name: options.name,
|
|
1096
|
-
config: options.config,
|
|
1097
|
-
verbose: options.verbose
|
|
1098
|
-
};
|
|
1099
|
-
let url;
|
|
1100
|
-
if (options.warmCdnCache) url = await deployWithCdnWarmup(root, [], {
|
|
1101
|
-
...wranglerOptions,
|
|
1102
|
-
cacheabilityProbe: needsCacheabilityProbeManifest,
|
|
1103
|
-
discoverWarmPlan: async ({ headers, targetUrl }) => {
|
|
1104
|
-
const discovery = await discoverPrerenderPathManifest({
|
|
1105
|
-
root: info.root,
|
|
1106
|
-
nextConfig,
|
|
1107
|
-
buildIdentity: hasBuildIdentityHeader ? "response-header" : void 0,
|
|
1108
|
-
includeCanonicalRsc: hasCanonicalRscWarmup,
|
|
1109
|
-
requestRouting: hasStagedRequestRouting ? "uncached-stage" : void 0,
|
|
1110
|
-
responseVary: hasStrictResponseVary ? "verbatim" : void 0,
|
|
1111
|
-
isResponsePolicyHeader: (name) => isConfiguredCdnResponsePolicyHeader(viteConfigMetadata.cacheConfig, name),
|
|
1112
|
-
routeRootConfig: viteConfigMetadata.routeRootConfig,
|
|
1113
|
-
pathDiscoveryTarget: {
|
|
1114
|
-
baseUrl: targetUrl,
|
|
1115
|
-
headers,
|
|
1116
|
-
phaseTimeoutMs: options.warmCdnDiscoveryTimeout ?? DEFAULT_REMOTE_PATH_DISCOVERY_PHASE_TIMEOUT_MS,
|
|
1117
|
-
retries: options.warmCdnDiscoveryRetries,
|
|
1118
|
-
retryDelayMs: DEFAULT_REMOTE_PATH_DISCOVERY_RETRY_DELAY_MS
|
|
1119
|
-
}
|
|
1120
|
-
});
|
|
1121
|
-
if (!discovery) return {
|
|
1122
|
-
loadingShellPaths: [],
|
|
1123
|
-
paths: [],
|
|
1124
|
-
rscPaths: []
|
|
1125
|
-
};
|
|
1126
|
-
return createPrerenderWarmPlan(root, discovery, {
|
|
1127
|
-
includeCanonicalRsc: hasCanonicalRscWarmup,
|
|
1128
|
-
includeFallbackShells: options.warmCdnIncludeFallbacks,
|
|
1129
|
-
strict: options.warmCdnCertify === true || !options.dangerouslyPromoteOnCdnWarmError
|
|
1130
|
-
});
|
|
1131
|
-
},
|
|
1132
|
-
statusSource: hasVinextCacheWarmupStatus ? "vinext" : "cloudflare",
|
|
1133
|
-
warmCdnConcurrency: options.warmCdnConcurrency,
|
|
1134
|
-
warmCdnTarget,
|
|
1135
|
-
warmCdnTimeout: options.warmCdnTimeout,
|
|
1136
|
-
warmCdnRetries: options.warmCdnRetries,
|
|
1137
|
-
warmCdnDiscoveryTimeout: options.warmCdnDiscoveryTimeout,
|
|
1138
|
-
warmCdnDiscoveryRetries: options.warmCdnDiscoveryRetries,
|
|
1139
|
-
warmCdnProbeTimeout: options.warmCdnProbeTimeout,
|
|
1140
|
-
warmCdnProbeRetries: options.warmCdnProbeRetries,
|
|
1141
|
-
warmCdnCertify: options.warmCdnCertify,
|
|
1142
|
-
warmCdnReadinessTimeout: options.warmCdnReadinessTimeout,
|
|
1143
|
-
warmCdnReadinessRetries: options.warmCdnReadinessRetries,
|
|
1144
|
-
warmCdnReadinessProbes: options.warmCdnReadinessProbes,
|
|
1145
|
-
warmCdnReadinessProbeDelay: options.warmCdnReadinessProbeDelay,
|
|
1146
|
-
dangerouslyPromoteOnCdnWarmError: options.dangerouslyPromoteOnCdnWarmError,
|
|
1147
|
-
warmCdnPromote: options.warmCdnPromote,
|
|
1148
|
-
warmCdnPromotionDelay: options.warmCdnPromotionDelay
|
|
1149
|
-
});
|
|
1150
|
-
else url = await runWranglerDeploy(root, wranglerOptions);
|
|
1151
1366
|
console.log("\n ─────────────────────────────────────────");
|
|
1152
|
-
console.log(` Deployed to: ${url}`);
|
|
1367
|
+
console.log(` ${options.warmCdnPromote === false ? "Version URL" : "Deployed to"}: ${url}`);
|
|
1153
1368
|
console.log(" ─────────────────────────────────────────\n");
|
|
1154
1369
|
}
|
|
1155
1370
|
//#endregion
|
|
1156
|
-
export { DEFAULT_CDN_WARM_PROMOTION_DELAY_MS, buildNodeCliInvocation, buildVersionOverrideHeaders, buildWranglerDeployArgs, buildWranglerInvocation,
|
|
1371
|
+
export { DEFAULT_CDN_WARM_PROMOTION_DELAY_MS, buildCfDeployArgs, buildNodeCliInvocation, buildVersionOverrideHeaders, buildWranglerDeployArgs, buildWranglerInvocation, deploy, deployWithCdnWarmup, getZeroPercentStagingTraffic, hasCdnWarmRequests, isCfCliInstalled, parseDeployArgs, projectRequiresRouteCacheabilityProbeManifest, resolveCdnWarmupTargetUrl, resolveCfBin, resolveDeploymentControlPlaneOptions, resolveDeploymentTool, resolvePrerenderOutputDirs, resolveViteBuildMode, resolveWorkerNameForVersionOverride, resolveWranglerBin, runCfDeploy, runWranglerDeploy, selectTPRWarmPlan, validateWranglerEnvName, withCloudflareEnv };
|