@vinext/cloudflare 1.0.0-beta.1 → 1.0.0-beta.10
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 +94 -1
- package/dist/cache/cdn-adapter-config.d.ts +30 -0
- package/dist/cache/cdn-adapter-config.js +87 -0
- package/dist/cache/cdn-adapter.d.ts +47 -15
- package/dist/cache/cdn-adapter.js +49 -13
- package/dist/cache/cdn-adapter.runtime.d.ts +26 -4
- package/dist/cache/cdn-adapter.runtime.js +150 -37
- package/dist/cache/cdn-adapter.worker.d.ts +31 -0
- package/dist/cache/cdn-adapter.worker.js +373 -0
- package/dist/cache/cdn-build-id.d.ts +6 -0
- package/dist/cache/cdn-build-id.js +9 -0
- package/dist/cache/kv-data-adapter.d.ts +32 -8
- package/dist/cache/kv-data-adapter.js +5 -1
- package/dist/cache/kv-data-adapter.runtime.d.ts +45 -13
- package/dist/cache/kv-data-adapter.runtime.js +132 -52
- package/dist/cache/kv-key.d.ts +15 -0
- package/dist/cache/kv-key.js +43 -0
- package/dist/cache/response-store-adapter.d.ts +73 -0
- package/dist/cache/response-store-adapter.js +64 -0
- package/dist/cache/response-store-adapter.self-contained.worker.d.ts +18 -0
- package/dist/cache/response-store-adapter.self-contained.worker.js +12 -0
- package/dist/cache/response-store-adapter.service-binding.worker.d.ts +16 -0
- package/dist/cache/response-store-adapter.service-binding.worker.js +11 -0
- package/dist/cache/response-store-adapter.worker.d.ts +14 -0
- package/dist/cache/response-store-adapter.worker.js +278 -0
- package/dist/cache/response-store-cdn.runtime.d.ts +5 -0
- package/dist/cache/response-store-cdn.runtime.js +41 -0
- package/dist/cache/response-store-data.runtime.d.ts +34 -0
- package/dist/cache/response-store-data.runtime.js +300 -0
- package/dist/cacheability-artifact.d.ts +9 -0
- package/dist/cacheability-artifact.js +191 -0
- package/dist/cacheability-manifest-limits.d.ts +4 -0
- package/dist/cacheability-manifest-limits.js +7 -0
- package/dist/cacheability-probe.d.ts +49 -0
- package/dist/cacheability-probe.js +660 -0
- package/dist/cdn-warm.d.ts +110 -12
- package/dist/cdn-warm.js +880 -82
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +15 -1
- package/dist/deploy-config.d.ts +13 -11
- package/dist/deploy-config.js +21 -3
- package/dist/deploy-help.d.ts +3 -4
- package/dist/deploy-help.js +61 -18
- package/dist/deploy.d.ts +121 -41
- package/dist/deploy.js +762 -104
- package/dist/images/images-optimizer.d.ts +5 -5
- package/dist/images/images-optimizer.runtime.d.ts +1 -5
- package/dist/prerender-kv-populate.d.ts +3 -4
- package/dist/prerender-kv-populate.js +51 -18
- package/dist/tpr.d.ts +32 -70
- package/dist/tpr.js +45 -602
- package/dist/utils/cache-control-metadata.d.ts +3 -4
- package/dist/version-deploy.d.ts +19 -17
- package/dist/version-deploy.js +32 -13
- package/dist/version-headers.d.ts +2 -0
- package/dist/version-headers.js +2 -0
- package/dist/worker-deployment-url.d.ts +9 -0
- package/dist/worker-deployment-url.js +45 -0
- package/dist/workers-dev-url.d.ts +2 -3
- package/dist/wrangler-config.d.ts +19 -0
- package/dist/wrangler-config.js +294 -0
- package/dist/wrangler-version-metadata.d.ts +7 -0
- package/dist/wrangler-version-metadata.js +9 -0
- package/package.json +14 -11
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { cacheabilityManifestByteLimitError } from "./cacheability-manifest-limits.js";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
import { CACHEABILITY_MANIFEST_MODULE } from "vinext/internal/server/cacheability-manifest";
|
|
6
|
+
//#region src/cacheability-artifact.ts
|
|
7
|
+
function tokenizeStaticImports(source) {
|
|
8
|
+
const tokens = [];
|
|
9
|
+
let index = 0;
|
|
10
|
+
const canStartRegularExpression = () => {
|
|
11
|
+
const previous = tokens.at(-1);
|
|
12
|
+
if (!previous) return true;
|
|
13
|
+
if (previous.kind === "punctuator" && "({[=,:;!?&|+-*%^~<>".includes(previous.value)) return true;
|
|
14
|
+
return previous.kind === "identifier" && /^(?:await|case|delete|do|else|in|instanceof|of|return|throw|typeof|void|yield)$/.test(previous.value);
|
|
15
|
+
};
|
|
16
|
+
while (index < source.length) {
|
|
17
|
+
const character = source[index];
|
|
18
|
+
if (/\s/.test(character)) {
|
|
19
|
+
index++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (character === "/" && source[index + 1] === "/") {
|
|
23
|
+
index = source.indexOf("\n", index + 2);
|
|
24
|
+
if (index === -1) break;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (character === "/" && source[index + 1] === "*") {
|
|
28
|
+
const end = source.indexOf("*/", index + 2);
|
|
29
|
+
index = end === -1 ? source.length : end + 2;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (character === "/" && canStartRegularExpression()) {
|
|
33
|
+
let inCharacterClass = false;
|
|
34
|
+
index++;
|
|
35
|
+
while (index < source.length) {
|
|
36
|
+
if (source[index] === "\\") {
|
|
37
|
+
index += 2;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (source[index] === "[") inCharacterClass = true;
|
|
41
|
+
if (source[index] === "]") inCharacterClass = false;
|
|
42
|
+
if (source[index++] === "/" && !inCharacterClass) break;
|
|
43
|
+
}
|
|
44
|
+
while (index < source.length && /[A-Za-z]/.test(source[index])) index++;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (character === "`") {
|
|
48
|
+
index++;
|
|
49
|
+
while (index < source.length) if (source[index] === "\\") index += 2;
|
|
50
|
+
else if (source[index++] === "`") break;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (character === "\"" || character === "'") {
|
|
54
|
+
const quote = character;
|
|
55
|
+
const start = ++index;
|
|
56
|
+
while (index < source.length && source[index] !== quote) index += source[index] === "\\" ? 2 : 1;
|
|
57
|
+
tokens.push({
|
|
58
|
+
kind: "string",
|
|
59
|
+
value: source.slice(start, index)
|
|
60
|
+
});
|
|
61
|
+
index++;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (/[A-Za-z_$]/.test(character)) {
|
|
65
|
+
const start = index++;
|
|
66
|
+
while (index < source.length && /[\w$]/.test(source[index])) index++;
|
|
67
|
+
tokens.push({
|
|
68
|
+
kind: "identifier",
|
|
69
|
+
value: source.slice(start, index)
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
tokens.push({
|
|
74
|
+
kind: "punctuator",
|
|
75
|
+
value: character
|
|
76
|
+
});
|
|
77
|
+
index++;
|
|
78
|
+
}
|
|
79
|
+
return tokens;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Check only the generated entry module's static dependency declarations. This
|
|
83
|
+
* deliberately avoids an AST parse or module-graph walk on the deploy path,
|
|
84
|
+
* while rejecting comments, strings, templates, and dynamic imports that only
|
|
85
|
+
* happen to mention the manifest filename.
|
|
86
|
+
*/
|
|
87
|
+
function hasStaticModuleSpecifier(source, expected) {
|
|
88
|
+
const tokens = tokenizeStaticImports(source);
|
|
89
|
+
let braceDepth = 0;
|
|
90
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
91
|
+
const token = tokens[index];
|
|
92
|
+
if (token.value === "{") {
|
|
93
|
+
braceDepth++;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (token.value === "}") {
|
|
97
|
+
braceDepth = Math.max(0, braceDepth - 1);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (braceDepth !== 0 || token.kind !== "identifier") continue;
|
|
101
|
+
if (token.value === "import") {
|
|
102
|
+
const next = tokens[index + 1];
|
|
103
|
+
if (next?.kind === "string" && next.value === expected) return true;
|
|
104
|
+
if (next?.value === "(" || next?.value === ".") continue;
|
|
105
|
+
} else if (token.value !== "export") continue;
|
|
106
|
+
for (let cursor = index + 1; cursor < tokens.length; cursor++) {
|
|
107
|
+
const candidate = tokens[cursor];
|
|
108
|
+
if (candidate.value === ";") break;
|
|
109
|
+
if (candidate.kind === "identifier" && candidate.value === "from") {
|
|
110
|
+
const specifier = tokens[cursor + 1];
|
|
111
|
+
if (specifier?.kind === "string" && specifier.value === expected) return true;
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
function resolveGeneratedServerConfig(root, configuredPath) {
|
|
119
|
+
const distDirectory = path.join(root, "dist");
|
|
120
|
+
const configPath = path.resolve(root, configuredPath ?? "dist/server/wrangler.json");
|
|
121
|
+
const relativeConfigPath = path.relative(distDirectory, configPath);
|
|
122
|
+
if (relativeConfigPath.startsWith("..") || path.isAbsolute(relativeConfigPath)) throw new Error("Two-stage CDN warming requires a generated Wrangler config under dist/. Pass --config dist/server/wrangler.json (or another generated dist config).");
|
|
123
|
+
if (!fs.existsSync(configPath) || !fs.lstatSync(configPath).isFile()) throw new Error(`Two-stage CDN warming requires the generated Wrangler config at ${path.relative(root, configPath)}. Rebuild the app before deploying.`);
|
|
124
|
+
return configPath;
|
|
125
|
+
}
|
|
126
|
+
function assertManifestModuleReachable(configPath) {
|
|
127
|
+
const serverDirectory = path.dirname(configPath);
|
|
128
|
+
let config;
|
|
129
|
+
try {
|
|
130
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
131
|
+
} catch (cause) {
|
|
132
|
+
throw new Error("Two-stage CDN warming could not parse the generated Wrangler config.", { cause });
|
|
133
|
+
}
|
|
134
|
+
const main = config && typeof config === "object" && !Array.isArray(config) ? config.main : void 0;
|
|
135
|
+
if (typeof main !== "string" || main.length === 0) throw new Error("Two-stage CDN warming requires a generated Wrangler main module.");
|
|
136
|
+
const mainPath = path.resolve(serverDirectory, main);
|
|
137
|
+
if (!fs.existsSync(mainPath) || !fs.lstatSync(mainPath).isFile()) throw new Error("Two-stage CDN warming could not find the generated Wrangler main module.");
|
|
138
|
+
const viteManifestPath = path.join(serverDirectory, ".vite", "manifest.json");
|
|
139
|
+
let viteManifest;
|
|
140
|
+
try {
|
|
141
|
+
viteManifest = JSON.parse(fs.readFileSync(viteManifestPath, "utf8"));
|
|
142
|
+
} catch (cause) {
|
|
143
|
+
throw new Error("Two-stage CDN warming could not read the generated Vite manifest.", { cause });
|
|
144
|
+
}
|
|
145
|
+
const normalizedMain = main.replace(/^\.\//, "");
|
|
146
|
+
const entryKey = Object.entries(viteManifest).find(([, entry]) => entry?.file === normalizedMain)?.[0];
|
|
147
|
+
const queue = entryKey ? [entryKey] : [];
|
|
148
|
+
const visited = /* @__PURE__ */ new Set();
|
|
149
|
+
let reachable = false;
|
|
150
|
+
while (queue.length > 0 && !reachable) {
|
|
151
|
+
const key = queue.shift();
|
|
152
|
+
if (visited.has(key)) continue;
|
|
153
|
+
visited.add(key);
|
|
154
|
+
const entry = viteManifest[key];
|
|
155
|
+
if (!entry || typeof entry.file !== "string") continue;
|
|
156
|
+
const modulePath = path.resolve(serverDirectory, entry.file);
|
|
157
|
+
if (fs.existsSync(modulePath) && fs.lstatSync(modulePath).isFile()) {
|
|
158
|
+
const relativeManifest = path.relative(path.dirname(modulePath), path.join(serverDirectory, CACHEABILITY_MANIFEST_MODULE)).split(path.sep).join("/");
|
|
159
|
+
const specifier = relativeManifest.startsWith(".") ? relativeManifest : `./${relativeManifest}`;
|
|
160
|
+
reachable = hasStaticModuleSpecifier(fs.readFileSync(modulePath, "utf8"), specifier);
|
|
161
|
+
}
|
|
162
|
+
for (const references of [entry.imports, entry.dynamicImports]) if (Array.isArray(references)) queue.push(...references.filter((value) => typeof value === "string"));
|
|
163
|
+
}
|
|
164
|
+
if (!reachable) throw new Error(`Two-stage CDN warming requires the generated Worker graph to statically import ${CACHEABILITY_MANIFEST_MODULE}.`);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Write the version-specific manifest into the built Worker artifact.
|
|
168
|
+
* The application build already imports this stable module asset, so the
|
|
169
|
+
* completed dist directory remains the exact input to the final upload.
|
|
170
|
+
*/
|
|
171
|
+
function writeCacheabilityManifestArtifact(root, configuredPath, manifest) {
|
|
172
|
+
const configPath = resolveGeneratedServerConfig(root, configuredPath);
|
|
173
|
+
assertManifestModuleReachable(configPath);
|
|
174
|
+
const serverDirectory = path.dirname(configPath);
|
|
175
|
+
const manifestPath = path.join(serverDirectory, CACHEABILITY_MANIFEST_MODULE);
|
|
176
|
+
if (!fs.existsSync(manifestPath) || !fs.lstatSync(manifestPath).isFile()) throw new Error(`Two-stage CDN warming requires ${CACHEABILITY_MANIFEST_MODULE} in the generated Worker artifact. Rebuild the app before deploying.`);
|
|
177
|
+
const serializedManifest = JSON.stringify(manifest);
|
|
178
|
+
const manifestBytes = Buffer.byteLength(serializedManifest);
|
|
179
|
+
if (manifestBytes > 2097152) throw cacheabilityManifestByteLimitError(manifestBytes);
|
|
180
|
+
const manifestSource = `export default ${JSON.stringify(serializedManifest)};\n`;
|
|
181
|
+
const pendingManifestPath = `${manifestPath}.${process.pid}.tmp`;
|
|
182
|
+
try {
|
|
183
|
+
fs.writeFileSync(pendingManifestPath, manifestSource, "utf8");
|
|
184
|
+
fs.renameSync(pendingManifestPath, manifestPath);
|
|
185
|
+
} finally {
|
|
186
|
+
if (fs.existsSync(pendingManifestPath)) fs.unlinkSync(pendingManifestPath);
|
|
187
|
+
}
|
|
188
|
+
return path.relative(root, configPath);
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { writeCacheabilityManifestArtifact };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/cacheability-manifest-limits.ts
|
|
2
|
+
const MAX_CACHEABILITY_MANIFEST_BYTES = 2097152;
|
|
3
|
+
function cacheabilityManifestByteLimitError(manifestBytes, limit = MAX_CACHEABILITY_MANIFEST_BYTES) {
|
|
4
|
+
return /* @__PURE__ */ new Error(`Two-stage CDN warming produced a ${manifestBytes}-byte route-pattern cacheability manifest; the limit is ${limit} bytes. Reduce the number or length of route patterns, or split the deployment before retrying.`);
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { MAX_CACHEABILITY_MANIFEST_BYTES, cacheabilityManifestByteLimitError };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { CdnWarmTarget } from "./cdn-warm.js";
|
|
2
|
+
import { CacheabilityManifest } from "vinext/internal/server/cacheability-manifest";
|
|
3
|
+
import { PrerenderRoutePattern } from "vinext/internal/build/prerender-paths";
|
|
4
|
+
//#region src/cacheability-probe.d.ts
|
|
5
|
+
export declare const DEFAULT_CACHEABILITY_PROBE_PHASE_TIMEOUT_MS = 120000;
|
|
6
|
+
export declare const DEFAULT_CACHEABILITY_PROBE_RETRIES = 2;
|
|
7
|
+
export declare const DEFAULT_CACHEABILITY_PROBE_RETRY_DELAY_MS = 1000;
|
|
8
|
+
export type CacheabilityProbeProgress = {
|
|
9
|
+
completed: number;
|
|
10
|
+
dynamic: number;
|
|
11
|
+
failed: number;
|
|
12
|
+
probed: number;
|
|
13
|
+
skipped: number;
|
|
14
|
+
static: number;
|
|
15
|
+
total: number;
|
|
16
|
+
};
|
|
17
|
+
export type CacheabilityProbeResult = {
|
|
18
|
+
cacheableTargets: CdnWarmTarget[];
|
|
19
|
+
classified: number;
|
|
20
|
+
dynamic: number;
|
|
21
|
+
failures: string[];
|
|
22
|
+
manifest: CacheabilityManifest;
|
|
23
|
+
probed: number;
|
|
24
|
+
skipped: number;
|
|
25
|
+
/** Paired representations admitted only if their own final warm render remains cacheable. */
|
|
26
|
+
speculativeTargets: CdnWarmTarget[];
|
|
27
|
+
};
|
|
28
|
+
export declare function readPrerenderSecret(root: string): string;
|
|
29
|
+
export declare function probeStagedWorkerCacheability(options: {
|
|
30
|
+
buildId: string;
|
|
31
|
+
concurrency?: number;
|
|
32
|
+
expectedResponseBuildId?: string;
|
|
33
|
+
fallbackRoutePatterns?: readonly PrerenderRoutePattern[];
|
|
34
|
+
fetchImpl?: typeof fetch;
|
|
35
|
+
headers?: HeadersInit;
|
|
36
|
+
retries?: number;
|
|
37
|
+
retryDelayMs?: number;
|
|
38
|
+
root: string;
|
|
39
|
+
targets: readonly CdnWarmTarget[];
|
|
40
|
+
targetUrl: string;
|
|
41
|
+
timeoutMs?: number;
|
|
42
|
+
phaseTimeoutMs?: number;
|
|
43
|
+
onProgress?: (progress: CacheabilityProbeProgress) => void;
|
|
44
|
+
/** @internal Apply stricter artifact bounds for focused coordinator tests. */
|
|
45
|
+
manifestLimits?: {
|
|
46
|
+
maxBytes?: number;
|
|
47
|
+
};
|
|
48
|
+
}): Promise<CacheabilityProbeResult>;
|
|
49
|
+
//#endregion
|