@vercel/build-utils 2.12.3-canary.21 → 2.12.3-canary.22

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.
@@ -11,6 +11,8 @@ export declare function convertRuntimeToPlugin(buildRuntime: (options: BuildOpti
11
11
  vercelConfig: {
12
12
  functions?: BuilderFunctions;
13
13
  regions?: string[];
14
+ trailingSlash?: boolean;
15
+ cleanUrls?: boolean;
14
16
  };
15
17
  workPath: string;
16
18
  }) => Promise<void>;
@@ -30,11 +32,30 @@ export declare function updateFunctionsManifest({ vercelConfig, workPath, pages,
30
32
  };
31
33
  }): Promise<void>;
32
34
  /**
33
- * Will append routes to the `routes-manifest.json` file.
34
- * If the file does not exist, it'll be created.
35
+ * Append routes to the `routes-manifest.json` file.
36
+ * If the file does not exist, it will be created.
35
37
  */
36
- export declare function updateRoutesManifest({ workPath, dynamicRoutes, }: {
38
+ export declare function updateRoutesManifest({ workPath, redirects, rewrites, headers, dynamicRoutes, staticRoutes, }: {
37
39
  workPath: string;
40
+ redirects?: {
41
+ source: string;
42
+ destination: string;
43
+ statusCode: number;
44
+ regex: string;
45
+ }[];
46
+ rewrites?: {
47
+ source: string;
48
+ destination: string;
49
+ regex: string;
50
+ }[];
51
+ headers?: {
52
+ source: string;
53
+ headers: {
54
+ key: string;
55
+ value: string;
56
+ }[];
57
+ regex: string;
58
+ }[];
38
59
  dynamicRoutes?: {
39
60
  page: string;
40
61
  regex: string;
@@ -43,4 +64,12 @@ export declare function updateRoutesManifest({ workPath, dynamicRoutes, }: {
43
64
  [named: string]: string;
44
65
  };
45
66
  }[];
67
+ staticRoutes?: {
68
+ page: string;
69
+ regex: string;
70
+ namedRegex?: string;
71
+ routeKeys?: {
72
+ [named: string]: string;
73
+ };
74
+ }[];
46
75
  }): Promise<void>;
@@ -8,6 +8,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const path_1 = require("path");
9
9
  const glob_1 = __importDefault(require("./fs/glob"));
10
10
  const normalize_path_1 = require("./fs/normalize-path");
11
+ const detect_builders_1 = require("./detect-builders");
11
12
  const lambda_1 = require("./lambda");
12
13
  const minimatch_1 = __importDefault(require("minimatch"));
13
14
  /**
@@ -18,12 +19,13 @@ const minimatch_1 = __importDefault(require("minimatch"));
18
19
  function convertRuntimeToPlugin(buildRuntime, ext) {
19
20
  // This `build()` signature should match `plugin.build()` signature in `vercel build`.
20
21
  return async function build({ vercelConfig, workPath, }) {
22
+ var _a;
21
23
  const opts = { cwd: workPath };
22
24
  const files = await glob_1.default('**', opts);
23
25
  delete files['vercel.json']; // Builders/Runtimes didn't have vercel.json
24
26
  const entrypoints = await glob_1.default(`api/**/*${ext}`, opts);
25
27
  const pages = {};
26
- const { functions = {} } = vercelConfig;
28
+ const { functions = {}, cleanUrls, trailingSlash } = vercelConfig;
27
29
  const traceDir = path_1.join(workPath, '.output', 'runtime-traced-files');
28
30
  await fs_extra_1.default.ensureDir(traceDir);
29
31
  for (const entrypoint of Object.keys(entrypoints)) {
@@ -80,6 +82,53 @@ function convertRuntimeToPlugin(buildRuntime, ext) {
80
82
  await fs_extra_1.default.writeFile(nft, json);
81
83
  }
82
84
  await updateFunctionsManifest({ vercelConfig, workPath, pages });
85
+ const { warnings, errors,
86
+ //defaultRoutes,
87
+ redirectRoutes,
88
+ //rewriteRoutes,
89
+ dynamicRoutesWithKeys,
90
+ // errorRoutes, already handled by pages404
91
+ } = await detect_builders_1.detectBuilders(Object.keys(files), null, {
92
+ tag: 'latest',
93
+ functions: functions,
94
+ projectSettings: undefined,
95
+ featHandleMiss: true,
96
+ cleanUrls,
97
+ trailingSlash,
98
+ });
99
+ if (errors) {
100
+ throw new Error(errors[0].message);
101
+ }
102
+ if (warnings) {
103
+ warnings.forEach(warning => console.warn(warning.message, warning.link));
104
+ }
105
+ const redirects = (_a = redirectRoutes === null || redirectRoutes === void 0 ? void 0 : redirectRoutes.filter(r => r.src && 'headers' in r)) === null || _a === void 0 ? void 0 : _a.map(r => {
106
+ var _a;
107
+ return ({
108
+ source: r.src || '',
109
+ destination: 'headers' in r && ((_a = r.headers) === null || _a === void 0 ? void 0 : _a.Location) ? r.headers.Location : '',
110
+ statusCode: 'status' in r && r.status ? r.status : 307,
111
+ regex: r.src || '',
112
+ });
113
+ });
114
+ const dynamicRoutes = dynamicRoutesWithKeys === null || dynamicRoutesWithKeys === void 0 ? void 0 : dynamicRoutesWithKeys.map(r => {
115
+ const keys = Object.keys(r.routeKeys);
116
+ return {
117
+ page: '/' + r.fileName.slice(0, -ext.length),
118
+ regex: r.regex,
119
+ routeKeys: r.routeKeys,
120
+ namedRegex: r.regex
121
+ .split('([^/]+)')
122
+ .map((str, i) => str + (keys[i] ? `(?<${keys[i]}>[^/]+)` : ''))
123
+ .join(''),
124
+ };
125
+ });
126
+ await updateRoutesManifest({
127
+ workPath,
128
+ redirects,
129
+ rewrites: [],
130
+ dynamicRoutes,
131
+ });
83
132
  };
84
133
  }
85
134
  exports.convertRuntimeToPlugin = convertRuntimeToPlugin;
@@ -133,21 +182,41 @@ async function updateFunctionsManifest({ vercelConfig, workPath, pages, }) {
133
182
  }
134
183
  exports.updateFunctionsManifest = updateFunctionsManifest;
135
184
  /**
136
- * Will append routes to the `routes-manifest.json` file.
137
- * If the file does not exist, it'll be created.
185
+ * Append routes to the `routes-manifest.json` file.
186
+ * If the file does not exist, it will be created.
138
187
  */
139
- async function updateRoutesManifest({ workPath, dynamicRoutes, }) {
188
+ async function updateRoutesManifest({ workPath, redirects, rewrites, headers, dynamicRoutes, staticRoutes, }) {
140
189
  const routesManifestPath = path_1.join(workPath, '.output', 'routes-manifest.json');
141
190
  const routesManifest = await readJson(routesManifestPath);
142
191
  if (!routesManifest.version)
143
- routesManifest.version = 1;
192
+ routesManifest.version = 3;
144
193
  if (routesManifest.pages404 === undefined)
145
194
  routesManifest.pages404 = true;
195
+ if (redirects) {
196
+ if (!routesManifest.redirects)
197
+ routesManifest.redirects = [];
198
+ routesManifest.redirects.push(...redirects);
199
+ }
200
+ if (rewrites) {
201
+ if (!routesManifest.rewrites)
202
+ routesManifest.rewrites = [];
203
+ routesManifest.rewrites.push(...rewrites);
204
+ }
205
+ if (headers) {
206
+ if (!routesManifest.headers)
207
+ routesManifest.headers = [];
208
+ routesManifest.headers.push(...headers);
209
+ }
146
210
  if (dynamicRoutes) {
147
211
  if (!routesManifest.dynamicRoutes)
148
212
  routesManifest.dynamicRoutes = [];
149
213
  routesManifest.dynamicRoutes.push(...dynamicRoutes);
150
214
  }
215
+ if (staticRoutes) {
216
+ if (!routesManifest.staticRoutes)
217
+ routesManifest.staticRoutes = [];
218
+ routesManifest.staticRoutes.push(...staticRoutes);
219
+ }
151
220
  await fs_extra_1.default.writeFile(routesManifestPath, JSON.stringify(routesManifest));
152
221
  }
153
222
  exports.updateRoutesManifest = updateRoutesManifest;
@@ -6,6 +6,13 @@ interface ErrorResponse {
6
6
  action?: string;
7
7
  link?: string;
8
8
  }
9
+ interface DynamicRoutesWithKeys {
10
+ fileName: string;
11
+ regex: string;
12
+ routeKeys: {
13
+ [key: string]: string;
14
+ };
15
+ }
9
16
  interface Options {
10
17
  tag?: 'canary' | 'latest' | string;
11
18
  functions?: BuilderFunctions;
@@ -34,5 +41,6 @@ export declare function detectBuilders(files: string[], pkg?: PackageJson | unde
34
41
  redirectRoutes: Route[] | null;
35
42
  rewriteRoutes: Route[] | null;
36
43
  errorRoutes: Route[] | null;
44
+ dynamicRoutesWithKeys: DynamicRoutesWithKeys[] | null;
37
45
  }>;
38
46
  export {};
@@ -66,6 +66,7 @@ async function detectBuilders(files, pkg, options = {}) {
66
66
  redirectRoutes: null,
67
67
  rewriteRoutes: null,
68
68
  errorRoutes: null,
69
+ dynamicRoutesWithKeys: null,
69
70
  };
70
71
  }
71
72
  const sortedFiles = files.sort(sortFiles);
@@ -99,11 +100,12 @@ async function detectBuilders(files, pkg, options = {}) {
99
100
  let fallbackEntrypoint = null;
100
101
  const apiRoutes = [];
101
102
  const dynamicRoutes = [];
103
+ const dynamicRoutesWithKeys = [];
102
104
  // API
103
105
  for (const fileName of sortedFiles) {
104
106
  const apiBuilder = maybeGetApiBuilder(fileName, apiMatches, options);
105
107
  if (apiBuilder) {
106
- const { routeError, apiRoute, isDynamic } = getApiRoute(fileName, apiSortedFiles, options, absolutePathCache);
108
+ const { routeError, apiRoute, isDynamic, routeKeys } = getApiRoute(fileName, apiSortedFiles, options, absolutePathCache);
107
109
  if (routeError) {
108
110
  return {
109
111
  builders: null,
@@ -113,12 +115,18 @@ async function detectBuilders(files, pkg, options = {}) {
113
115
  redirectRoutes: null,
114
116
  rewriteRoutes: null,
115
117
  errorRoutes: null,
118
+ dynamicRoutesWithKeys: null,
116
119
  };
117
120
  }
118
121
  if (apiRoute) {
119
122
  apiRoutes.push(apiRoute);
120
123
  if (isDynamic) {
121
124
  dynamicRoutes.push(apiRoute);
125
+ dynamicRoutesWithKeys.push({
126
+ fileName,
127
+ regex: apiRoute.src,
128
+ routeKeys,
129
+ });
122
130
  }
123
131
  }
124
132
  addToUsedFunctions(apiBuilder);
@@ -167,6 +175,7 @@ async function detectBuilders(files, pkg, options = {}) {
167
175
  defaultRoutes: null,
168
176
  rewriteRoutes: null,
169
177
  errorRoutes: null,
178
+ dynamicRoutesWithKeys: null,
170
179
  };
171
180
  }
172
181
  // If `outputDirectory` is an empty string,
@@ -203,6 +212,7 @@ async function detectBuilders(files, pkg, options = {}) {
203
212
  defaultRoutes: null,
204
213
  rewriteRoutes: null,
205
214
  errorRoutes: null,
215
+ dynamicRoutesWithKeys: null,
206
216
  };
207
217
  }
208
218
  const builders = [];
@@ -230,6 +240,7 @@ async function detectBuilders(files, pkg, options = {}) {
230
240
  defaultRoutes: routesResult.defaultRoutes,
231
241
  rewriteRoutes: routesResult.rewriteRoutes,
232
242
  errorRoutes: routesResult.errorRoutes,
243
+ dynamicRoutesWithKeys,
233
244
  };
234
245
  }
235
246
  exports.detectBuilders = detectBuilders;
@@ -484,6 +495,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
484
495
  return {
485
496
  apiRoute: null,
486
497
  isDynamic: false,
498
+ routeKeys: {},
487
499
  routeError: {
488
500
  code: 'conflicting_path_segment',
489
501
  message: `The segment "${conflictingSegment}" occurs more than ` +
@@ -498,6 +510,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
498
510
  return {
499
511
  apiRoute: null,
500
512
  isDynamic: false,
513
+ routeKeys: {},
501
514
  routeError: {
502
515
  code: 'conflicting_file_path',
503
516
  message: `Two or more files have conflicting paths or names. ` +
@@ -510,6 +523,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
510
523
  return {
511
524
  apiRoute: out.route,
512
525
  isDynamic: out.isDynamic,
526
+ routeKeys: out.routeKeys,
513
527
  routeError: null,
514
528
  };
515
529
  }
@@ -619,6 +633,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
619
633
  const parts = filePath.split('/');
620
634
  let counter = 1;
621
635
  const query = [];
636
+ const routeKeys = {};
622
637
  let isDynamic = false;
623
638
  const srcParts = parts.map((segment, i) => {
624
639
  const name = getSegmentName(segment);
@@ -626,6 +641,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
626
641
  if (name !== null) {
627
642
  // We can't use `URLSearchParams` because `$` would get escaped
628
643
  query.push(`${name}=$${counter++}`);
644
+ routeKeys[name] = name;
629
645
  isDynamic = true;
630
646
  return `([^/]+)`;
631
647
  }
@@ -668,7 +684,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
668
684
  dest: `/${filePath}${queryString}`,
669
685
  };
670
686
  }
671
- return { route, isDynamic };
687
+ return { route, isDynamic, routeKeys };
672
688
  }
673
689
  function getRouteResult(apiRoutes, dynamicRoutes, outputDirectory, apiBuilders, frontendBuilder, options) {
674
690
  var _a, _b;
package/dist/index.js CHANGED
@@ -32285,6 +32285,7 @@ const fs_extra_1 = __importDefault(__webpack_require__(5392));
32285
32285
  const path_1 = __webpack_require__(5622);
32286
32286
  const glob_1 = __importDefault(__webpack_require__(4240));
32287
32287
  const normalize_path_1 = __webpack_require__(6261);
32288
+ const detect_builders_1 = __webpack_require__(4246);
32288
32289
  const lambda_1 = __webpack_require__(6721);
32289
32290
  const minimatch_1 = __importDefault(__webpack_require__(9566));
32290
32291
  /**
@@ -32295,12 +32296,13 @@ const minimatch_1 = __importDefault(__webpack_require__(9566));
32295
32296
  function convertRuntimeToPlugin(buildRuntime, ext) {
32296
32297
  // This `build()` signature should match `plugin.build()` signature in `vercel build`.
32297
32298
  return async function build({ vercelConfig, workPath, }) {
32299
+ var _a;
32298
32300
  const opts = { cwd: workPath };
32299
32301
  const files = await glob_1.default('**', opts);
32300
32302
  delete files['vercel.json']; // Builders/Runtimes didn't have vercel.json
32301
32303
  const entrypoints = await glob_1.default(`api/**/*${ext}`, opts);
32302
32304
  const pages = {};
32303
- const { functions = {} } = vercelConfig;
32305
+ const { functions = {}, cleanUrls, trailingSlash } = vercelConfig;
32304
32306
  const traceDir = path_1.join(workPath, '.output', 'runtime-traced-files');
32305
32307
  await fs_extra_1.default.ensureDir(traceDir);
32306
32308
  for (const entrypoint of Object.keys(entrypoints)) {
@@ -32357,6 +32359,53 @@ function convertRuntimeToPlugin(buildRuntime, ext) {
32357
32359
  await fs_extra_1.default.writeFile(nft, json);
32358
32360
  }
32359
32361
  await updateFunctionsManifest({ vercelConfig, workPath, pages });
32362
+ const { warnings, errors,
32363
+ //defaultRoutes,
32364
+ redirectRoutes,
32365
+ //rewriteRoutes,
32366
+ dynamicRoutesWithKeys,
32367
+ // errorRoutes, already handled by pages404
32368
+ } = await detect_builders_1.detectBuilders(Object.keys(files), null, {
32369
+ tag: 'latest',
32370
+ functions: functions,
32371
+ projectSettings: undefined,
32372
+ featHandleMiss: true,
32373
+ cleanUrls,
32374
+ trailingSlash,
32375
+ });
32376
+ if (errors) {
32377
+ throw new Error(errors[0].message);
32378
+ }
32379
+ if (warnings) {
32380
+ warnings.forEach(warning => console.warn(warning.message, warning.link));
32381
+ }
32382
+ const redirects = (_a = redirectRoutes === null || redirectRoutes === void 0 ? void 0 : redirectRoutes.filter(r => r.src && 'headers' in r)) === null || _a === void 0 ? void 0 : _a.map(r => {
32383
+ var _a;
32384
+ return ({
32385
+ source: r.src || '',
32386
+ destination: 'headers' in r && ((_a = r.headers) === null || _a === void 0 ? void 0 : _a.Location) ? r.headers.Location : '',
32387
+ statusCode: 'status' in r && r.status ? r.status : 307,
32388
+ regex: r.src || '',
32389
+ });
32390
+ });
32391
+ const dynamicRoutes = dynamicRoutesWithKeys === null || dynamicRoutesWithKeys === void 0 ? void 0 : dynamicRoutesWithKeys.map(r => {
32392
+ const keys = Object.keys(r.routeKeys);
32393
+ return {
32394
+ page: '/' + r.fileName.slice(0, -ext.length),
32395
+ regex: r.regex,
32396
+ routeKeys: r.routeKeys,
32397
+ namedRegex: r.regex
32398
+ .split('([^/]+)')
32399
+ .map((str, i) => str + (keys[i] ? `(?<${keys[i]}>[^/]+)` : ''))
32400
+ .join(''),
32401
+ };
32402
+ });
32403
+ await updateRoutesManifest({
32404
+ workPath,
32405
+ redirects,
32406
+ rewrites: [],
32407
+ dynamicRoutes,
32408
+ });
32360
32409
  };
32361
32410
  }
32362
32411
  exports.convertRuntimeToPlugin = convertRuntimeToPlugin;
@@ -32410,21 +32459,41 @@ async function updateFunctionsManifest({ vercelConfig, workPath, pages, }) {
32410
32459
  }
32411
32460
  exports.updateFunctionsManifest = updateFunctionsManifest;
32412
32461
  /**
32413
- * Will append routes to the `routes-manifest.json` file.
32414
- * If the file does not exist, it'll be created.
32462
+ * Append routes to the `routes-manifest.json` file.
32463
+ * If the file does not exist, it will be created.
32415
32464
  */
32416
- async function updateRoutesManifest({ workPath, dynamicRoutes, }) {
32465
+ async function updateRoutesManifest({ workPath, redirects, rewrites, headers, dynamicRoutes, staticRoutes, }) {
32417
32466
  const routesManifestPath = path_1.join(workPath, '.output', 'routes-manifest.json');
32418
32467
  const routesManifest = await readJson(routesManifestPath);
32419
32468
  if (!routesManifest.version)
32420
- routesManifest.version = 1;
32469
+ routesManifest.version = 3;
32421
32470
  if (routesManifest.pages404 === undefined)
32422
32471
  routesManifest.pages404 = true;
32472
+ if (redirects) {
32473
+ if (!routesManifest.redirects)
32474
+ routesManifest.redirects = [];
32475
+ routesManifest.redirects.push(...redirects);
32476
+ }
32477
+ if (rewrites) {
32478
+ if (!routesManifest.rewrites)
32479
+ routesManifest.rewrites = [];
32480
+ routesManifest.rewrites.push(...rewrites);
32481
+ }
32482
+ if (headers) {
32483
+ if (!routesManifest.headers)
32484
+ routesManifest.headers = [];
32485
+ routesManifest.headers.push(...headers);
32486
+ }
32423
32487
  if (dynamicRoutes) {
32424
32488
  if (!routesManifest.dynamicRoutes)
32425
32489
  routesManifest.dynamicRoutes = [];
32426
32490
  routesManifest.dynamicRoutes.push(...dynamicRoutes);
32427
32491
  }
32492
+ if (staticRoutes) {
32493
+ if (!routesManifest.staticRoutes)
32494
+ routesManifest.staticRoutes = [];
32495
+ routesManifest.staticRoutes.push(...staticRoutes);
32496
+ }
32428
32497
  await fs_extra_1.default.writeFile(routesManifestPath, JSON.stringify(routesManifest));
32429
32498
  }
32430
32499
  exports.updateRoutesManifest = updateRoutesManifest;
@@ -32521,6 +32590,7 @@ async function detectBuilders(files, pkg, options = {}) {
32521
32590
  redirectRoutes: null,
32522
32591
  rewriteRoutes: null,
32523
32592
  errorRoutes: null,
32593
+ dynamicRoutesWithKeys: null,
32524
32594
  };
32525
32595
  }
32526
32596
  const sortedFiles = files.sort(sortFiles);
@@ -32554,11 +32624,12 @@ async function detectBuilders(files, pkg, options = {}) {
32554
32624
  let fallbackEntrypoint = null;
32555
32625
  const apiRoutes = [];
32556
32626
  const dynamicRoutes = [];
32627
+ const dynamicRoutesWithKeys = [];
32557
32628
  // API
32558
32629
  for (const fileName of sortedFiles) {
32559
32630
  const apiBuilder = maybeGetApiBuilder(fileName, apiMatches, options);
32560
32631
  if (apiBuilder) {
32561
- const { routeError, apiRoute, isDynamic } = getApiRoute(fileName, apiSortedFiles, options, absolutePathCache);
32632
+ const { routeError, apiRoute, isDynamic, routeKeys } = getApiRoute(fileName, apiSortedFiles, options, absolutePathCache);
32562
32633
  if (routeError) {
32563
32634
  return {
32564
32635
  builders: null,
@@ -32568,12 +32639,18 @@ async function detectBuilders(files, pkg, options = {}) {
32568
32639
  redirectRoutes: null,
32569
32640
  rewriteRoutes: null,
32570
32641
  errorRoutes: null,
32642
+ dynamicRoutesWithKeys: null,
32571
32643
  };
32572
32644
  }
32573
32645
  if (apiRoute) {
32574
32646
  apiRoutes.push(apiRoute);
32575
32647
  if (isDynamic) {
32576
32648
  dynamicRoutes.push(apiRoute);
32649
+ dynamicRoutesWithKeys.push({
32650
+ fileName,
32651
+ regex: apiRoute.src,
32652
+ routeKeys,
32653
+ });
32577
32654
  }
32578
32655
  }
32579
32656
  addToUsedFunctions(apiBuilder);
@@ -32622,6 +32699,7 @@ async function detectBuilders(files, pkg, options = {}) {
32622
32699
  defaultRoutes: null,
32623
32700
  rewriteRoutes: null,
32624
32701
  errorRoutes: null,
32702
+ dynamicRoutesWithKeys: null,
32625
32703
  };
32626
32704
  }
32627
32705
  // If `outputDirectory` is an empty string,
@@ -32658,6 +32736,7 @@ async function detectBuilders(files, pkg, options = {}) {
32658
32736
  defaultRoutes: null,
32659
32737
  rewriteRoutes: null,
32660
32738
  errorRoutes: null,
32739
+ dynamicRoutesWithKeys: null,
32661
32740
  };
32662
32741
  }
32663
32742
  const builders = [];
@@ -32685,6 +32764,7 @@ async function detectBuilders(files, pkg, options = {}) {
32685
32764
  defaultRoutes: routesResult.defaultRoutes,
32686
32765
  rewriteRoutes: routesResult.rewriteRoutes,
32687
32766
  errorRoutes: routesResult.errorRoutes,
32767
+ dynamicRoutesWithKeys,
32688
32768
  };
32689
32769
  }
32690
32770
  exports.detectBuilders = detectBuilders;
@@ -32939,6 +33019,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
32939
33019
  return {
32940
33020
  apiRoute: null,
32941
33021
  isDynamic: false,
33022
+ routeKeys: {},
32942
33023
  routeError: {
32943
33024
  code: 'conflicting_path_segment',
32944
33025
  message: `The segment "${conflictingSegment}" occurs more than ` +
@@ -32953,6 +33034,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
32953
33034
  return {
32954
33035
  apiRoute: null,
32955
33036
  isDynamic: false,
33037
+ routeKeys: {},
32956
33038
  routeError: {
32957
33039
  code: 'conflicting_file_path',
32958
33040
  message: `Two or more files have conflicting paths or names. ` +
@@ -32965,6 +33047,7 @@ function getApiRoute(fileName, sortedFiles, options, absolutePathCache) {
32965
33047
  return {
32966
33048
  apiRoute: out.route,
32967
33049
  isDynamic: out.isDynamic,
33050
+ routeKeys: out.routeKeys,
32968
33051
  routeError: null,
32969
33052
  };
32970
33053
  }
@@ -33074,6 +33157,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
33074
33157
  const parts = filePath.split('/');
33075
33158
  let counter = 1;
33076
33159
  const query = [];
33160
+ const routeKeys = {};
33077
33161
  let isDynamic = false;
33078
33162
  const srcParts = parts.map((segment, i) => {
33079
33163
  const name = getSegmentName(segment);
@@ -33081,6 +33165,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
33081
33165
  if (name !== null) {
33082
33166
  // We can't use `URLSearchParams` because `$` would get escaped
33083
33167
  query.push(`${name}=$${counter++}`);
33168
+ routeKeys[name] = name;
33084
33169
  isDynamic = true;
33085
33170
  return `([^/]+)`;
33086
33171
  }
@@ -33123,7 +33208,7 @@ function createRouteFromPath(filePath, featHandleMiss, cleanUrls) {
33123
33208
  dest: `/${filePath}${queryString}`,
33124
33209
  };
33125
33210
  }
33126
- return { route, isDynamic };
33211
+ return { route, isDynamic, routeKeys };
33127
33212
  }
33128
33213
  function getRouteResult(apiRoutes, dynamicRoutes, outputDirectory, apiBuilders, frontendBuilder, options) {
33129
33214
  var _a, _b;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/build-utils",
3
- "version": "2.12.3-canary.21",
3
+ "version": "2.12.3-canary.22",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.js",
@@ -49,5 +49,5 @@
49
49
  "typescript": "4.3.4",
50
50
  "yazl": "2.4.3"
51
51
  },
52
- "gitHead": "cc7b2691c1d43ecb19f1dd6e88f29137d85da61a"
52
+ "gitHead": "0cacb1bdace342133fad4bd7a98354e5b2948df0"
53
53
  }