@vercel/config 0.0.10 → 0.0.12

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/cli.js CHANGED
@@ -28,7 +28,22 @@ const fs_1 = require("fs");
28
28
  const path_1 = require("path");
29
29
  const fs_2 = require("fs");
30
30
  /**
31
- * Read the user's vercel.ts file (or fallback to router.config.ts for backwards compatibility)
31
+ * Named exports that should NOT be auto-converted to config
32
+ * (these are route-based features that compile into the routes array, or internal module properties)
33
+ */
34
+ const ROUTE_BASED_EXPORTS = new Set([
35
+ 'default',
36
+ 'routes',
37
+ 'redirects',
38
+ 'rewrites',
39
+ 'headers',
40
+ 'crons',
41
+ 'env',
42
+ 'cacheControl',
43
+ '__esModule' // ES module metadata
44
+ ]);
45
+ /**
46
+ * Read the user's vercel.ts file and collect both default export and export const declarations
32
47
  */
33
48
  async function configureRouter() {
34
49
  var _a;
@@ -36,8 +51,22 @@ async function configureRouter() {
36
51
  const routerConfigPath = (0, path_1.resolve)(process.cwd(), "router.config.ts");
37
52
  // Prefer vercel.ts, fallback to router.config.ts
38
53
  const configPath = (0, fs_2.existsSync)(vercelTsPath) ? vercelTsPath : routerConfigPath;
39
- const routerConfig = (await (_a = configPath, Promise.resolve().then(() => __importStar(require(_a))))).default;
40
- return routerConfig;
54
+ // Import the entire module to get both default and named exports
55
+ const module = await (_a = configPath, Promise.resolve().then(() => __importStar(require(_a))));
56
+ // Start with the default export (router.getConfig())
57
+ const routerConfig = module.default || {};
58
+ // Auto-collect all export const declarations (except route-based ones)
59
+ const exportedConstants = {};
60
+ for (const [key, value] of Object.entries(module)) {
61
+ if (!ROUTE_BASED_EXPORTS.has(key)) {
62
+ exportedConstants[key] = value;
63
+ }
64
+ }
65
+ // Merge: export const declarations take precedence over default export
66
+ return {
67
+ ...routerConfig,
68
+ ...exportedConstants
69
+ };
41
70
  }
42
71
  /**
43
72
  * Read existing vercel.json and extract fields to preserve
package/dist/router.d.ts CHANGED
@@ -215,27 +215,28 @@ export interface Header {
215
215
  export interface TransformOptions {
216
216
  /**
217
217
  * Headers to set/modify on the incoming request.
218
- * Use param() for path parameters and runtimeEnv() for environment variables.
218
+ * Sets the key and value if missing.
219
219
  *
220
220
  * @example
221
221
  * requestHeaders: {
222
- * 'x-user-id': param('userId'),
223
- * 'authorization': `Bearer ${runtimeEnv('API_TOKEN')}`
222
+ * 'x-user-id': userId,
223
+ * 'authorization': `Bearer ${env.API_TOKEN}`
224
224
  * }
225
225
  */
226
226
  requestHeaders?: Record<string, string | string[]>;
227
227
  /**
228
228
  * Headers to set/modify on the outgoing response.
229
- * Use param() for path parameters and runtimeEnv() for environment variables.
229
+ * Sets the key and value if missing.
230
230
  *
231
231
  * @example
232
232
  * responseHeaders: {
233
- * 'x-post-id': param('postId')
233
+ * 'x-post-id': postId
234
234
  * }
235
235
  */
236
236
  responseHeaders?: Record<string, string | string[]>;
237
237
  /**
238
238
  * Query parameters to set/modify on the request.
239
+ * Sets the key and value if missing.
239
240
  *
240
241
  * @example
241
242
  * requestQuery: {
@@ -243,6 +244,60 @@ export interface TransformOptions {
243
244
  * }
244
245
  */
245
246
  requestQuery?: Record<string, string | string[]>;
247
+ /**
248
+ * Headers to append to the incoming request.
249
+ * Appends args to the value of the key, and will set if missing.
250
+ *
251
+ * @example
252
+ * appendRequestHeaders: {
253
+ * 'x-custom': 'value'
254
+ * }
255
+ */
256
+ appendRequestHeaders?: Record<string, string | string[]>;
257
+ /**
258
+ * Headers to append to the outgoing response.
259
+ * Appends args to the value of the key, and will set if missing.
260
+ *
261
+ * @example
262
+ * appendResponseHeaders: {
263
+ * 'x-custom': 'value'
264
+ * }
265
+ */
266
+ appendResponseHeaders?: Record<string, string | string[]>;
267
+ /**
268
+ * Query parameters to append to the request.
269
+ * Appends args to the value of the key, and will set if missing.
270
+ *
271
+ * @example
272
+ * appendRequestQuery: {
273
+ * 'tag': 'value'
274
+ * }
275
+ */
276
+ appendRequestQuery?: Record<string, string | string[]>;
277
+ /**
278
+ * Headers to delete from the incoming request.
279
+ * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key.
280
+ *
281
+ * @example
282
+ * deleteRequestHeaders: ['x-remove-this', 'x-remove-that']
283
+ */
284
+ deleteRequestHeaders?: string[];
285
+ /**
286
+ * Headers to delete from the outgoing response.
287
+ * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key.
288
+ *
289
+ * @example
290
+ * deleteResponseHeaders: ['x-powered-by']
291
+ */
292
+ deleteResponseHeaders?: string[];
293
+ /**
294
+ * Query parameters to delete from the request.
295
+ * Deletes the key entirely if args is not provided; otherwise, it will delete the value of args from the matching key.
296
+ *
297
+ * @example
298
+ * deleteRequestQuery: ['debug', 'trace']
299
+ */
300
+ deleteRequestQuery?: string[];
246
301
  }
