@vinext/cloudflare 1.2.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/deploy.js CHANGED
@@ -99,6 +99,7 @@ const deployArgOptions = {
99
99
  env: { type: "string" },
100
100
  name: { type: "string" },
101
101
  config: { type: "string" },
102
+ "vite-config": { type: "string" },
102
103
  "skip-build": {
103
104
  type: "boolean",
104
105
  default: false
@@ -249,6 +250,7 @@ function parseDeployArgs(args) {
249
250
  env: values.env?.trim() || void 0,
250
251
  name: values.name?.trim() || void 0,
251
252
  config: values.config?.trim() || void 0,
253
+ viteConfig: values["vite-config"]?.trim() || void 0,
252
254
  skipBuild: values["skip-build"],
253
255
  dryRun: values["dry-run"],
254
256
  verbose: values.verbose,
@@ -339,11 +341,11 @@ async function loadProjectWranglerApi(root) {
339
341
  function resolveViteBuildMode(deploymentTool, env) {
340
342
  return deploymentTool === "cf" ? env ?? "production" : "production";
341
343
  }
342
- async function loadDeployViteConfigMetadata(root, mode) {
344
+ async function loadDeployViteConfigMetadata(root, mode, configFile) {
343
345
  const plugins = (await (await loadProjectViteApi(root)).loadConfigFromFile({
344
346
  command: "build",
345
347
  mode
346
- }, void 0, root))?.config.plugins;
348
+ }, configFile, root))?.config.plugins;
347
349
  return {
348
350
  cacheConfig: await findVinextCacheConfigInPlugins(plugins),
349
351
  nextConfig: await findVinextNextConfigInPlugins(plugins),
@@ -351,7 +353,7 @@ async function loadDeployViteConfigMetadata(root, mode) {
351
353
  routeRootConfig: await findVinextRouteRootConfigInPlugins(plugins)
352
354
  };
353
355
  }
354
- async function runBuild(info, env, mode) {
356
+ async function runBuild(info, env, mode, configFile) {
355
357
  console.log("\n Building for Cloudflare Workers...\n");
356
358
  const { createBuilder } = await loadProjectViteApi(info.root);
357
359
  let completed = false;
@@ -362,6 +364,7 @@ async function runBuild(info, env, mode) {
362
364
  await (await createBuilder({
363
365
  root: info.root,
364
366
  mode,
367
+ configFile,
365
368
  [VINEXT_BUILD_LIFECYCLE_CONFIG]: invocation
366
369
  })).buildApp();
367
370
  });
@@ -1190,6 +1193,7 @@ async function deploy(options) {
1190
1193
  if (isPreview && deploymentTool !== "cf") throw new Error("Worker Previews require a cloudflare.config.ts project and the cf CLI.");
1191
1194
  if (deploymentTool === "cf" && options.name) throw new Error("--name is not supported for cloudflare.config.ts projects. Set `name` in cloudflare.config.ts instead.");
1192
1195
  const viteMode = resolveViteBuildMode(deploymentTool, deployEnv);
1196
+ const viteConfigFile = options.viteConfig ? path.resolve(root, options.viteConfig) : void 0;
1193
1197
  const wranglerFallbackEnv = deploymentTool === "cf" ? void 0 : deployEnv;
1194
1198
  if (!process.env.NODE_ENV) Reflect.set(process.env, "NODE_ENV", "production");
1195
1199
  loadDotenv({
@@ -1210,16 +1214,25 @@ async function deploy(options) {
1210
1214
  console.log(` Project: ${info.projectName}`);
1211
1215
  console.log(` Router: ${info.isAppRouter ? "App Router" : "Pages Router"}`);
1212
1216
  console.log(` ISR: ${info.hasISR ? "detected" : "none"}`);
1213
- const missingScaffolding = [!info.hasViteConfig && "Vite config", !info.hasWranglerConfig && "Wrangler config"].filter((value) => Boolean(value));
1217
+ if (viteConfigFile && !fs.existsSync(viteConfigFile)) throw new Error(`Vite config file not found: ${viteConfigFile}`);
1218
+ const hasViteConfig = Boolean(viteConfigFile) || info.hasViteConfig;
1219
+ const missingScaffolding = [!hasViteConfig && "Vite config", !info.hasWranglerConfig && "Wrangler config"].filter((value) => Boolean(value));
1214
1220
  if (missingScaffolding.length > 0) throw new Error(`Missing Cloudflare deployment setup: ${missingScaffolding.join(", ")}. Run \`vinext init --platform=cloudflare\` first.`);
1215
1221
  const missingDeps = getMissingDeps(info);
1216
1222
  if (missingDeps.length > 0) throw new Error(`Missing deployment dependencies: ${missingDeps.map((dependency) => dependency.name).join(", ")}. Run \`vinext init --platform=cloudflare\` first.`);
1217
1223
  if (deploymentTool === "cf" && !isCfCliInstalled(root)) throw new Error("Missing deployment dependencies: cf. Run `vinext init --platform=cloudflare` first.");
1218
- if (info.hasViteConfig && !viteConfigHasCloudflarePlugin(root)) throw new Error(formatMissingCloudflarePluginError({ isAppRouter: info.isAppRouter }));
1219
- if (info.hasISR && !viteConfigHasCacheAdapter(root) && !workerEntryHasCacheHandler(root)) throw new Error(formatMissingCacheAdapterError({ typedConfig: deploymentTool === "cf" }));
1220
- if (!viteConfigHasImageAdapter(root)) {
1224
+ if (hasViteConfig && !viteConfigHasCloudflarePlugin(root, viteConfigFile)) throw new Error(formatMissingCloudflarePluginError({
1225
+ isAppRouter: info.isAppRouter,
1226
+ configFile: viteConfigFile,
1227
+ initUpdatesConfig: !viteConfigFile
1228
+ }));
1229
+ if (info.hasISR && !viteConfigHasCacheAdapter(root, viteConfigFile) && !workerEntryHasCacheHandler(root)) throw new Error(formatMissingCacheAdapterError({
1230
+ configFile: viteConfigFile,
1231
+ typedConfig: deploymentTool === "cf"
1232
+ }));
1233
+ if (!viteConfigHasImageAdapter(root, viteConfigFile)) {
1221
1234
  console.log();
1222
- console.log(formatImageOptimizationHint(deploymentTool === "cf"));
1235
+ console.log(formatImageOptimizationHint(deploymentTool === "cf", viteConfigFile));
1223
1236
  }
1224
1237
  if (options.dryRun) {
1225
1238
  console.log("\n Dry run complete. No build or deploy performed.\n");
@@ -1233,7 +1246,7 @@ async function deploy(options) {
1233
1246
  }));
1234
1247
  return;
1235
1248
  }
1236
- const viteConfigMetadata = await withBuildContext(() => loadDeployViteConfigMetadata(info.root, viteMode));
1249
+ const viteConfigMetadata = await withBuildContext(() => loadDeployViteConfigMetadata(info.root, viteMode, viteConfigFile));
1237
1250
  const cdnAdapterConfig = resolveCdnAdapterConfig(viteConfigMetadata.cacheConfig);
1238
1251
  const nextConfig = await withBuildContext(async () => {
1239
1252
  const inlineNextConfig = viteConfigMetadata.nextConfig;
@@ -1259,7 +1272,7 @@ async function deploy(options) {
1259
1272
  const replacement = isPreview ? "Preview deployments render these routes on request." : 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.";
1260
1273
  console.warn(`\n Warning: ${trigger} is ignored by Cloudflare deploy. ${replacement}`);
1261
1274
  }
1262
- if (!options.skipBuild) await withBuildContext(() => runBuild(info, cloudflareEnv, viteMode));
1275
+ if (!options.skipBuild) await withBuildContext(() => runBuild(info, cloudflareEnv, viteMode, viteConfigFile));
1263
1276
  else console.log("\n Skipping build (--skip-build)");
1264
1277
  const prerenderOutputDirs = resolvePrerenderOutputDirs(info.root, deploymentTool, viteConfigMetadata.routeRootConfig);
1265
1278
  const canWarmTpr = options.experimentalTPR && !shouldPrerenderLocally && hasBuildIdentityHeader;
@@ -5,5 +5,6 @@ export declare function parsePreviewsDeployArgs(args: string[]): {
5
5
  name: string | undefined;
6
6
  mode: string | undefined;
7
7
  skipBuild: boolean;
8
+ viteConfig: string | undefined;
8
9
  };
9
10
  //#endregion
@@ -28,7 +28,8 @@ function parsePreviewsDeployArgs(args) {
28
28
  "skip-build": {
29
29
  type: "boolean",
30
30
  default: false
31
- }
31
+ },
32
+ "vite-config": { type: "string" }
32
33
  }
33
34
  });
34
35
  if (positionals.length > 1) throw new Error("Expected at most one Preview name: previews deploy [preview-name].");
@@ -36,7 +37,8 @@ function parsePreviewsDeployArgs(args) {
36
37
  help: values.help,
37
38
  name: positionals[0] === void 0 ? void 0 : validatePreviewName(positionals[0]),
38
39
  mode: values.mode === void 0 ? void 0 : validateMode(values.mode),
39
- skipBuild: values["skip-build"]
40
+ skipBuild: values["skip-build"],
41
+ viteConfig: values["vite-config"]?.trim() || void 0
40
42
  };
41
43
  }
42
44
  //#endregion
package/dist/tpr.js CHANGED
@@ -102,7 +102,6 @@ function filterTrafficPaths(entries) {
102
102
  if (/\.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?|ttf|eot|map|webp|avif)$/i.test(e.path)) return false;
103
103
  if (e.path.startsWith("/api/")) return false;
104
104
  if (e.path.startsWith("/_next/") || e.path.startsWith("/__vinext/")) return false;
105
- if (e.path.endsWith(".rsc")) return false;
106
105
  return true;
107
106
  });
108
107
  }
@@ -6,5 +6,10 @@
6
6
  * helpers in the vinext core).
7
7
  */
8
8
  export declare function isUnknownRecord(value: unknown): value is Record<string, unknown>;
9
+ /**
10
+ * When a `"use cache"` entry's generation started (`ctx.timestamp`), which dates
11
+ * the entry like Next.js does. Absent, malformed or future values fall back to `now`.
12
+ */
13
+ export declare function readCacheTimestamp(ctx: Record<string, unknown> | undefined, now: number): number;
9
14
  export declare function readCacheControlNumberField(ctx: Record<string, unknown> | undefined, field: string): number | undefined;
10
15
  //#endregion
@@ -12,9 +12,17 @@ function readRecordField(ctx, field) {
12
12
  const value = ctx?.[field];
13
13
  return isUnknownRecord(value) ? value : void 0;
14
14
  }
15
+ /**
16
+ * When a `"use cache"` entry's generation started (`ctx.timestamp`), which dates
17
+ * the entry like Next.js does. Absent, malformed or future values fall back to `now`.
18
+ */
19
+ function readCacheTimestamp(ctx, now) {
20
+ const value = ctx?.timestamp;
21
+ return typeof value === "number" && Number.isFinite(value) && value > 0 && value <= now ? value : now;
22
+ }
15
23
  function readCacheControlNumberField(ctx, field) {
16
24
  const value = readRecordField(ctx, "cacheControl")?.[field] ?? ctx?.[field];
17
25
  return typeof value === "number" ? value : void 0;
18
26
  }
19
27
  //#endregion
20
- export { isUnknownRecord, readCacheControlNumberField };
28
+ export { isUnknownRecord, readCacheControlNumberField, readCacheTimestamp };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vinext/cloudflare",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "Cloudflare cache and image adapters for vinext.",
5
5
  "homepage": "https://vinext.dev/",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@cloudflare/workers-response-store": "1.1.3"
51
+ "@cloudflare/workers-response-store": "1.1.4"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^25.9.2",
@@ -56,12 +56,12 @@
56
56
  "miniflare": "5.20260730.0-alpha",
57
57
  "vite": "npm:@voidzero-dev/vite-plus-core@1.3.0",
58
58
  "vite-plus": "1.3.0",
59
- "vinext": "1.3.1"
59
+ "vinext": "1.4.1"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "@cloudflare/vite-plugin": "*",
63
63
  "cf": "*",
64
- "vinext": "^1.3.1"
64
+ "vinext": "^1.4.1"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "@cloudflare/vite-plugin": {