vercel 54.14.2 → 54.15.0

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 (53) hide show
  1. package/dist/chunks/{add-PKT6ULVJ.js → add-6XHROCMP.js} +5 -5
  2. package/dist/chunks/{chunk-3BR246Y6.js → chunk-3RIVJWW5.js} +2 -11
  3. package/dist/chunks/{chunk-J7BMPRCU.js → chunk-574PHXNT.js} +9 -4
  4. package/dist/chunks/{chunk-FLW73SZ3.js → chunk-6A62YUBE.js} +3 -3
  5. package/dist/chunks/{chunk-G3NXHUFT.js → chunk-6SL223IW.js} +1 -1
  6. package/dist/chunks/{chunk-2ZSXQQXI.js → chunk-6TPH3ZBU.js} +10 -19
  7. package/dist/chunks/{chunk-2XEEOHHH.js → chunk-AG6TBL6C.js} +1 -1
  8. package/dist/chunks/chunk-BRQ6PX3U.js +593 -0
  9. package/dist/chunks/{chunk-O7RJHL34.js → chunk-CENOYXK3.js} +583 -11
  10. package/dist/chunks/{chunk-YLGMXYFG.js → chunk-DCN3SOR6.js} +2 -2
  11. package/dist/chunks/{chunk-OHIZ4SVU.js → chunk-EAEEBPMD.js} +15 -3
  12. package/dist/chunks/{chunk-2HN6DLIY.js → chunk-HSXUEJ4T.js} +1 -1
  13. package/dist/chunks/{chunk-SDZ5ICZL.js → chunk-LABX5FSJ.js} +1 -1
  14. package/dist/chunks/{chunk-JISJDGJF.js → chunk-LOPPFUV3.js} +2 -2
  15. package/dist/chunks/{chunk-O4V7CMVO.js → chunk-OEYKL4IY.js} +7 -5
  16. package/dist/chunks/{chunk-372SHB43.js → chunk-OQD4G5FW.js} +4 -4
  17. package/dist/chunks/{chunk-LJ5WXXG6.js → chunk-QH7WYDEP.js} +11 -0
  18. package/dist/chunks/{chunk-Z3X747P6.js → chunk-RHXSECUF.js} +206 -31
  19. package/dist/chunks/{chunk-LQR3CHMH.js → chunk-SFPJ3VR7.js} +421 -799
  20. package/dist/chunks/{chunk-FEYVO2US.js → chunk-TLVKY7WL.js} +90 -32
  21. package/dist/chunks/{chunk-4BFK3C7V.js → chunk-UZD3DM6V.js} +1 -1
  22. package/dist/chunks/{chunk-IPWWE7PB.js → chunk-WGH26RJV.js} +1 -1
  23. package/dist/chunks/{chunk-ILJH44MK.js → chunk-YE3C5CUX.js} +1 -1
  24. package/dist/chunks/{compile-vercel-config-3LV7J3IZ.js → compile-vercel-config-ATU3UBFK.js} +1 -1
  25. package/dist/chunks/{delete-GFW6Y6TZ.js → delete-WIN4UHQY.js} +3 -3
  26. package/dist/chunks/{disable-PGRAS2ZL.js → disable-24KUO3TS.js} +3 -3
  27. package/dist/chunks/{discard-S6N5Q4G5.js → discard-B6ATZCPD.js} +3 -3
  28. package/dist/chunks/{edit-TICKX4ZV.js → edit-DIYIVLFQ.js} +7 -7
  29. package/dist/chunks/{enable-L3BYWN6S.js → enable-BF7NKTV7.js} +3 -3
  30. package/dist/chunks/{export-NXS33U5T.js → export-HHONDN7V.js} +3 -3
  31. package/dist/chunks/{inspect-OOI5JN3Y.js → inspect-GSYKUMK5.js} +4 -4
  32. package/dist/chunks/{list-77WL6463.js → list-OSJGB5AE.js} +4 -4
  33. package/dist/chunks/{list-6EHRL2D4.js → list-PZ4DRWLO.js} +2 -2
  34. package/dist/chunks/{ls-PBSOEXFG.js → ls-QBCHGSIC.js} +5 -5
  35. package/dist/chunks/{publish-CU2THVYW.js → publish-QYPZQ66O.js} +3 -3
  36. package/dist/chunks/{query-HEATRYAK.js → query-BDMX4CF6.js} +3 -3
  37. package/dist/chunks/{reorder-IQVKSM3H.js → reorder-YDTGTTJB.js} +3 -3
  38. package/dist/chunks/{restore-RDEOBGAS.js → restore-LXO2ZBAF.js} +3 -3
  39. package/dist/chunks/{rm-MCSGTU4J.js → rm-3L7FVCDA.js} +5 -5
  40. package/dist/chunks/{rule-inspect-3YK2XSL3.js → rule-inspect-T57QBYJR.js} +5 -5
  41. package/dist/chunks/{rules-F4MRDDHM.js → rules-E5DTNMFG.js} +7 -7
  42. package/dist/chunks/{schema-65C5EBJ7.js → schema-VYVJ4GYP.js} +3 -3
  43. package/dist/chunks/{update-XB4WSRGY.js → update-LT3LZVEZ.js} +5 -5
  44. package/dist/commands/build/index.js +157 -101
  45. package/dist/commands/deploy/index.js +13 -12
  46. package/dist/commands/dev/index.js +70 -23
  47. package/dist/commands/env/index.js +8 -6
  48. package/dist/commands/link/index.js +9 -16
  49. package/dist/commands/list/index.js +3 -3
  50. package/dist/commands-bulk.js +5371 -1618
  51. package/dist/index.js +9 -9
  52. package/dist/version.mjs +1 -1
  53. package/package.json +21 -21