247
302
  /**
248
303
  * HeaderRule defines one or more headers to set for requests
@@ -429,6 +484,8 @@ export declare class Router {
429
484
  private extractEnvVars;
430
485
  /**
431
486
  * Internal helper to convert TransformOptions to Transform array
487
+ * @param options Transform options to convert
488
+ * @param trackedEnvVars Optional set of environment variables that were accessed via the env proxy
432
489
  */
433
490
  private transformOptionsToTransforms;
434
491
  /**
@@ -460,6 +517,12 @@ export declare class Router {
460
517
  requestHeaders?: Record<string, string | string[]>;
461
518
  responseHeaders?: Record<string, string | string[]>;
462
519
  requestQuery?: Record<string, string | string[]>;
520
+ appendRequestHeaders?: Record<string, string | string[]>;
521
+ appendResponseHeaders?: Record<string, string | string[]>;
522
+ appendRequestQuery?: Record<string, string | string[]>;
523
+ deleteRequestHeaders?: string[];
524
+ deleteResponseHeaders?: string[];
525
+ deleteRequestQuery?: string[];
463
526
  } | ((params: Record<string, string> & {
464
527
  env: any;
465
528
  }) => {
@@ -468,6 +531,12 @@ export declare class Router {
468
531
  requestHeaders?: Record<string, string | string[]>;
469
532
  responseHeaders?: Record<string, string | string[]>;
470
533
  requestQuery?: Record<string, string | string[]>;
534
+ appendRequestHeaders?: Record<string, string | string[]>;
535
+ appendResponseHeaders?: Record<string, string | string[]>;
536
+ appendRequestQuery?: Record<string, string | string[]>;
537
+ deleteRequestHeaders?: string[];
538
+ deleteResponseHeaders?: string[];
539
+ deleteRequestQuery?: string[];
471
540
  })): this;
472
541
  /**
473
542
  * Loads rewrite rules asynchronously and appends them.
@@ -509,6 +578,12 @@ export declare class Router {
509
578
  requestHeaders?: Record<string, string | string[]>;
510
579
  responseHeaders?: Record<string, string | string[]>;
511
580
  requestQuery?: Record<string, string | string[]>;
581
+ appendRequestHeaders?: Record<string, string | string[]>;
582
+ appendResponseHeaders?: Record<string, string | string[]>;
583
+ appendRequestQuery?: Record<string, string | string[]>;
584
+ deleteRequestHeaders?: string[];
585
+ deleteResponseHeaders?: string[];
586
+ deleteRequestQuery?: string[];
512
587
  } | ((params: Record<string, string> & {
513
588
  env: any;
514
589
  }) => {
@@ -519,6 +594,12 @@ export declare class Router {
519
594
  requestHeaders?: Record<string, string | string[]>;
520
595
  responseHeaders?: Record<string, string | string[]>;
521
596
  requestQuery?: Record<string, string | string[]>;
597
+ appendRequestHeaders?: Record<string, string | string[]>;
598
+ appendResponseHeaders?: Record<string, string | string[]>;
599
+ appendRequestQuery?: Record<string, string | string[]>;
600
+ deleteRequestHeaders?: string[];
601
+ deleteResponseHeaders?: string[];
602
+ deleteRequestQuery?: string[];
522
603
  })): this;
523
604
  /**
524
605
  * Loads redirect rules asynchronously and appends them.
package/dist/router.js CHANGED
@@ -131,13 +131,26 @@ class Router {
131
131
  }
132
132
  /**
133
133
  * Internal helper to convert TransformOptions to Transform array
134
+ * @param options Transform options to convert
135
+ * @param trackedEnvVars Optional set of environment variables that were accessed via the env proxy
134
136
  */
