veryfront 0.1.841 → 0.1.843
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/esm/deno.js +1 -1
- package/esm/src/cache/keys/prefixes.d.ts +3 -3
- package/esm/src/cache/keys/prefixes.d.ts.map +1 -1
- package/esm/src/cache/keys/prefixes.js +14 -0
- package/esm/src/cache/keys/utils.d.ts.map +1 -1
- package/esm/src/cache/keys/utils.js +33 -9
- package/esm/src/config/schemas/config.schema.d.ts +4 -4
- package/esm/src/config/schemas/config.schema.js +2 -2
- package/esm/src/rendering/renderer.d.ts +2 -2
- package/esm/src/rendering/renderer.js +2 -2
- package/esm/src/server/handlers/request/module/page-data-endpoint-handler.d.ts.map +1 -1
- package/esm/src/server/handlers/request/module/page-data-endpoint-handler.js +3 -10
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
package/esm/deno.js
CHANGED
|
@@ -36,13 +36,13 @@ export type FileSourceType = "branch" | "release" | "environment";
|
|
|
36
36
|
* Query parameter handling policy for cache keys.
|
|
37
37
|
*
|
|
38
38
|
* - "ignore-all": Ignore all query params (best for marketing UTM params)
|
|
39
|
-
* - "include-all": Include all query params in cache key
|
|
39
|
+
* - "include-all": Include all query params in cache key
|
|
40
40
|
* - "include-list": Only include specified params
|
|
41
|
-
* - "exclude-list": Include all except specified params
|
|
41
|
+
* - "exclude-list": Include all except specified params (default behavior)
|
|
42
42
|
*/
|
|
43
43
|
export type QueryParamPolicy = "ignore-all" | "include-all" | "include-list" | "exclude-list";
|
|
44
44
|
export interface QueryParamCacheOptions {
|
|
45
|
-
/** How to handle query params. Default: "
|
|
45
|
+
/** How to handle query params. Default: "exclude-list" */
|
|
46
46
|
policy?: QueryParamPolicy;
|
|
47
47
|
/** List of param names for include-list or exclude-list policies */
|
|
48
48
|
params?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prefixes.d.ts","sourceRoot":"","sources":["../../../../src/src/cache/keys/prefixes.ts"],"names":[],"mappings":"AAAA;;;;;;kFAMkF;AAElF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;CA0CjB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAElE;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAE9F,MAAM,WAAW,sBAAsB;IACrC,
|
|
1
|
+
{"version":3,"file":"prefixes.d.ts","sourceRoot":"","sources":["../../../../src/src/cache/keys/prefixes.ts"],"names":[],"mappings":"AAAA;;;;;;kFAMkF;AAElF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;CA0CjB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,CAAC;AAElE;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAE9F,MAAM,WAAW,sBAAsB;IACrC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,cAAc,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,6FAA6F;AAC7F,eAAO,MAAM,6BAA6B,UA+CzC,CAAC"}
|
|
@@ -58,20 +58,34 @@ export const DEFAULT_EXCLUDED_QUERY_PARAMS = [
|
|
|
58
58
|
"dclid",
|
|
59
59
|
"_ga",
|
|
60
60
|
"_gl",
|
|
61
|
+
"gad_source",
|
|
62
|
+
"gbraid",
|
|
63
|
+
"wbraid",
|
|
61
64
|
// Facebook
|
|
62
65
|
"fbclid",
|
|
63
66
|
"fb_action_ids",
|
|
64
67
|
"fb_action_types",
|
|
68
|
+
// LinkedIn
|
|
69
|
+
"li_fat_id",
|
|
65
70
|
// Microsoft / Bing
|
|
66
71
|
"msclkid",
|
|
67
72
|
// Mailchimp
|
|
68
73
|
"mc_cid",
|
|
69
74
|
"mc_eid",
|
|
75
|
+
// Cache-busting probes
|
|
76
|
+
"_",
|
|
77
|
+
"cb",
|
|
78
|
+
"cacheBust",
|
|
79
|
+
"cache_bust",
|
|
80
|
+
"cachebuster",
|
|
81
|
+
"cache_buster",
|
|
70
82
|
// Other tracking
|
|
71
83
|
"ref",
|
|
72
84
|
"referrer",
|
|
73
85
|
"source",
|
|
74
86
|
"_openstat",
|
|
87
|
+
"igshid",
|
|
88
|
+
"twclid",
|
|
75
89
|
"yclid",
|
|
76
90
|
"zanpid",
|
|
77
91
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/src/cache/keys/utils.ts"],"names":[],"mappings":"AAAA;;;;;;kFAMkF;AASlF,OAAO,EAAiC,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/src/cache/keys/utils.ts"],"names":[],"mappings":"AAAA;;;;;;kFAMkF;AASlF,OAAO,EAAiC,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAI3F,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,IAAI,CAcP;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAcrD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkB1D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,EACvB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAwBzB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,GAAG,GAAG,eAAe,EAC1B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,MAAM,CAsBR;AA+BD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAqB3B;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAE7E;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,YAAY,GAAE,OAAc,GAC3B,OAAO,CAAC;IAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;CAAE,CAAC,CAU1E;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CAW1D"}
|
|
@@ -10,6 +10,7 @@ import { withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
|
10
10
|
import { SpanNames } from "../../observability/tracing/span-names.js";
|
|
11
11
|
import { cacheRegistry } from "../registry.js";
|
|
12
12
|
import { DEFAULT_EXCLUDED_QUERY_PARAMS } from "./prefixes.js";
|
|
13
|
+
const querySegmentEncoder = new TextEncoder();
|
|
13
14
|
export function parseRenderCacheKey(cacheKey) {
|
|
14
15
|
const parts = cacheKey.split(":");
|
|
15
16
|
if (parts.length < 5)
|
|
@@ -89,15 +90,17 @@ export function filterQueryParams(params, options) {
|
|
|
89
90
|
case "include-list":
|
|
90
91
|
return entries.filter(([key]) => paramList.includes(key));
|
|
91
92
|
case "exclude-list": {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return entries.filter(([key]) => !excludeSet.has(key));
|
|
93
|
+
const excludeSet = new Set([...DEFAULT_EXCLUDED_QUERY_PARAMS, ...paramList].map(normalizeQueryParamName));
|
|
94
|
+
return entries.filter(([key]) => !excludeSet.has(normalizeQueryParamName(key)));
|
|
95
95
|
}
|
|
96
96
|
case "include-all":
|
|
97
97
|
default:
|
|
98
98
|
return entries;
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
|
+
function normalizeQueryParamName(param) {
|
|
102
|
+
return param.toLowerCase();
|
|
103
|
+
}
|
|
101
104
|
/**
|
|
102
105
|
* Sanitize query params for use in cache keys.
|
|
103
106
|
* Converts query params to a format safe for API cache key validation.
|
|
@@ -114,22 +117,43 @@ export function sanitizeQueryParamsForCacheKey(url, options) {
|
|
|
114
117
|
const filtered = filterQueryParams(params, options);
|
|
115
118
|
if (filtered.length === 0)
|
|
116
119
|
return "";
|
|
117
|
-
|
|
118
|
-
const sorted = filtered.sort(([a], [b]) => a.localeCompare(b));
|
|
120
|
+
const sorted = sortQueryParamsForCacheKey(filtered);
|
|
119
121
|
// Build sanitized string using allowed characters:
|
|
120
122
|
// - Use hyphen (-) instead of equals (=)
|
|
121
123
|
// - Use underscore (_) instead of ampersand (&)
|
|
122
|
-
// -
|
|
124
|
+
// - Percent-encode special characters using * as the escape marker
|
|
123
125
|
const sanitized = sorted
|
|
124
126
|
.map(([key, value]) => {
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
const safeValue = value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
127
|
+
const safeKey = encodeCacheKeySegment(key);
|
|
128
|
+
const safeValue = encodeCacheKeySegment(value);
|
|
128
129
|
return `${safeKey}-${safeValue}`;
|
|
129
130
|
})
|
|
130
131
|
.join("_");
|
|
131
132
|
return sanitized;
|
|
132
133
|
}
|
|
134
|
+
function sortQueryParamsForCacheKey(entries) {
|
|
135
|
+
const grouped = new Map();
|
|
136
|
+
for (const entry of entries) {
|
|
137
|
+
const [key] = entry;
|
|
138
|
+
const group = grouped.get(key);
|
|
139
|
+
if (group) {
|
|
140
|
+
group.push(entry);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
grouped.set(key, [entry]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return [...grouped.keys()]
|
|
147
|
+
.sort((leftKey, rightKey) => leftKey.localeCompare(rightKey))
|
|
148
|
+
.flatMap((key) => grouped.get(key));
|
|
149
|
+
}
|
|
150
|
+
function encodeCacheKeySegment(value) {
|
|
151
|
+
return Array.from(value, (char) => {
|
|
152
|
+
if (/^[a-zA-Z0-9_.-]$/.test(char))
|
|
153
|
+
return char;
|
|
154
|
+
return Array.from(querySegmentEncoder.encode(char), (byte) => `*${byte.toString(16).toUpperCase().padStart(2, "0")}`).join("");
|
|
155
|
+
}).join("");
|
|
156
|
+
}
|
|
133
157
|
export function createCacheKeyFilter(options) {
|
|
134
158
|
return (key) => {
|
|
135
159
|
const parts = key.split(":");
|
|
@@ -57,9 +57,9 @@ export declare const getVeryfrontConfigSchema: () => import("../../internal-agen
|
|
|
57
57
|
*
|
|
58
58
|
* Policies:
|
|
59
59
|
* - "ignore-all": Ignore all query params (pages with ?utm_campaign=x share cache with /)
|
|
60
|
-
* - "include-all": Include all query params (
|
|
60
|
+
* - "include-all": Include all query params (each unique query = separate cache)
|
|
61
61
|
* - "include-list": Only include specified params in cache key
|
|
62
|
-
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*)
|
|
62
|
+
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*) (default)
|
|
63
63
|
*
|
|
64
64
|
* @example
|
|
65
65
|
* // Ignore all marketing/tracking params (recommended for most sites)
|
|
@@ -461,9 +461,9 @@ export declare const veryfrontConfigSchema: import("../../internal-agents/schema
|
|
|
461
461
|
*
|
|
462
462
|
* Policies:
|
|
463
463
|
* - "ignore-all": Ignore all query params (pages with ?utm_campaign=x share cache with /)
|
|
464
|
-
* - "include-all": Include all query params (
|
|
464
|
+
* - "include-all": Include all query params (each unique query = separate cache)
|
|
465
465
|
* - "include-list": Only include specified params in cache key
|
|
466
|
-
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*)
|
|
466
|
+
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*) (default)
|
|
467
467
|
*
|
|
468
468
|
* @example
|
|
469
469
|
* // Ignore all marketing/tracking params (recommended for most sites)
|
|
@@ -97,9 +97,9 @@ export const getVeryfrontConfigSchema = defineSchema((v) => v
|
|
|
97
97
|
*
|
|
98
98
|
* Policies:
|
|
99
99
|
* - "ignore-all": Ignore all query params (pages with ?utm_campaign=x share cache with /)
|
|
100
|
-
* - "include-all": Include all query params (
|
|
100
|
+
* - "include-all": Include all query params (each unique query = separate cache)
|
|
101
101
|
* - "include-list": Only include specified params in cache key
|
|
102
|
-
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*)
|
|
102
|
+
* - "exclude-list": Exclude specified params (+ common tracking params like utm_*) (default)
|
|
103
103
|
*
|
|
104
104
|
* @example
|
|
105
105
|
* // Ignore all marketing/tracking params (recommended for most sites)
|
|
@@ -57,9 +57,9 @@ export declare class Renderer {
|
|
|
57
57
|
*
|
|
58
58
|
* Query param handling is configurable via `config.cache.queryParams`:
|
|
59
59
|
* - "ignore-all": Ignore all query params (pages share cache regardless of URL params)
|
|
60
|
-
* - "include-all": Include all query params (
|
|
60
|
+
* - "include-all": Include all query params (each unique query = separate cache)
|
|
61
61
|
* - "include-list": Only include specified params
|
|
62
|
-
* - "exclude-list": Exclude common tracking params (
|
|
62
|
+
* - "exclude-list": Exclude common tracking/cache-busting params (default)
|
|
63
63
|
*/
|
|
64
64
|
private buildCacheKey;
|
|
65
65
|
private doRenderPage;
|
|
@@ -216,9 +216,9 @@ export class Renderer {
|
|
|
216
216
|
*
|
|
217
217
|
* Query param handling is configurable via `config.cache.queryParams`:
|
|
218
218
|
* - "ignore-all": Ignore all query params (pages share cache regardless of URL params)
|
|
219
|
-
* - "include-all": Include all query params (
|
|
219
|
+
* - "include-all": Include all query params (each unique query = separate cache)
|
|
220
220
|
* - "include-list": Only include specified params
|
|
221
|
-
* - "exclude-list": Exclude common tracking params (
|
|
221
|
+
* - "exclude-list": Exclude common tracking/cache-busting params (default)
|
|
222
222
|
*/
|
|
223
223
|
buildCacheKey(slug, ctx, options) {
|
|
224
224
|
if (options?.cacheKey)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-data-endpoint-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/module/page-data-endpoint-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"page-data-endpoint-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/module/page-data-endpoint-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AA8EhE,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D;AAED,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,cAAc,EACnB,qBAAqB,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,eAAe,EAC/D,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,aAAa,EAC9C,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAC1C,OAAO,CAAC,aAAa,CAAC,CA6GxB"}
|
|
@@ -8,6 +8,7 @@ import { HTTP_GATEWAY_TIMEOUT } from "../../../../utils/constants/http.js";
|
|
|
8
8
|
import { serverLogger } from "../../../../utils/index.js";
|
|
9
9
|
import { Singleflight } from "../../../../utils/singleflight.js";
|
|
10
10
|
import { requestHasCacheSensitiveState } from "../../../../cache/request-cacheability.js";
|
|
11
|
+
import { sanitizeQueryParamsForCacheKey, } from "../../../../cache/keys.js";
|
|
11
12
|
import { getEnv } from "../../../../platform/compat/process.js";
|
|
12
13
|
const PAGE_DATA_TIMEOUT_MS = 25_000;
|
|
13
14
|
const PAGE_DATA_CACHE_TTL_MS = readPositiveIntegerEnv("VERYFRONT_PAGE_DATA_CACHE_TTL_MS", 60_000);
|
|
@@ -216,7 +217,8 @@ function buildPageDataCacheKey(ctx, slug, url) {
|
|
|
216
217
|
(environment === "production"
|
|
217
218
|
? ctx.releaseId ?? "release"
|
|
218
219
|
: ctx.requestContext?.branch ?? "main");
|
|
219
|
-
const
|
|
220
|
+
const queryParamOptions = ctx.config?.cache?.queryParams;
|
|
221
|
+
const query = sanitizeQueryParamsForCacheKey(url, queryParamOptions);
|
|
220
222
|
return [
|
|
221
223
|
projectKey,
|
|
222
224
|
environment,
|
|
@@ -225,12 +227,3 @@ function buildPageDataCacheKey(ctx, slug, url) {
|
|
|
225
227
|
query,
|
|
226
228
|
].join("|");
|
|
227
229
|
}
|
|
228
|
-
function buildSortedQueryKey(url) {
|
|
229
|
-
const entries = Array.from(url.searchParams.entries());
|
|
230
|
-
if (entries.length === 0)
|
|
231
|
-
return "";
|
|
232
|
-
return entries
|
|
233
|
-
.sort(([leftKey, leftValue], [rightKey, rightValue]) => leftKey === rightKey ? leftValue.localeCompare(rightValue) : leftKey.localeCompare(rightKey))
|
|
234
|
-
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
|
|
235
|
-
.join("&");
|
|
236
|
-
}
|