@@ -7,12 +7,12 @@ const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  printProjectNotFoundError,
9
9
  setupAndLink
10
- } from "./chunk-372SHB43.js";
10
+ } from "./chunk-OQD4G5FW.js";
11
11
  import {
12
12
  getLinkedProject,
13
13
  param,
14
14
  resolveProjectCwd
15
- } from "./chunk-LQR3CHMH.js";
15
+ } from "./chunk-SFPJ3VR7.js";
16
16
  import {
17
17
  buildCommandWithYes,
18
18
  outputActionRequired
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-V5P25P7F.js";
10
10
  import {
11
11
  getLocalPathConfig
12
- } from "./chunk-4BFK3C7V.js";
12
+ } from "./chunk-UZD3DM6V.js";
13
13
  import {
14
14
  DEFAULT_VERCEL_CONFIG_FILENAME,
15
15
  VERCEL_CONFIG_EXTENSIONS,
@@ -36,7 +36,7 @@ import {
36
36
  useKeypress,
37
37
  usePrefix,
38
38
  useState
39
- } from "./chunk-LQR3CHMH.js";
39
+ } from "./chunk-SFPJ3VR7.js";
40
40
  import {
41
41
  require_load_json_file
42
42
  } from "./chunk-HIYWSGI7.js";
@@ -1994,6 +1994,17 @@ Are you sure you want to proceed?`;
1994
1994
  }
1995
1995
  };
1996
1996
 
1997
+ // src/util/output/progress.ts
1998
+ function progress(current, total, opts = {}) {
1999
+ const { width = 20, complete = "=", incomplete = "-" } = opts;
2000
+ if (total <= 0 || current < 0 || current > total) {
2001
+ return null;
2002
+ }
2003
+ const unit = total / width;
2004
+ const pos = Math.floor(current / unit);
2005
+ return `${complete.repeat(pos)}${incomplete.repeat(width - pos)}`;
2006
+ }
2007
+
1997
2008
  export {
1998
2009
  getGlobalPathConfig2 as getGlobalPathConfig,
1999
2010
  require_dist3 as require_dist,
@@ -2007,5 +2018,6 @@ export {
2007
2018
  readLocalConfig,
2008
2019
  sleep,
2009
2020
  isJSONObject,
2010
- Client
2021
+ Client,
2022
+ progress
2011
2023
  };
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  STANDARD_ENVIRONMENTS
9
- } from "./chunk-LQR3CHMH.js";
9
+ } from "./chunk-SFPJ3VR7.js";
10
10
  import {
11
11
  getCommandName,
12
12
  require_lib
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  getEnvTargetPlaceholder
9
- } from "./chunk-LQR3CHMH.js";
9
+ } from "./chunk-SFPJ3VR7.js";
10
10
  import {
11
11
  projectOption,
12
12
  yesOption
@@ -6,7 +6,7 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  resolveAlertsScope
9
- } from "./chunk-FLW73SZ3.js";
9
+ } from "./chunk-6A62YUBE.js";
10
10
  import {
11
11
  handleValidationError,
12
12
  outputError,
@@ -14,7 +14,7 @@ import {
14
14
  } from "./chunk-D7MGZH35.js";
15
15
  import {
16
16
  AGENT_REASON
17
- } from "./chunk-LJ5WXXG6.js";
17
+ } from "./chunk-QH7WYDEP.js";
18
18
  import {
19
19
  buildCommandWithGlobalFlags,
20
20
  outputAgentError
@@ -6,27 +6,29 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  writeProjectSettings
9
- } from "./chunk-2XEEOHHH.js";
9
+ } from "./chunk-AG6TBL6C.js";
10
+ import {
11
+ autoInstallVercelPlugin
12
+ } from "./chunk-BRQ6PX3U.js";
10
13
  import {
11
14
  stamp_default
12
15
  } from "./chunk-64IF634X.js";
13
16
  import {
14
17
  ensureLink
15
- } from "./chunk-YLGMXYFG.js";
18
+ } from "./chunk-DCN3SOR6.js";
16
19
  import {
17
20
  pullCommand
18
- } from "./chunk-SDZ5ICZL.js";
21
+ } from "./chunk-LABX5FSJ.js";
19
22
  import {
20
23
  help
21
24
  } from "./chunk-AWD3IGXU.js";
22
25
  import {
23
26
  VERCEL_DIR,
24
27
  VERCEL_DIR_PROJECT,
25
- autoInstallVercelPlugin,
26
28
  envPullCommandLogic,
27
29
  humanizePath,
28
30
  parseTarget
29
- } from "./chunk-LQR3CHMH.js";
31
+ } from "./chunk-SFPJ3VR7.js";
30
32
  import {
31
33
  TelemetryClient
32
34
  } from "./chunk-HIYWSGI7.js";
@@ -7,13 +7,13 @@ const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  AGENT_REASON,
9
9
  AGENT_STATUS
10
- } from "./chunk-LJ5WXXG6.js";
10
+ } from "./chunk-QH7WYDEP.js";
11
11
  import {
12
12
  getLocalPathConfig
13
- } from "./chunk-4BFK3C7V.js";
13
+ } from "./chunk-UZD3DM6V.js";
14
14
  import {
15
15
  getScope
16
- } from "./chunk-G3NXHUFT.js";
16
+ } from "./chunk-6SL223IW.js";
17
17
  import {
18
18
  VERCEL_DIR_PROJECT,
19
19
  VERCEL_DIR_README,
@@ -48,7 +48,7 @@ import {
48
48
  selectAndParseRemoteUrl,
49
49
  selectOrg,
50
50
  writeServicesConfig
51
- } from "./chunk-LQR3CHMH.js";
51
+ } from "./chunk-SFPJ3VR7.js";
52
52
  import {
53
53
  buildCommandWithGlobalFlags,
54
54
  outputAgentError,
@@ -22,7 +22,10 @@ var AGENT_REASON = {
22
22
  NOT_FOUND: "not_found",
23
23
  PROJECT_NOT_FOUND: "project_not_found",
24
24
  MISSING_SCOPE: "missing_scope",
25
+ SCOPE_NOT_ACCESSIBLE: "scope_not_accessible",
25
26
  API_ERROR: "api_error",
27
+ // Flags
28
+ SEGMENT_IN_USE: "segment_in_use",
26
29
  // Env
27
30
  MISSING_REQUIREMENTS: "missing_requirements",
28
31
  MISSING_NAME: "missing_name",
@@ -46,6 +49,14 @@ var AGENT_REASON = {
46
49
  INVALID_DNS_TYPE: "invalid_dns_type",
47
50
  DNS_ADD_FAILED: "dns_add_failed",
48
51
  INVALID_DOMAIN: "invalid_domain",
52
+ CONFIGURED_CORRECTLY: "configured_correctly",
53
+ VERIFICATION_NEEDED: "verification_needed",
54
+ INVALID_CONFIGURATION: "invalid_configuration",
55
+ DNS_CHANGE_REQUIRED: "dns_change_required",
56
+ DNS_CHANGE_RECOMMENDED: "dns_change_recommended",
57
+ DNSSEC_NEEDS_TO_BE_DISABLED: "dnssec_needs_to_be_disabled",
58
+ PROJECT_ATTACHMENT_RECOMMENDED: "project_attachment_recommended",
59
+ PROJECT_DOMAIN_MISSING: "project_domain_missing",
49
60
  /** User must accept marketplace integration terms in the browser before install can continue. */
50
61
  INTEGRATION_TERMS_ACCEPTANCE_REQUIRED: "integration_terms_acceptance_required",
51
62
  /** Integration uninstall blocked because team-scoped resources still exist. */
@@ -6,8 +6,9 @@ const __filename = __fileURLToPath(import.meta.url);
6
6
  const __dirname = __dirname_(__filename);
7
7
  import {
8
8
  formatCondition,
9
- formatTransform
10
- } from "./chunk-J7BMPRCU.js";
9
+ formatTransform,
10
+ isTargetTransform
11
+ } from "./chunk-574PHXNT.js";
11
12
  import {
12
13
  output_manager_default
13
14
  } from "./chunk-Z5SBJH6L.js";
@@ -26,28 +27,62 @@ function extractEnvVarNames(value) {
26
27
  }
27
28
  return Array.from(names);
28
29
  }
29
- function populateRouteEnv(route) {
30
- const routeEnv = /* @__PURE__ */ new Set();
31
- if (route.dest) {
32
- for (const name of extractEnvVarNames(route.dest)) {
33
- routeEnv.add(name);
34
- }
35
- }
36
- if (route.headers) {
37
- for (const value of Object.values(route.headers)) {
38
- for (const name of extractEnvVarNames(value)) {
39
- routeEnv.add(name);
30
+ function escapeRegex(value) {
31
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
32
+ }
33
+ function referencesEnvVar(value, name) {
34
+ const escapedName = escapeRegex(name);
35
+ return new RegExp(
36
+ `\\$(?:\\{${escapedName}\\}|${escapedName}(?![A-Za-z0-9_]))`
37
+ ).test(value);
38
+ }
39
+ function referencesBracedEnvVar(value, name) {
40
+ return new RegExp(`\\$\\{${escapeRegex(name)}\\}`).test(value);
41
+ }
42
+ function collectReferencedEnvVars(values, explicitEnv = [], excludedNames = /* @__PURE__ */ new Set()) {
43
+ const names = new Set(
44
+ explicitEnv.filter(
45
+ (name) => values.some((value) => referencesEnvVar(value, name))
46
+ )
47
+ );
48
+ for (const value of values) {
49
+ for (const name of extractEnvVarNames(value)) {
50
+ if (!excludedNames.has(name) || names.has(name) || referencesBracedEnvVar(value, name)) {
51
+ names.add(name);
40
52
  }
41
53
  }
42
54
  }
43
- route.env = routeEnv.size > 0 ? Array.from(routeEnv) : void 0;
55
+ return Array.from(names);
56
+ }
57
+ function collectNamedRegexCaptures(source) {
58
+ return new Set(
59
+ Array.from(
60
+ source.matchAll(/\(\?<([a-zA-Z][a-zA-Z0-9_]*)>/g),
61
+ (match) => match[1]
62
+ )
63
+ );
64
+ }
65
+ function populateRouteEnv(route, srcSyntax = "regex") {
66
+ const excludedNames = srcSyntax === "regex" && route.src ? collectNamedRegexCaptures(route.src) : /* @__PURE__ */ new Set();
67
+ const routeValues = [
68
+ ...route.dest ? [route.dest] : [],
69
+ ...Object.values(route.headers || {})
70
+ ];
71
+ const routeEnv = collectReferencedEnvVars(
72
+ routeValues,
73
+ route.env,
74
+ excludedNames
75
+ );
76
+ route.env = routeEnv.length > 0 ? routeEnv : void 0;
44
77
  if (route.transforms) {
45
78
  for (const transform of route.transforms) {
46
- if (transform.args) {
47
- const argsStr = Array.isArray(transform.args) ? transform.args.join(" ") : transform.args;
48
- const names = extractEnvVarNames(argsStr);
49
- transform.env = names.length > 0 ? names : void 0;
50
- }
79
+ const args = transform.args ? Array.isArray(transform.args) ? transform.args : [transform.args] : [];
80
+ const names = collectReferencedEnvVars(
81
+ args,
82
+ transform.env,
83
+ excludedNames
84
+ );
85
+ transform.env = names.length > 0 ? names : void 0;
51
86
  }
52
87
  }
53
88
  }
@@ -643,6 +678,15 @@ function formatCondition2(field) {
643
678
  }
644
679
 
645
680
  // src/util/routes/ai-transform.ts
681
+ function isTargetTransformType(transform, type) {
682
+ return transform.type === type && isTargetTransform(transform);
683
+ }
684
+ function stringifyTransformArgs(args) {
685
+ return Array.isArray(args) ? args.join(", ") : args;
686
+ }
687
+ function isPathTransform(transform) {
688
+ return transform.type === "request.path";
689
+ }
646
690
  function generatedRouteToAddInput(generated) {
647
691
  const hasConditions = [];
648
692
  const missingConditions = [];
@@ -678,9 +722,16 @@ function generatedRouteToAddInput(generated) {
678
722
  status = action.status;
679
723
  break;
680
724
  case "modify": {
681
- if (!action.headers)
682
- break;
683
- if (action.subType === "response-headers") {
725
+ if (action.subType === "transform-request-path") {
726
+ if (!action.requestPath)
727
+ break;
728
+ transforms.push({
729
+ type: "request.path",
730
+ op: action.requestPath.op,
731
+ args: action.requestPath.value,
732
+ ...action.requestPath.env && { env: action.requestPath.env }
733
+ });
734
+ } else if (action.subType === "response-headers" && action.headers) {
684
735
  for (const h of action.headers) {
685
736
  if (h.op === "set") {
686
737
  headers[h.key] = h.value ?? "";
@@ -693,7 +744,7 @@ function generatedRouteToAddInput(generated) {
693
744
  });
694
745
  }
695
746
  }
696
- } else if (action.subType === "transform-request-header") {
747
+ } else if (action.subType === "transform-request-header" && action.headers) {
697
748
  for (const h of action.headers) {
698
749
  transforms.push({
699
750
  type: "request.headers",
@@ -702,7 +753,7 @@ function generatedRouteToAddInput(generated) {
702
753
  ...h.op !== "delete" && h.value && { args: h.value }
703
754
  });
704
755
  }
705
- } else if (action.subType === "transform-request-query") {
756
+ } else if (action.subType === "transform-request-query" && action.headers) {
706
757
  for (const h of action.headers) {
707
758
  transforms.push({
708
759
  type: "request.query",
@@ -783,9 +834,9 @@ function routingRuleToCurrentRoute(rule) {
783
834
  op: "set"
784
835
  })) : [];
785
836
  const allTransforms = rule.route.transforms ?? [];
786
- const responseHeaderTransforms = allTransforms.filter((t) => t.type === "response.headers").map((t) => ({
837
+ const responseHeaderTransforms = allTransforms.filter((t) => isTargetTransformType(t, "response.headers")).map((t) => ({
787
838
  key: typeof t.target.key === "string" ? t.target.key : String(t.target.key),
788
- value: t.args,
839
+ value: stringifyTransformArgs(t.args),
789
840
  op: t.op
790
841
  }));
791
842
  const allResponseHeaders = [...responseHeaders, ...responseHeaderTransforms];
@@ -796,9 +847,9 @@ function routingRuleToCurrentRoute(rule) {
796
847
  headers: allResponseHeaders
797
848
  });
798
849
  }
799
- const requestHeaders = allTransforms.filter((t) => t.type === "request.headers").map((t) => ({
850
+ const requestHeaders = allTransforms.filter((t) => isTargetTransformType(t, "request.headers")).map((t) => ({
800
851
  key: typeof t.target.key === "string" ? t.target.key : String(t.target.key),
801
- value: t.args,
852
+ value: stringifyTransformArgs(t.args),
802
853
  op: t.op
803
854
  }));
804
855
  if (requestHeaders.length > 0) {
@@ -808,9 +859,9 @@ function routingRuleToCurrentRoute(rule) {
808
859
  headers: requestHeaders
809
860
  });
810
861
  }
811
- const requestQuery = allTransforms.filter((t) => t.type === "request.query").map((t) => ({
862
+ const requestQuery = allTransforms.filter((t) => isTargetTransformType(t, "request.query")).map((t) => ({
812
863
  key: typeof t.target.key === "string" ? t.target.key : String(t.target.key),
813
- value: t.args,
864
+ value: stringifyTransformArgs(t.args),
814
865
  op: t.op
815
866
  }));
816
867
  if (requestQuery.length > 0) {
@@ -820,6 +871,18 @@ function routingRuleToCurrentRoute(rule) {
820
871
  headers: requestQuery
821
872
  });
822
873
  }
874
+ const requestPathTransforms = allTransforms.filter(isPathTransform);
875
+ for (const requestPath of requestPathTransforms) {
876
+ actions.push({
877
+ type: "modify",
878
+ subType: "transform-request-path",
879
+ requestPath: {
880
+ value: requestPath.args,
881
+ op: requestPath.op,
882
+ ...requestPath.env && { env: requestPath.env }
883
+ }
884
+ });
885
+ }
823
886
  return {
824
887
  name: rule.name,
825
888
  description: rule.description,
@@ -876,7 +939,15 @@ function printGeneratedRoutePreview(generated) {
876
939
  }
877
940
  }
878
941
  for (const action of generated.actions) {
879
- if (action.type === "modify" && action.headers) {
942
+ if (action.type === "modify" && action.subType === "transform-request-path" && action.requestPath) {
943
+ output_manager_default.print(` ${import_chalk.default.cyan("Request Path:")}
944
+ `);
945
+ const env = action.requestPath.env?.length ? import_chalk.default.gray(` (env: ${action.requestPath.env.join(", ")})`) : "";
946
+ output_manager_default.print(
947
+ ` ${import_chalk.default.yellow(action.requestPath.op)} ${import_chalk.default.cyan("path")} = ${action.requestPath.value}${env}
948
+ `
949
+ );
950
+ } else if (action.type === "modify" && action.headers) {
880
951
  const label = action.subType === "response-headers" ? "Response Headers" : action.subType === "transform-request-header" ? "Request Headers" : "Request Query";
881
952
  output_manager_default.print(` ${import_chalk.default.cyan(`${label}:`)}
