@vinext/cloudflare 1.0.0-beta.3 → 1.0.0-beta.5
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/cache/cdn-adapter.runtime.d.ts +0 -1
- package/dist/cache/kv-data-adapter.d.ts +7 -3
- package/dist/cache/kv-data-adapter.runtime.d.ts +3 -6
- package/dist/cache/kv-data-adapter.runtime.js +5 -2
- package/dist/cache/kv-key.d.ts +2 -1
- package/dist/cdn-warm.d.ts +0 -1
- package/dist/cli.d.ts +1 -1
- package/dist/deploy-config.d.ts +0 -1
- package/dist/deploy.d.ts +37 -19
- package/dist/images/images-optimizer.d.ts +2 -1
- package/dist/images/images-optimizer.runtime.d.ts +1 -5
- package/dist/prerender-kv-populate.js +8 -6
- package/dist/tpr.d.ts +18 -8
- package/dist/version-deploy.d.ts +0 -1
- package/package.json +5 -5
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { CdnCacheAdapter, CdnCacheableHeaderInput, CdnResponseHeaders } from "vinext/shims/cdn-cache";
|
|
2
2
|
import { CacheHandlerValue, IncrementalCacheValue } from "vinext/shims/cache";
|
|
3
|
-
|
|
4
3
|
//#region src/cache/cdn-adapter.runtime.d.ts
|
|
5
4
|
declare class CloudflareCdnCacheAdapter implements CdnCacheAdapter {
|
|
6
5
|
readonly ownsBackgroundRevalidation = false;
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
declare const DEFAULT_KV_DATA_CACHE_BINDING = "VINEXT_KV_CACHE";
|
|
3
3
|
/** Options accepted by {@link kvDataAdapter}, forwarded to the runtime factory. */
|
|
4
4
|
type KvDataAdapterOptions = {
|
|
5
|
-
/** KV namespace binding name on the Worker `env`. @default "VINEXT_KV_CACHE" */
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/** KV namespace binding name on the Worker `env`. @default "VINEXT_KV_CACHE" */
|
|
6
|
+
binding?: string;
|
|
7
|
+
/** Namespace prefix for cache keys (isolates multiple apps in one namespace). */
|
|
8
|
+
appPrefix?: string;
|
|
9
|
+
/** Default KV `expirationTtl` in seconds. @default 2592000 (30 days) */
|
|
10
|
+
ttlSeconds?: number;
|
|
11
|
+
/** TTL in milliseconds for the in-memory tag-invalidation cache. @default 5000 */
|
|
8
12
|
tagCacheTtlMs?: number;
|
|
9
13
|
};
|
|
10
14
|
/**
|
|
@@ -2,7 +2,6 @@ import { KvDataAdapterOptions } from "./kv-data-adapter.js";
|
|
|
2
2
|
import { ENTRY_PREFIX } from "./kv-key.js";
|
|
3
3
|
import { ExecutionContextLike } from "vinext/shims/request-context";
|
|
4
4
|
import { CacheHandler, CacheHandlerValue, IncrementalCacheValue } from "vinext/shims/cache";
|
|
5
|
-
|
|
6
5
|
//#region src/cache/kv-data-adapter.runtime.d.ts
|
|
7
6
|
type KVNamespace = {
|
|
8
7
|
get(key: string, options?: {
|
|
@@ -62,7 +61,8 @@ declare class KVCacheHandler implements CacheHandler {
|
|
|
62
61
|
constructor(kvNamespace: KVNamespace, options?: {
|
|
63
62
|
appPrefix?: string;
|
|
64
63
|
ctx?: ExecutionContextLike;
|
|
65
|
-
ttlSeconds?: number;
|
|
64
|
+
ttlSeconds?: number;
|
|
65
|
+
/** TTL in milliseconds for the local tag cache. Defaults to 5000ms. */
|
|
66
66
|
tagCacheTtlMs?: number;
|
|
67
67
|
});
|
|
68
68
|
private _entryKey;
|
|
@@ -125,10 +125,7 @@ declare class KVCacheHandler implements CacheHandler {
|
|
|
125
125
|
*/
|
|
126
126
|
private _put;
|
|
127
127
|
}
|
|
128
|
-
declare const createKvDataCacheAdapter: ({
|
|
129
|
-
env,
|
|
130
|
-
options
|
|
131
|
-
}: {
|
|
128
|
+
declare const createKvDataCacheAdapter: ({ env, options }: {
|
|
132
129
|
env?: Record<string, unknown>;
|
|
133
130
|
options?: KvDataAdapterOptions;
|
|
134
131
|
}) => CacheHandler;
|
|
@@ -213,14 +213,16 @@ var KVCacheHandler = class {
|
|
|
213
213
|
let effectiveExpire;
|
|
214
214
|
effectiveRevalidate = readCacheControlNumberField(ctx, "revalidate");
|
|
215
215
|
effectiveExpire = readCacheControlNumberField(ctx, "expire");
|
|
216
|
+
const effectiveStale = readCacheControlNumberField(ctx, "stale");
|
|
216
217
|
if (data && "revalidate" in data && typeof data.revalidate === "number") effectiveRevalidate = data.revalidate;
|
|
217
218
|
if (effectiveRevalidate === 0) return Promise.resolve();
|
|
218
219
|
const now = Date.now();
|
|
219
220
|
const revalidateAt = typeof effectiveRevalidate === "number" && effectiveRevalidate > 0 ? now + effectiveRevalidate * 1e3 : null;
|
|
220
221
|
const expireAt = typeof effectiveExpire === "number" && effectiveExpire > 0 ? now + effectiveExpire * 1e3 : null;
|
|
221
|
-
const cacheControl = typeof effectiveRevalidate === "number" ?
|
|
222
|
+
const cacheControl = typeof effectiveRevalidate === "number" ? {
|
|
222
223
|
revalidate: effectiveRevalidate,
|
|
223
|
-
expire: effectiveExpire
|
|
224
|
+
...effectiveExpire === void 0 ? {} : { expire: effectiveExpire },
|
|
225
|
+
...effectiveStale === void 0 ? {} : { stale: effectiveStale }
|
|
224
226
|
} : void 0;
|
|
225
227
|
const entry = {
|
|
226
228
|
value: data ? serializeForJSON(data) : null,
|
|
@@ -350,6 +352,7 @@ function validateCacheEntry(raw) {
|
|
|
350
352
|
if (!isUnknownRecord(obj.cacheControl)) return null;
|
|
351
353
|
if (typeof obj.cacheControl.revalidate !== "number") return null;
|
|
352
354
|
if (obj.cacheControl.expire !== void 0 && typeof obj.cacheControl.expire !== "number") return null;
|
|
355
|
+
if (obj.cacheControl.stale !== void 0 && typeof obj.cacheControl.stale !== "number") return null;
|
|
353
356
|
}
|
|
354
357
|
if (obj.value !== null) {
|
|
355
358
|
if (!obj.value || typeof obj.value !== "object") return null;
|
package/dist/cache/kv-key.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
/** Key prefix for cache entries. */
|
|
3
3
|
declare const ENTRY_PREFIX = "cache:";
|
|
4
4
|
type KvKeySpace = {
|
|
5
|
-
/** Prefix shared by every cache entry, including entries with hashed logical keys. */
|
|
5
|
+
/** Prefix shared by every cache entry, including entries with hashed logical keys. */
|
|
6
|
+
entryPrefix: string;
|
|
6
7
|
entryKey(logicalKey: string): string;
|
|
7
8
|
tagKey(tag: string): string;
|
|
8
9
|
};
|
package/dist/cdn-warm.d.ts
CHANGED
package/dist/cli.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/deploy-config.d.ts
CHANGED
package/dist/deploy.d.ts
CHANGED
|
@@ -2,27 +2,45 @@ import { parseWranglerConfig } from "./tpr.js";
|
|
|
2
2
|
import { WranglerDeploymentStatus, WranglerVersionTraffic } from "./version-deploy.js";
|
|
3
3
|
import { KVBulkPair } from "./prerender-kv-populate.js";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
-
|
|
6
5
|
//#region src/deploy.d.ts
|
|
7
6
|
type DeployOptions = {
|
|
8
|
-
/** Project root directory */
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
7
|
+
/** Project root directory */
|
|
8
|
+
root: string;
|
|
9
|
+
/** Deploy to preview environment (default: production) */
|
|
10
|
+
preview?: boolean;
|
|
11
|
+
/** Wrangler environment name from wrangler.jsonc env.<name> */
|
|
12
|
+
env?: string;
|
|
13
|
+
/** Custom project name for the Worker */
|
|
14
|
+
name?: string;
|
|
15
|
+
/** Wrangler config path, relative to root unless absolute */
|
|
16
|
+
config?: string;
|
|
17
|
+
/** Skip the build step (assume already built) */
|
|
18
|
+
skipBuild?: boolean;
|
|
19
|
+
/** Dry run — validate setup but don't build or deploy */
|
|
20
|
+
dryRun?: boolean;
|
|
21
|
+
/** Pre-render all discovered routes into the dist output after building */
|
|
22
|
+
prerenderAll?: boolean;
|
|
23
|
+
/** Maximum number of routes to prerender in parallel */
|
|
24
|
+
prerenderConcurrency?: number;
|
|
25
|
+
/** Warm Cloudflare's CDN cache by requesting build-discovered paths for the uploaded version */
|
|
26
|
+
warmCdnCache?: boolean;
|
|
27
|
+
/** Maximum number of CDN warmup requests to issue in parallel */
|
|
28
|
+
warmCdnConcurrency?: number;
|
|
29
|
+
/** Per-request CDN warmup timeout in milliseconds */
|
|
30
|
+
warmCdnTimeout?: number;
|
|
31
|
+
/** Number of CDN warmup retries for transient failures */
|
|
32
|
+
warmCdnRetries?: number;
|
|
33
|
+
/** Fail deployment if any CDN warmup request fails */
|
|
34
|
+
warmCdnStrict?: boolean;
|
|
35
|
+
/** Include PPR fallback-shell placeholder paths during CDN warmup */
|
|
36
|
+
warmCdnIncludeFallbacks?: boolean;
|
|
37
|
+
/** Enable experimental TPR (Traffic-aware Pre-Rendering) */
|
|
38
|
+
experimentalTPR?: boolean;
|
|
39
|
+
/** TPR: traffic coverage percentage target (0–100, default: 90) */
|
|
40
|
+
tprCoverage?: number;
|
|
41
|
+
/** TPR: hard cap on number of pages to pre-render (default: 1000) */
|
|
42
|
+
tprLimit?: number;
|
|
43
|
+
/** TPR: analytics lookback window in hours (default: 24) */
|
|
26
44
|
tprWindow?: number;
|
|
27
45
|
};
|
|
28
46
|
declare function parseDeployArgs(args: string[]): {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
//#region src/images/images-optimizer.d.ts
|
|
2
2
|
/** Options accepted by {@link imagesOptimizer}, forwarded to the runtime factory. */
|
|
3
3
|
type ImagesOptimizerOptions = {
|
|
4
|
-
/** Cloudflare Images binding name on the Worker `env`. @default "IMAGES" */
|
|
4
|
+
/** Cloudflare Images binding name on the Worker `env`. @default "IMAGES" */
|
|
5
|
+
binding?: string;
|
|
5
6
|
};
|
|
6
7
|
/**
|
|
7
8
|
* Config-time builder: returns a serializable descriptor whose `adapter` is the
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import { ImageOptimizer } from "vinext/server/image-optimization";
|
|
2
|
-
|
|
3
2
|
//#region src/images/images-optimizer.runtime.d.ts
|
|
4
3
|
/** Options accepted by the optimizer factory (mirrors `ImagesOptimizerOptions`). */
|
|
5
4
|
type ImagesOptimizerOptions = {
|
|
6
5
|
binding?: string;
|
|
7
6
|
};
|
|
8
|
-
declare const createCloudflareImageOptimizer: ({
|
|
9
|
-
env,
|
|
10
|
-
options
|
|
11
|
-
}: {
|
|
7
|
+
declare const createCloudflareImageOptimizer: ({ env, options }: {
|
|
12
8
|
env?: Record<string, unknown>;
|
|
13
9
|
options?: ImagesOptimizerOptions;
|
|
14
10
|
}) => ImageOptimizer;
|
|
@@ -28,10 +28,11 @@ function formatUnknownError(error) {
|
|
|
28
28
|
if (error instanceof Error && error.message) return error.message;
|
|
29
29
|
return String(error);
|
|
30
30
|
}
|
|
31
|
-
function buildCacheEntry(value, tags, now, revalidateSeconds, expireSeconds) {
|
|
32
|
-
const cacheControl = revalidateSeconds === void 0 ? void 0 :
|
|
31
|
+
function buildCacheEntry(value, tags, now, revalidateSeconds, expireSeconds, staleSeconds) {
|
|
32
|
+
const cacheControl = revalidateSeconds === void 0 ? void 0 : {
|
|
33
33
|
revalidate: revalidateSeconds,
|
|
34
|
-
expire: expireSeconds
|
|
34
|
+
...expireSeconds === void 0 ? {} : { expire: expireSeconds },
|
|
35
|
+
...staleSeconds === void 0 ? {} : { stale: staleSeconds }
|
|
35
36
|
};
|
|
36
37
|
return JSON.stringify({
|
|
37
38
|
value,
|
|
@@ -79,8 +80,9 @@ function buildPrerenderKVPairs(serverDir, options) {
|
|
|
79
80
|
if (typeof route.revalidate === "number" && route.revalidate <= 0) continue;
|
|
80
81
|
const revalidateSeconds = typeof route.revalidate === "number" ? route.revalidate : void 0;
|
|
81
82
|
const expireSeconds = typeof route.expire === "number" ? route.expire : void 0;
|
|
83
|
+
const staleSeconds = typeof route.stale === "number" && route.stale >= 0 ? route.stale : void 0;
|
|
82
84
|
const expirationTtl = revalidateSeconds === void 0 ? void 0 : ttlSeconds;
|
|
83
|
-
const tags = buildAppPageCacheTags(cachePathname, []);
|
|
85
|
+
const tags = buildAppPageCacheTags(cachePathname, route.tags ?? []);
|
|
84
86
|
const metadata = buildMetadata(tags);
|
|
85
87
|
const htmlKey = appIsrCacheKey(cachePathname, "html", manifest.buildId);
|
|
86
88
|
const rscKey = appIsrCacheKey(cachePathname, "rsc", manifest.buildId);
|
|
@@ -90,7 +92,7 @@ function buildPrerenderKVPairs(serverDir, options) {
|
|
|
90
92
|
kind: "APP_PAGE",
|
|
91
93
|
html: fs.readFileSync(htmlPath, "utf-8"),
|
|
92
94
|
headers: route.headers
|
|
93
|
-
}, tags, now, revalidateSeconds, expireSeconds),
|
|
95
|
+
}, tags, now, revalidateSeconds, expireSeconds, staleSeconds),
|
|
94
96
|
...expirationTtl !== void 0 ? { expiration_ttl: expirationTtl } : {},
|
|
95
97
|
...metadata ? { metadata } : {}
|
|
96
98
|
});
|
|
@@ -102,7 +104,7 @@ function buildPrerenderKVPairs(serverDir, options) {
|
|
|
102
104
|
kind: "APP_PAGE",
|
|
103
105
|
html: "",
|
|
104
106
|
rscData
|
|
105
|
-
}, tags, now, revalidateSeconds, expireSeconds),
|
|
107
|
+
}, tags, now, revalidateSeconds, expireSeconds, staleSeconds),
|
|
106
108
|
...expirationTtl !== void 0 ? { expiration_ttl: expirationTtl } : {},
|
|
107
109
|
...metadata ? { metadata } : {}
|
|
108
110
|
});
|
package/dist/tpr.d.ts
CHANGED
|
@@ -21,17 +21,27 @@
|
|
|
21
21
|
* or no KV namespace is configured.
|
|
22
22
|
*/
|
|
23
23
|
type TPROptions = {
|
|
24
|
-
/** Project root directory. */
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
/** Project root directory. */
|
|
25
|
+
root: string;
|
|
26
|
+
/** Wrangler config path, relative to root unless absolute. */
|
|
27
|
+
config?: string;
|
|
28
|
+
/** Traffic coverage percentage (0–100). Default: 90. */
|
|
29
|
+
coverage: number;
|
|
30
|
+
/** Hard cap on number of pages to pre-render. Default: 1000. */
|
|
31
|
+
limit: number;
|
|
32
|
+
/** Analytics lookback window in hours. Default: 24. */
|
|
28
33
|
window: number;
|
|
29
34
|
};
|
|
30
35
|
type TPRResult = {
|
|
31
|
-
/** Total unique page paths found in analytics. */
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
/** Total unique page paths found in analytics. */
|
|
37
|
+
totalPaths: number;
|
|
38
|
+
/** Number of pages successfully pre-rendered and uploaded. */
|
|
39
|
+
prerenderedCount: number;
|
|
40
|
+
/** Actual traffic coverage achieved (percentage). */
|
|
41
|
+
coverageAchieved: number;
|
|
42
|
+
/** Wall-clock duration of the TPR step in milliseconds. */
|
|
43
|
+
durationMs: number;
|
|
44
|
+
/** If TPR was skipped, the reason. */
|
|
35
45
|
skipped?: string;
|
|
36
46
|
};
|
|
37
47
|
type PrerenderResult = {
|
package/dist/version-deploy.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vinext/cloudflare",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.5",
|
|
4
4
|
"description": "Cloudflare adapters for vinext (KV data cache and Images-backed image optimization).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "^25.9.2",
|
|
55
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.
|
|
56
|
-
"vite-plus": "0.2.
|
|
57
|
-
"vinext": "1.0.0-beta.
|
|
55
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.6",
|
|
56
|
+
"vite-plus": "0.2.6",
|
|
57
|
+
"vinext": "1.0.0-beta.5"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
|
-
"vinext": "^1.0.0-beta.
|
|
60
|
+
"vinext": "^1.0.0-beta.5"
|
|
61
61
|
},
|
|
62
62
|
"engines": {
|
|
63
63
|
"node": ">=22"
|