@vercel/gatsby-plugin-vercel-builder 2.2.19 → 2.2.21

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.
Files changed (2) hide show
  1. package/dist/index.js +199 -5
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -814,6 +814,7 @@ var require_superstatic = __commonJS({
814
814
  var superstatic_exports = {};
815
815
  __export2(superstatic_exports, {
816
816
  collectHasSegments: () => collectHasSegments,
817
+ compilePathToRegexpTemplate: () => compilePathToRegexpTemplate2,
817
818
  convertCleanUrls: () => convertCleanUrls,
818
819
  convertHeaders: () => convertHeaders,
819
820
  convertRedirects: () => convertRedirects,
@@ -957,6 +958,22 @@ var require_superstatic = __commonJS({
957
958
  }
958
959
  route = { src, destination };
959
960
  }
961
+ if (r.transforms) {
962
+ route.transforms = r.transforms.map((transform) => {
963
+ if (transform.type !== "request.path") {
964
+ return { ...transform };
965
+ }
966
+ return {
967
+ ...transform,
968
+ args: compilePathToRegexpTemplateFromSegments(
969
+ transform.args,
970
+ segments,
971
+ hasSegments,
972
+ transform.env
973
+ )
974
+ };
975
+ });
976
+ }
960
977
  if (typeof r.env !== "undefined") {
961
978
  route.env = r.env;
962
979
  }
@@ -1097,6 +1114,81 @@ var require_superstatic = __commonJS({
1097
1114
  }
1098
1115
  var escapeSegment = (str, segmentName) => str.replace(new RegExp(`:${segmentName}`, "g"), `__ESC_COLON_${segmentName}`);
1099
1116
  var unescapeSegments = (str) => str.replace(/__ESC_COLON_/gi, ":");
1117
+ var pathTemplateSegmentNameRegex = /^([a-zA-Z_][a-zA-Z0-9_]*)/;
1118
+ function isEscaped(value, index) {
1119
+ let backslashCount = 0;
1120
+ for (let i = index - 1; i >= 0 && value[i] === "\\"; i--) {
1121
+ backslashCount++;
1122
+ }
1123
+ return backslashCount % 2 === 1;
1124
+ }
1125
+ function collectPathTemplateSegments(template) {
1126
+ const segments = [];
1127
+ for (let i = 0; i < template.length; i++) {
1128
+ if (template[i] !== ":" || isEscaped(template, i)) {
1129
+ continue;
1130
+ }
1131
+ const match = template.slice(i + 1).match(pathTemplateSegmentNameRegex);
1132
+ if (match) {
1133
+ segments.push(match[1]);
1134
+ i += match[1].length;
1135
+ }
1136
+ }
1137
+ return segments;
1138
+ }
1139
+ function collectNamedDollarReferences(template) {
1140
+ const references = [];
1141
+ for (let i = 0; i < template.length; i++) {
1142
+ if (template[i] !== "$" || isEscaped(template, i)) {
1143
+ continue;
1144
+ }
1145
+ const remainder = template.slice(i + 1);
1146
+ const bracedMatch = remainder.match(/^\{([a-zA-Z_][a-zA-Z0-9_]*)\}/);
1147
+ const unbracedMatch = remainder.match(pathTemplateSegmentNameRegex);
1148
+ const name = bracedMatch?.[1] || unbracedMatch?.[1];
1149
+ if (name) {
1150
+ references.push(name);
1151
+ }
1152
+ }
1153
+ return references;
1154
+ }
1155
+ function compilePathToRegexpTemplateFromSegments(template, segments, hasItemSegments, env = []) {
1156
+ const indexes = {};
1157
+ segments.forEach((name, index) => {
1158
+ indexes[name] = toSegmentDest(index);
1159
+ });
1160
+ hasItemSegments.forEach((name) => {
1161
+ indexes[name] = `$${name}`;
1162
+ });
1163
+ for (const name of collectPathTemplateSegments(template)) {
1164
+ if (!(name in indexes)) {
1165
+ throw new Error(
1166
+ `Path template references parameter ":${name}" that is not present in the source or has conditions.`
1167
+ );
1168
+ }
1169
+ }
1170
+ const routeParameters = /* @__PURE__ */ new Set([
1171
+ ...segments.filter((name) => name !== UN_NAMED_SEGMENT),
1172
+ ...hasItemSegments
1173
+ ]);
1174
+ for (const name of collectNamedDollarReferences(template)) {
1175
+ if (routeParameters.has(name) && !env.includes(name)) {
1176
+ throw new Error(
1177
+ `Path template references route parameter "${name}" as \`$${name}\`. Use \`:${name}\` path-to-regexp syntax in high-level rewrites, or list "${name}" in the transform env allowlist if it is an environment variable.`
1178
+ );
1179
+ }
1180
+ }
1181
+ return safelyCompile(template, indexes, true);
1182
+ }
1183
+ function compilePathToRegexpTemplate2(source, template, has, env) {
1184
+ const { segments } = sourceToRegex2(source);
1185
+ return compilePathToRegexpTemplateFromSegments(
1186
+ template,
1187
+ segments,
1188
+ collectHasSegments(has),
1189
+ env
1190
+ );
1191
+ }
1100
1192
  function replaceSegments(segments, hasItemSegments, destination, isRedirect, internalParamNames) {
1101
1193
  const namedSegments = segments.filter((name) => name !== UN_NAMED_SEGMENT);
1102
1194
  const canNeedReplacing = destination.includes(":") && namedSegments.length > 0 || hasItemSegments.length > 0 || !isRedirect;
@@ -1498,7 +1590,8 @@ var require_schemas = __commonJS({
1498
1590
  redirectsSchema: () => redirectsSchema,
1499
1591
  rewritesSchema: () => rewritesSchema,
1500
1592
  routesSchema: () => routesSchema,
1501
- trailingSlashSchema: () => trailingSlashSchema
1593
+ trailingSlashSchema: () => trailingSlashSchema,
1594
+ transformsSchema: () => transformsSchema
1502
1595
  });
1503
1596
  module2.exports = __toCommonJS2(schemas_exports);
1504
1597
  var mitigateSchema = {
@@ -1663,18 +1756,23 @@ var require_schemas = __commonJS({
1663
1756
  }
1664
1757
  };
1665
1758
  var transformsSchema = {
1666
- description: "A list of transform rules to adjust the query parameters of a request or HTTP headers of request or response",
1759
+ description: "A list of transform rules to adjust a request path, request query parameters, or request/response headers",
1667
1760
  type: "array",
1668
1761
  minItems: 1,
1669
1762
  items: {
1670
1763
  type: "object",
1671
1764
  additionalProperties: false,
1672
- required: ["type", "op", "target"],
1765
+ required: ["type", "op"],
1673
1766
  properties: {
1674
1767
  type: {
1675
1768
  description: "The scope of the transform to apply",
1676
1769
  type: "string",
1677
- enum: ["request.headers", "request.query", "response.headers"]
1770
+ enum: [
1771
+ "request.headers",
1772
+ "request.query",
1773
+ "response.headers",
1774
+ "request.path"
1775
+ ]
1678
1776
  },
1679
1777
  op: {
1680
1778
  description: "The operation to perform on the target",
@@ -1860,10 +1958,90 @@ var require_schemas = __commonJS({
1860
1958
  }
1861
1959
  }
1862
1960
  }
1961
+ },
1962
+ {
1963
+ if: {
1964
+ required: ["type"],
1965
+ properties: {
1966
+ type: {
1967
+ enum: ["request.headers", "request.query", "response.headers"]
1968
+ }
1969
+ }
1970
+ },
1971
+ // biome-ignore lint/suspicious/noThenProperty: JSON Schema if/then keyword
1972
+ then: {
1973
+ required: ["target"]
1974
+ }
1975
+ },
1976
+ {
1977
+ if: {
1978
+ required: ["type"],
1979
+ properties: {
1980
+ type: {
1981
+ enum: ["request.path"]
1982
+ }
1983
+ }
1984
+ },
1985
+ // biome-ignore lint/suspicious/noThenProperty: JSON Schema if/then keyword
1986
+ then: {
1987
+ required: ["args"],
1988
+ not: {
1989
+ required: ["target"]
1990
+ },
1991
+ properties: {
1992
+ op: {
1993
+ enum: ["set"]
1994
+ },
1995
+ args: {
1996
+ description: "The runtime-visible request path. Must be an origin-form path without query or fragment.",
1997
+ type: "string",
1998
+ maxLength: 2048,
1999
+ pattern: "^/(?!/)(?!.*[?#\\s\\x00-\\x1F\\x7F]).*$"
2000
+ }
2001
+ }
2002
+ }
1863
2003
  }
1864
2004
  ]
1865
2005
  }
1866
2006
  };
2007
+ var rewriteTransformsSchema = {
2008
+ description: "A list of request path transforms using path-to-regexp parameters.",
2009
+ type: "array",
2010
+ minItems: 1,
2011
+ items: {
2012
+ type: "object",
2013
+ additionalProperties: false,
2014
+ required: ["type", "op", "args"],
2015
+ properties: {
2016
+ type: {
2017
+ description: "The request path to expose to the target runtime",
2018
+ type: "string",
2019
+ enum: ["request.path"]
2020
+ },
2021
+ op: {
2022
+ description: "Replace the runtime-visible request path",
2023
+ type: "string",
2024
+ enum: ["set"]
2025
+ },
2026
+ args: {
2027
+ description: "An origin-form request path. Route parameters use path-to-regexp syntax such as `/:path*`.",
2028
+ type: "string",
2029
+ maxLength: 2048,
2030
+ pattern: "^/(?!/)(?!.*[?#\\s\\x00-\\x1F\\x7F]).*$"
2031
+ },
2032
+ env: {
2033
+ description: "An array of environment variable names that should be replaced at runtime in the args value",
2034
+ type: "array",
2035
+ minItems: 1,
2036
+ maxItems: 64,
2037
+ items: {
2038
+ type: "string",
2039
+ maxLength: 256
2040
+ }
2041
+ }
2042
+ }
2043
+ }
2044
+ };
1867
2045
  var routesSchema = {
1868
2046
  type: "array",
1869
2047
  description: "A list of routes objects used to rewrite paths to point towards other internal or external paths",
@@ -2043,6 +2221,7 @@ var require_schemas = __commonJS({
2043
2221
  description: "An absolute pathname to an existing resource, an external URL, or a service-targeted destination object.",
2044
2222
  anyOf: [{ type: "string", maxLength: 4096 }, serviceDestinationSchema]
2045
2223
  },
2224
+ transforms: rewriteTransformsSchema,
2046
2225
  has: hasSchema,
2047
2226
  missing: hasSchema,
2048
2227
  statusCode: {
@@ -2211,6 +2390,7 @@ var require_dist3 = __commonJS({
2211
2390
  var src_exports2 = {};
2212
2391
  __export2(src_exports2, {
2213
2392
  appendRoutesToPhase: () => import_append.appendRoutesToPhase,
2393
+ compilePathToRegexpTemplate: () => import_superstatic2.compilePathToRegexpTemplate,
2214
2394
  getCleanUrls: () => import_superstatic2.getCleanUrls,
2215
2395
  getOwnershipGuard: () => import_service_route_ownership.getOwnershipGuard,
2216
2396
  getTransformedRoutes: () => getTransformedRoutes2,
@@ -2384,7 +2564,8 @@ var require_dist3 = __commonJS({
2384
2564
  function checkPatternSyntax(type, index, {
2385
2565
  source,
2386
2566
  destination,
2387
- has
2567
+ has,
2568
+ transforms
2388
2569
  }) {
2389
2570
  let sourceSegments = /* @__PURE__ */ new Set();
2390
2571
  const destinationSegments = /* @__PURE__ */ new Set();
@@ -2424,6 +2605,19 @@ var require_dist3 = __commonJS({
2424
2605
  }
2425
2606
  }
2426
2607
  }
2608
+ for (const transform of transforms || []) {
2609
+ if (transform.type !== "request.path") {
2610
+ continue;
2611
+ }
2612
+ try {
2613
+ (0, import_superstatic.compilePathToRegexpTemplate)(source, transform.args, has, transform.env);
2614
+ } catch (error) {
2615
+ return {
2616
+ message: `${type} at index ${index} has an invalid \`request.path\` transform: ${error instanceof Error ? error.message : String(error)}`,
2617
+ link: "https://vercel.link/invalid-route-destination-segment"
2618
+ };
2619
+ }
2620
+ }
2427
2621
  return null;
2428
2622
  }
2429
2623
  function checkRedirect(r, index) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/gatsby-plugin-vercel-builder",
3
- "version": "2.2.19",
3
+ "version": "2.2.21",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist",
@@ -17,7 +17,7 @@
17
17
  "esbuild": "0.27.0",
18
18
  "etag": "1.8.1",
19
19
  "fs-extra": "11.1.0",
20
- "@vercel/build-utils": "13.30.0"
20
+ "@vercel/build-utils": "13.31.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/etag": "1.8.0",
@@ -25,7 +25,7 @@
25
25
  "@types/node": "20.11.0",
26
26
  "@types/react": "18.0.26",
27
27
  "vitest": "2.0.3",
28
- "@vercel/routing-utils": "6.3.0"
28
+ "@vercel/routing-utils": "6.3.1"
29
29
  },
30
30
  "license": "Apache-2.0",
31
31
  "scripts": {