882
953
  `);
@@ -996,6 +1067,17 @@ function printRouteConfig(route) {
996
1067
  `);
997
1068
  for (const t of requestQuery) {
998
1069
  output_manager_default.print(` ${formatTransform(t)}
1070
+ `);
1071
+ }
1072
+ }
1073
+ const requestPaths = getTransformsByType(route, "request.path");
1074
+ if (requestPaths.length > 0) {
1075
+ output_manager_default.print(`
1076
+ ${import_chalk2.default.cyan("Request Path:")}
1077
+ `);
1078
+ for (const transform of requestPaths) {
1079
+ const env = transform.env?.length ? import_chalk2.default.gray(` (env: ${transform.env.join(", ")})`) : "";
1080
+ output_manager_default.print(` ${formatTransform(transform)}${env}
999
1081
  `);
1000
1082
  }
1001
1083
  }
@@ -1145,6 +1227,7 @@ async function runInteractiveEditLoop(client, route) {
1145
1227
  const responseHeaders = getAllResponseHeaders(route).length;
1146
1228
  const requestHeaders = getTransformsByType(route, "request.headers").length;
1147
1229
  const requestQuery = getTransformsByType(route, "request.query").length;
1230
+ const requestPaths = getTransformsByType(route, "request.path").length;
1148
1231
  const syntaxLabel = route.srcSyntax === "path-to-regexp" ? "Pattern" : route.srcSyntax === "equals" ? "Exact" : "Regex";
1149
1232
  const descriptionPreview = route.description ? route.description.length > 40 ? route.description.slice(0, 40) + "..." : route.description : "";
1150
1233
  const editChoices = [
@@ -1177,6 +1260,10 @@ async function runInteractiveEditLoop(client, route) {
1177
1260
  name: `Request Query (${requestQuery})`,
1178
1261
  value: "request-query"
1179
1262
  },
1263
+ {
1264
+ name: `Request Path (${requestPaths})`,
1265
+ value: "request-path"
1266
+ },
1180
1267
  { name: "Done - save changes", value: "done" }
1181
1268
  ];
1182
1269
  const choice = await client.input.select({
@@ -1220,6 +1307,9 @@ async function runInteractiveEditLoop(client, route) {
1220
1307
  "request-query"
1221
1308
  );
1222
1309
  break;
1310
+ case "request-path":
1311
+ await editRequestPaths(client, route);
1312
+ break;
1223
1313
  case "done":
1224
1314
  break;
1225
1315
  }
@@ -1688,6 +1778,91 @@ async function editTransformsByType(client, route, transformType, headerType) {
1688
1778
  }
1689
1779
  }
1690
1780
  }