135
- transformOptionsToTransforms(options) {
137
+ transformOptionsToTransforms(options, trackedEnvVars) {
136
138
  const transforms = [];
137
- // Convert requestHeaders
139
+ // Helper to get env vars for a value
140
+ const getEnvVars = (value) => {
141
+ if (trackedEnvVars) {
142
+ return Array.from(trackedEnvVars).filter(envVar => {
143
+ const valueStr = Array.isArray(value) ? value.join(' ') : value;
144
+ return valueStr.includes(`$${envVar}`);
145
+ });
146
+ }
147
+ return this.extractEnvVars(value);
148
+ };
149
+ // SET operations
150
+ // Convert requestHeaders (set)
138
151
  if (options.requestHeaders) {
139
152
  for (const [key, value] of Object.entries(options.requestHeaders)) {
140
- const envVars = this.extractEnvVars(value);
153
+ const envVars = getEnvVars(value);
141
154
  transforms.push({
142
155
  type: 'request.headers',
143
156
  op: 'set',
@@ -147,10 +160,10 @@ class Router {
147
160
  });
148
161
  }
149
162
  }
150
- // Convert responseHeaders
163
+ // Convert responseHeaders (set)
151
164
  if (options.responseHeaders) {
152
165
  for (const [key, value] of Object.entries(options.responseHeaders)) {
153
- const envVars = this.extractEnvVars(value);
166
+ const envVars = getEnvVars(value);
154
167
  transforms.push({
155
168
  type: 'response.headers',
156
169
  op: 'set',
@@ -160,10 +173,10 @@ class Router {
160
173
  });
161
174
  }
162
175
  }
163
- // Convert requestQuery
176
+ // Convert requestQuery (set)
164
177
  if (options.requestQuery) {
165
178
  for (const [key, value] of Object.entries(options.requestQuery)) {
166
- const envVars = this.extractEnvVars(value);
179
+ const envVars = getEnvVars(value);
167
180
  transforms.push({
168
181
  type: 'request.query',
169
182
  op: 'set',
@@ -173,6 +186,77 @@ class Router {
173
186
  });
174
187
  }
175
188
  }
189
+ // APPEND operations
190
+ // Convert appendRequestHeaders
191
+ if (options.appendRequestHeaders) {
192
+ for (const [key, value] of Object.entries(options.appendRequestHeaders)) {
193
+ const envVars = getEnvVars(value);
194
+ transforms.push({
195
+ type: 'request.headers',
196
+ op: 'append',
197
+ target: { key },
198
+ args: value,
199
+ ...(envVars.length > 0 && { env: envVars }),
200
+ });
201
+ }
202
+ }
203
+ // Convert appendResponseHeaders
204
+ if (options.appendResponseHeaders) {
205
+ for (const [key, value] of Object.entries(options.appendResponseHeaders)) {
206
+ const envVars = getEnvVars(value);
207
+ transforms.push({
208
+ type: 'response.headers',
209
+ op: 'append',
210
+ target: { key },
211
+ args: value,
212
+ ...(envVars.length > 0 && { env: envVars }),
213
+ });
214
+ }
215
+ }
216
+ // Convert appendRequestQuery
217
+ if (options.appendRequestQuery) {
218
+ for (const [key, value] of Object.entries(options.appendRequestQuery)) {
219
+ const envVars = getEnvVars(value);
220
+ transforms.push({
221
+ type: 'request.query',
222
+ op: 'append',
223
+ target: { key },
224
+ args: value,
225
+ ...(envVars.length > 0 && { env: envVars }),
226
+ });
227
+ }
228
+ }
229
+ // DELETE operations
230
+ // Convert deleteRequestHeaders
231
+ if (options.deleteRequestHeaders) {
232
+ for (const key of options.deleteRequestHeaders) {
233
+ transforms.push({
234
+ type: 'request.headers',
235
+ op: 'delete',
236
+ target: { key },
237
+ });
238
+ }
239
+ }
240
+ // Convert deleteResponseHeaders
241
+ if (options.deleteResponseHeaders) {
242
+ for (const key of options.deleteResponseHeaders) {
243
+ transforms.push({
244
+ type: 'response.headers',
245
+ op: 'delete',
246
+ target: { key },
247
+ });
248
+ }
249
+ }
250
+ // Convert deleteRequestQuery
251
+ if (options.deleteRequestQuery) {
252
+ for (const key of options.deleteRequestQuery) {
253
+ transforms.push({
254
+ type: 'request.query',
255
+ op: 'delete',
256
+ target: { key },
257
+ });
258
+ }
259
+ }
176
260
  return transforms;
177
261
  }
178
262
  /**
@@ -202,10 +286,12 @@ class Router {
202
286
  this.validateSourcePattern(source);
203
287
  (0, validation_1.validateCaptureGroupReferences)(source, destination);
204
288
  let options;
289
+ let trackedEnvVars;
205
290
  // Handle callback syntax
206
291
  if (typeof optionsOrCallback === 'function') {
207
292
  const pathParams = this.extractPathParams(source);
208
- const { proxy: envProxy } = this.createEnvProxy();
293
+ const { proxy: envProxy, accessedVars } = this.createEnvProxy();
294
+ trackedEnvVars = accessedVars;
209
295
  // Create params object with path parameters as $paramName
210
296
  const paramsObj = {};
211
297
  for (const param of pathParams) {
@@ -219,15 +305,24 @@ class Router {
219
305
  options = optionsOrCallback;
220
306
  }
221
307
  // Extract transform options
222
- const { requestHeaders, responseHeaders, requestQuery, has, missing } = options || {};
308
+ const { requestHeaders, responseHeaders, requestQuery, appendRequestHeaders, appendResponseHeaders, appendRequestQuery, deleteRequestHeaders, deleteResponseHeaders, deleteRequestQuery, has, missing } = options || {};
223
309
  const transformOpts = {
224
310
  requestHeaders,
225
311
  responseHeaders,
226
312
  requestQuery,
313
+ appendRequestHeaders,
314
+ appendResponseHeaders,
315
+ appendRequestQuery,
316
+ deleteRequestHeaders,
317
+ deleteResponseHeaders,
318
+ deleteRequestQuery,
227
319
  };
228
320
  // Convert to transforms if any transform options provided
229
- const transforms = requestHeaders || responseHeaders || requestQuery
230
- ? this.transformOptionsToTransforms(transformOpts)
321
+ const hasTransforms = requestHeaders || responseHeaders || requestQuery ||
322
+ appendRequestHeaders || appendResponseHeaders || appendRequestQuery ||
323
+ deleteRequestHeaders || deleteResponseHeaders || deleteRequestQuery;
324
+ const transforms = hasTransforms
325
+ ? this.transformOptionsToTransforms(transformOpts, trackedEnvVars)
231
326
  : undefined;
232
327
  this.rewriteRules.push({
233
328
  source,
@@ -296,10 +391,12 @@ class Router {
296
391
  this.validateSourcePattern(source);
297
392
  (0, validation_1.validateCaptureGroupReferences)(source, destination);
298
393
  let options;
394
+ let trackedEnvVars;
299
395
  // Handle callback syntax
300
396
  if (typeof optionsOrCallback === 'function') {
301
397
  const pathParams = this.extractPathParams(source);
302
- const { proxy: envProxy } = this.createEnvProxy();
398
+ const { proxy: envProxy, accessedVars } = this.createEnvProxy();
399
+ trackedEnvVars = accessedVars;
303
400
  // Create params object with path parameters as $paramName
304
401
  const paramsObj = {};
305
402
  for (const param of pathParams) {
@@ -313,15 +410,24 @@ class Router {
313
410
  options = optionsOrCallback;
314
411
  }
315
412
  // Extract transform options
316
- const { requestHeaders, responseHeaders, requestQuery, permanent, statusCode, has, missing, } = options || {};
413
+ const { requestHeaders, responseHeaders, requestQuery, appendRequestHeaders, appendResponseHeaders, appendRequestQuery, deleteRequestHeaders, deleteResponseHeaders, deleteRequestQuery, permanent, statusCode, has, missing, } = options || {};
317
414
  // If transforms are provided, create a route instead of a redirect
318
- if (requestHeaders || responseHeaders || requestQuery) {
415
+ const hasTransforms = requestHeaders || responseHeaders || requestQuery ||
416
+ appendRequestHeaders || appendResponseHeaders || appendRequestQuery ||
417
+ deleteRequestHeaders || deleteResponseHeaders || deleteRequestQuery;
418
+ if (hasTransforms) {
319
419
  const transformOpts = {
320
420
  requestHeaders,
321
421
  responseHeaders,
322
422
  requestQuery,
423
+ appendRequestHeaders,
424
+ appendResponseHeaders,
425
+ appendRequestQuery,
426
+ deleteRequestHeaders,
427
+ deleteResponseHeaders,
428
+ deleteRequestQuery,
323
429
  };
324
- const transforms = this.transformOptionsToTransforms(transformOpts);
430
+ const transforms = this.transformOptionsToTransforms(transformOpts, trackedEnvVars);
325
431
  this.routeRules.push({
326
432
  src: source,
327
433
  dest: destination,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/config",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "A TypeScript SDK for programmatically generating Vercel configuration files",
5
5
  "bugs": {
6
6
  "url": "https://github.com/vercel/router-sdk/issues"