1781
+ async function editRequestPaths(client, route) {
1782
+ for (; ; ) {
1783
+ const allTransforms = route.route.transforms ?? [];
1784
+ const matching = allTransforms.filter(
1785
+ (transform) => transform.type === "request.path"
1786
+ );
1787
+ if (matching.length > 0) {
1788
+ output_manager_default.print(`
1789
+ ${import_chalk2.default.cyan("Request Path:")}
1790
+ `);
1791
+ matching.forEach((transform, index) => {
1792
+ const env = transform.env?.length ? import_chalk2.default.gray(` (env: ${transform.env.join(", ")})`) : "";
1793
+ output_manager_default.print(
1794
+ ` ${import_chalk2.default.gray(`${index + 1}.`)} ${formatTransform(transform)}${env}
1795
+ `
1796
+ );
1797
+ });
1798
+ output_manager_default.print("\n");
1799
+ } else {
1800
+ output_manager_default.print("\n No request path transforms set.\n\n");
1801
+ }
1802
+ const choices = [];
1803
+ if (matching.length > 0) {
1804
+ choices.push({
1805
+ name: "Remove a request path transform",
1806
+ value: "remove"
1807
+ });
1808
+ }
1809
+ choices.push({ name: "Add a request path transform", value: "add" });
1810
+ choices.push({ name: "Back", value: "back" });
1811
+ const action = await client.input.select({
1812
+ message: "Request Path:",
1813
+ choices
1814
+ });
1815
+ if (action === "back")
1816
+ break;
1817
+ if (action === "remove") {
1818
+ const toRemove = await client.input.select({
1819
+ message: "Select request path transform to remove:",
1820
+ choices: [
1821
+ ...matching.map((transform, index) => ({
1822
+ name: formatTransform(transform),
1823
+ value: index
1824
+ })),
1825
+ { name: "Cancel", value: -1 }
1826
+ ]
1827
+ });
1828
+ if (toRemove !== -1) {
1829
+ let matchIndex = 0;
1830
+ const removeIndex = allTransforms.findIndex((transform) => {
1831
+ if (transform.type === "request.path") {
1832
+ if (matchIndex === toRemove)
1833
+ return true;
1834
+ matchIndex++;
1835
+ }
1836
+ return false;
1837
+ });
1838
+ if (removeIndex !== -1) {
1839
+ allTransforms.splice(removeIndex, 1);
1840
+ route.route.transforms = allTransforms;
1841
+ }
1842
+ }
1843
+ }
1844
+ if (action === "add") {
1845
+ const example = route.srcSyntax === "path-to-regexp" ? "/:path*" : route.srcSyntax === "regex" ? "/$1" : "/internal";
1846
+ const args = await client.input.text({
1847
+ message: `Runtime-visible request path (e.g., ${example}):`,
1848
+ validate: (value) => {
1849
+ if (!value.startsWith("/") || value.startsWith("//")) {
1850
+ return "Request path must be an origin-form path starting with a single `/`";
1851
+ }
1852
+ if (/[?#\s\x00-\x1f\x7f]/.test(value)) {
1853
+ return "Request path cannot contain a query, fragment, whitespace, or control characters";
1854
+ }
1855
+ return true;
1856
+ }
1857
+ });
1858
+ route.route.transforms = [
1859
+ ...allTransforms,
1860
+ { type: "request.path", op: "set", args }
1861
+ ];
1862
+ break;
1863
+ }
1864
+ }
1865
+ }
1691
1866
 
1692
1867
  export {
1693
1868
  parseConditions,