@vercel/config 0.0.14 → 0.0.17
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/README.md +60 -306
- package/dist/cli.js +57 -28
- package/dist/router.d.ts +35 -97
- package/dist/router.js +117 -301
- package/dist/types.d.ts +61 -3
- package/dist/types.js +5 -0
- package/dist/utils/validation.d.ts +27 -0
- package/dist/utils/validation.js +96 -1
- package/dist/v1/index.d.ts +5 -0
- package/dist/v1/index.js +29 -0
- package/package.json +13 -3
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -21
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @vercel/config
|
|
2
2
|
|
|
3
|
-
TypeScript SDK for defining Vercel configuration
|
|
3
|
+
TypeScript SDK for programmatically defining Vercel configuration. Write type-safe routing rules and build configuration in TypeScript instead of JSON.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,338 +8,92 @@ TypeScript SDK for defining Vercel configuration programmatically.
|
|
|
8
8
|
npm install @vercel/config
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Quick Start
|
|
12
12
|
|
|
13
13
|
Create a `vercel.ts` file in your project root:
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
import { createRouter } from '@vercel/config';
|
|
17
|
+
import type { VercelConfig } from '@vercel/config';
|
|
17
18
|
|
|
18
19
|
const router = createRouter();
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
router.cleanUrls = true;
|
|
43
|
-
router.trailingSlash = true;
|
|
44
|
-
|
|
45
|
-
// Bulk redirects
|
|
46
|
-
router.bulkRedirectsPath = './bulkRedirectsDemo.json';
|
|
47
|
-
|
|
48
|
-
// Cron jobs
|
|
49
|
-
router.cron('/api/cleanup', '0 0 * * *');
|
|
50
|
-
|
|
51
|
-
export default router.getConfig();
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Automatic Compilation
|
|
55
|
-
|
|
56
|
-
Your `vercel.ts` file is automatically compiled when you run:
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
vercel build # For local builds
|
|
60
|
-
vercel dev # For local development
|
|
61
|
-
vercel deploy # For deployment
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
The Vercel CLI automatically compiles `vercel.ts` to `.vercel/vercel.json` before building or deploying.
|
|
65
|
-
|
|
66
|
-
## API Reference
|
|
67
|
-
|
|
68
|
-
### `createRouter()`
|
|
69
|
-
|
|
70
|
-
Creates a new router instance.
|
|
71
|
-
|
|
72
|
-
### `router.rewrite(source, destination, options?)`
|
|
73
|
-
|
|
74
|
-
Add a rewrite rule. Options can be an object or a callback function that receives path parameters and environment variables.
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
// With callback for transforms
|
|
78
|
-
router.rewrite('/users/:userId', 'https://api.example.com/users/$1', ({userId, env}) => ({
|
|
79
|
-
requestHeaders: {
|
|
80
|
-
'x-user-id': userId,
|
|
81
|
-
'authorization': `Bearer ${env.API_TOKEN}`
|
|
82
|
-
},
|
|
83
|
-
responseHeaders: {
|
|
84
|
-
'x-powered-by': 'My API'
|
|
85
|
-
},
|
|
86
|
-
requestQuery: {
|
|
87
|
-
'version': '2.0'
|
|
88
|
-
}
|
|
89
|
-
}));
|
|
90
|
-
|
|
91
|
-
// Simple rewrite without transforms
|
|
92
|
-
router.rewrite('/api/(.*)', 'https://backend.com/$1');
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### `router.redirect(source, destination, options?)`
|
|
96
|
-
|
|
97
|
-
Add a redirect rule. Options include `permanent` and `statusCode`.
|
|
98
|
-
|
|
99
|
-
```typescript
|
|
100
|
-
router.redirect('/old-page', '/new-page', { permanent: true });
|
|
101
|
-
router.redirect('/temp', '/elsewhere', { statusCode: 302 });
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### `router.header(source, headers, options?)`
|
|
105
|
-
|
|
106
|
-
Add custom headers for a path pattern.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
router.header('/api/(.*)', [
|
|
110
|
-
{ key: 'X-Custom-Header', value: 'value' }
|
|
111
|
-
]);
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### `router.cacheControl(source, options)`
|
|
115
|
-
|
|
116
|
-
Set cache control headers. Options include `public`, `private`, `maxAge`, `sMaxAge`, `immutable`, etc.
|
|
117
|
-
|
|
118
|
-
```typescript
|
|
119
|
-
router.cacheControl('/static/(.*)', {
|
|
120
|
-
public: true,
|
|
121
|
-
maxAge: '1 week',
|
|
122
|
-
immutable: true
|
|
123
|
-
});
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### `router.cleanUrls`
|
|
127
|
-
|
|
128
|
-
Set whether to enable clean URLs (removes file extensions).
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
router.cleanUrls = true;
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
### `router.trailingSlash`
|
|
135
|
-
|
|
136
|
-
Set whether to normalize paths to include trailing slashes.
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
router.trailingSlash = true;
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### `router.bulkRedirectsPath`
|
|
143
|
-
|
|
144
|
-
Set the path to a bulk redirects JSON file.
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
router.bulkRedirectsPath = './bulkRedirectsDemo.json';
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
## Conditional Routing
|
|
151
|
-
|
|
152
|
-
The SDK supports powerful conditional routing using `has` and `missing` conditions. These conditions can be added to rewrites, redirects, headers, and cache control rules.
|
|
153
|
-
|
|
154
|
-
### Condition Types
|
|
155
|
-
|
|
156
|
-
- `header`: Match HTTP headers
|
|
157
|
-
- `cookie`: Match cookies
|
|
158
|
-
- `host`: Match the request host
|
|
159
|
-
- `query`: Match query parameters
|
|
160
|
-
- `path`: Match the request path pattern
|
|
161
|
-
|
|
162
|
-
### Simple Presence Check
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// Only rewrite if x-api-key header exists
|
|
166
|
-
router.rewrite('/api/(.*)', 'https://backend.com/$1', {
|
|
167
|
-
has: [
|
|
168
|
-
{ type: 'header', key: 'x-api-key' }
|
|
169
|
-
]
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Redirect if auth-token cookie is missing
|
|
173
|
-
router.redirect('/dashboard', '/login', {
|
|
174
|
-
missing: [
|
|
175
|
-
{ type: 'cookie', key: 'auth-token' }
|
|
176
|
-
]
|
|
177
|
-
});
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Conditional Operators
|
|
181
|
-
|
|
182
|
-
The SDK supports advanced matching operators for more complex conditions:
|
|
183
|
-
|
|
184
|
-
#### Equality Operators
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
// Exact match using 'eq'
|
|
188
|
-
router.rewrite('/api/(.*)', 'https://backend.com/$1', {
|
|
189
|
-
has: [
|
|
190
|
-
{ type: 'header', key: 'x-api-version', eq: 'v2' }
|
|
191
|
-
]
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Not equal using 'neq'
|
|
195
|
-
router.redirect('/beta/(.*)', '/stable/$1', {
|
|
196
|
-
has: [
|
|
197
|
-
{ type: 'cookie', key: 'beta-access', neq: 'granted' }
|
|
198
|
-
]
|
|
199
|
-
});
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
#### Inclusion Operators
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
// Must be one of (inclusion)
|
|
206
|
-
router.rewrite('/admin/(.*)', 'https://admin.backend.com/$1', {
|
|
207
|
-
has: [
|
|
208
|
-
{ type: 'header', key: 'x-user-role', inc: ['admin', 'moderator', 'superuser'] }
|
|
209
|
-
]
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// Must NOT be one of (non-inclusion)
|
|
213
|
-
router.redirect('/public/(.*)', '/private/$1', {
|
|
214
|
-
has: [
|
|
215
|
-
{ type: 'header', key: 'x-user-role', ninc: ['guest', 'anonymous'] }
|
|
216
|
-
]
|
|
217
|
-
});
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
#### String Pattern Operators
|
|
21
|
+
export const config: VercelConfig = {
|
|
22
|
+
buildCommand: 'npm run build',
|
|
23
|
+
framework: 'nextjs',
|
|
24
|
+
|
|
25
|
+
rewrites: [
|
|
26
|
+
// Simple rewrite
|
|
27
|
+
router.rewrite('/api/(.*)', 'https://backend.api.example.com/$1'),
|
|
28
|
+
|
|
29
|
+
// Rewrite with transforms
|
|
30
|
+
router.rewrite('/users/:userId', 'https://api.example.com/users/$1',
|
|
31
|
+
({ userId, env }) => ({
|
|
32
|
+
requestHeaders: {
|
|
33
|
+
'x-user-id': userId,
|
|
34
|
+
'authorization': `Bearer ${env.API_TOKEN}`
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
],
|
|
39
|
+
|
|
40
|
+
redirects: [
|
|
41
|
+
router.redirect('/old-docs', '/docs', { permanent: true })
|
|
42
|
+
],
|
|
221
43
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
44
|
+
headers: [
|
|
45
|
+
router.cacheControl('/static/(.*)', {
|
|
46
|
+
public: true,
|
|
47
|
+
maxAge: '1 week',
|
|
48
|
+
immutable: true
|
|
49
|
+
})
|
|
50
|
+
],
|
|
229
51
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
has: [
|
|
233
|
-
{ type: 'header', key: 'x-environment', suf: '-dev' }
|
|
52
|
+
crons: [
|
|
53
|
+
{ path: '/api/cleanup', schedule: '0 0 * * *' }
|
|
234
54
|
]
|
|
235
|
-
}
|
|
55
|
+
};
|
|
236
56
|
```
|
|
237
57
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
// Greater than
|
|
242
|
-
router.rewrite('/api/v3/(.*)', 'https://api-v3.backend.com/$1', {
|
|
243
|
-
has: [
|
|
244
|
-
{ type: 'query', key: 'version', gt: 2 }
|
|
245
|
-
]
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Greater than or equal
|
|
249
|
-
router.rewrite('/premium/(.*)', '/premium-content/$1', {
|
|
250
|
-
has: [
|
|
251
|
-
{ type: 'header', key: 'x-subscription-tier', gte: 3 }
|
|
252
|
-
]
|
|
253
|
-
});
|
|
58
|
+
## Features
|
|
254
59
|
|
|
255
|
-
|
|
256
|
-
router.redirect(
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
});
|
|
60
|
+
- **Type-safe configuration** - Full TypeScript support with IDE autocomplete
|
|
61
|
+
- **Readable syntax** - Helper methods like `router.redirect()`, `router.rewrite()`, `router.header()`
|
|
62
|
+
- **Transforms** - Modify request/response headers and query parameters on the fly
|
|
63
|
+
- **Conditions** - Advanced routing with `has` and `missing` conditions
|
|
64
|
+
- **CLI tools** - `compile` and `validate` commands for development
|
|
261
65
|
|
|
262
|
-
|
|
263
|
-
router.rewrite('/free/(.*)', '/free-tier/$1', {
|
|
264
|
-
has: [
|
|
265
|
-
{ type: 'header', key: 'x-plan', lte: 1 }
|
|
266
|
-
]
|
|
267
|
-
});
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Host and Path Matching
|
|
66
|
+
## Build-Time Compilation
|
|
271
67
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
]
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// Path pattern matching (no key required)
|
|
281
|
-
router.rewrite('/(.*)', '/internal/$1', {
|
|
282
|
-
has: [
|
|
283
|
-
{ type: 'path', value: '^/api/v[0-9]+/.*' }
|
|
284
|
-
]
|
|
285
|
-
});
|
|
68
|
+
Your `vercel.ts` is automatically compiled to `vercel.json` during:
|
|
69
|
+
```bash
|
|
70
|
+
vercel build
|
|
71
|
+
vercel dev
|
|
72
|
+
vercel deploy
|
|
286
73
|
```
|
|
287
74
|
|
|
288
|
-
|
|
75
|
+
No manual build step needed - the Vercel CLI handles compilation automatically.
|
|
289
76
|
|
|
290
|
-
|
|
77
|
+
## CLI Commands
|
|
291
78
|
|
|
292
|
-
|
|
293
|
-
router.rewrite('/secure/(.*)', 'https://secure.backend.com/$1', {
|
|
294
|
-
has: [
|
|
295
|
-
{ type: 'header', key: 'x-api-key' },
|
|
296
|
-
{ type: 'header', key: 'x-user-role', inc: ['admin', 'superuser'] },
|
|
297
|
-
{ type: 'cookie', key: 'session', pre: 'secure-' },
|
|
298
|
-
{ type: 'query', key: 'version', gte: 2 }
|
|
299
|
-
]
|
|
300
|
-
});
|
|
301
|
-
```
|
|
79
|
+
For development and validation:
|
|
302
80
|
|
|
303
|
-
|
|
81
|
+
```bash
|
|
82
|
+
# Compile vercel.ts to JSON (output to stdout)
|
|
83
|
+
npx @vercel/config compile
|
|
304
84
|
|
|
305
|
-
|
|
85
|
+
# Validate config for errors and show summary
|
|
86
|
+
npx @vercel/config validate
|
|
306
87
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
has: [
|
|
310
|
-
{ type: 'header', key: 'authorization', pre: 'Bearer ' },
|
|
311
|
-
{ type: 'header', key: 'x-api-version', gte: 2 }
|
|
312
|
-
],
|
|
313
|
-
missing: [
|
|
314
|
-
{ type: 'header', key: 'x-deprecated-header' }
|
|
315
|
-
],
|
|
316
|
-
requestHeaders: {
|
|
317
|
-
'x-user-id': userId,
|
|
318
|
-
'x-internal-key': env.INTERNAL_API_KEY
|
|
319
|
-
}
|
|
320
|
-
}));
|
|
88
|
+
# Generate vercel.json locally (for development)
|
|
89
|
+
npx @vercel/config generate
|
|
321
90
|
```
|
|
322
91
|
|
|
323
|
-
### Available Operators
|
|
324
|
-
|
|
325
|
-
| Operator | Type | Description | Example |
|
|
326
|
-
|----------|------|-------------|---------|
|
|
327
|
-
| `eq` | string \| number | Exact equality match | `{ eq: 'v2' }` |
|
|
328
|
-
| `neq` | string | Not equal | `{ neq: 'guest' }` |
|
|
329
|
-
| `inc` | string[] | Value is one of | `{ inc: ['admin', 'mod'] }` |
|
|
330
|
-
| `ninc` | string[] | Value is not one of | `{ ninc: ['guest', 'banned'] }` |
|
|
331
|
-
| `pre` | string | Starts with prefix | `{ pre: 'Bearer ' }` |
|
|
332
|
-
| `suf` | string | Ends with suffix | `{ suf: '-dev' }` |
|
|
333
|
-
| `gt` | number | Greater than | `{ gt: 2 }` |
|
|
334
|
-
| `gte` | number | Greater than or equal | `{ gte: 3 }` |
|
|
335
|
-
| `lt` | number | Less than | `{ lt: 5 }` |
|
|
336
|
-
| `lte` | number | Less than or equal | `{ lte: 10 }` |
|
|
337
|
-
|
|
338
92
|
## Important Notes
|
|
339
93
|
|
|
340
|
-
- **One config file only**: You cannot have both `vercel.ts` and `vercel.json`.
|
|
341
|
-
- **
|
|
342
|
-
- **
|
|
94
|
+
- **One config file only**: You cannot have both `vercel.ts` and `vercel.json`.
|
|
95
|
+
- **Transforms compile to routes**: When you add transforms to rewrites/redirects (like `requestHeaders`), they're compiled to the lower-level `routes` primitive internally.
|
|
96
|
+
- **Automatic compilation**: The Vercel CLI compiles `vercel.ts` automatically.
|
|
343
97
|
|
|
344
98
|
## Learn More
|
|
345
99
|
|
package/dist/cli.js
CHANGED
|
@@ -27,6 +27,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
27
27
|
const fs_1 = require("fs");
|
|
28
28
|
const path_1 = require("path");
|
|
29
29
|
const fs_2 = require("fs");
|
|
30
|
+
const validation_1 = require("./utils/validation");
|
|
30
31
|
/**
|
|
31
32
|
* Named exports that should NOT be auto-converted to config
|
|
32
33
|
* (these are route-based features that compile into the routes array, or internal module properties)
|
|
@@ -68,46 +69,51 @@ async function configureRouter() {
|
|
|
68
69
|
};
|
|
69
70
|
}
|
|
70
71
|
/**
|
|
71
|
-
*
|
|
72
|
+
* Compile vercel.ts to JSON and output to stdout
|
|
72
73
|
*/
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
async function compileConfig() {
|
|
75
|
+
try {
|
|
76
|
+
const config = await configureRouter();
|
|
77
|
+
const json = JSON.stringify(config, null, 2);
|
|
78
|
+
console.log(json);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
console.error("Failed to compile config:", error);
|
|
82
|
+
process.exit(1);
|
|
77
83
|
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Validate the vercel.ts config
|
|
87
|
+
*/
|
|
88
|
+
async function validateConfig() {
|
|
89
|
+
var _a, _b, _c, _d;
|
|
78
90
|
try {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
return preserved;
|
|
91
|
+
const config = await configureRouter();
|
|
92
|
+
// Validate static fields
|
|
93
|
+
(0, validation_1.validateStaticFields)(config);
|
|
94
|
+
console.log("✓ Config is valid");
|
|
95
|
+
console.log(` - buildCommand: ${config.buildCommand || '(not set)'}`);
|
|
96
|
+
console.log(` - framework: ${config.framework || '(not set)'}`);
|
|
97
|
+
console.log(` - routes: ${((_a = config.routes) === null || _a === void 0 ? void 0 : _a.length) || 0} route(s)`);
|
|
98
|
+
console.log(` - redirects: ${((_b = config.redirects) === null || _b === void 0 ? void 0 : _b.length) || 0} redirect(s)`);
|
|
99
|
+
console.log(` - rewrites: ${((_c = config.rewrites) === null || _c === void 0 ? void 0 : _c.length) || 0} rewrite(s)`);
|
|
100
|
+
console.log(` - headers: ${((_d = config.headers) === null || _d === void 0 ? void 0 : _d.length) || 0} header(s)`);
|
|
90
101
|
}
|
|
91
102
|
catch (error) {
|
|
92
|
-
console.
|
|
93
|
-
|
|
103
|
+
console.error("✗ Config validation failed:");
|
|
104
|
+
console.error(` ${error}`);
|
|
105
|
+
process.exit(1);
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
108
|
/**
|
|
97
|
-
*
|
|
109
|
+
* Generate vercel.json file (for backwards compatibility / development)
|
|
98
110
|
*/
|
|
99
111
|
async function generateVercelConfig() {
|
|
100
112
|
try {
|
|
101
113
|
const config = await configureRouter();
|
|
102
|
-
const
|
|
103
|
-
// Merge: generated config takes precedence, but preserve existing build/install commands if not set
|
|
104
|
-
const mergedConfig = {
|
|
105
|
-
...existingFields,
|
|
106
|
-
...config,
|
|
107
|
-
};
|
|
108
|
-
const vercelConfig = JSON.stringify(mergedConfig, null, 2);
|
|
114
|
+
const json = JSON.stringify(config, null, 2);
|
|
109
115
|
const outputPath = (0, path_1.resolve)(process.cwd(), "vercel.json");
|
|
110
|
-
(0, fs_1.writeFileSync)(outputPath,
|
|
116
|
+
(0, fs_1.writeFileSync)(outputPath, json);
|
|
111
117
|
console.log("Successfully generated vercel.json");
|
|
112
118
|
}
|
|
113
119
|
catch (error) {
|
|
@@ -115,7 +121,30 @@ async function generateVercelConfig() {
|
|
|
115
121
|
process.exit(1);
|
|
116
122
|
}
|
|
117
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* CLI entry point
|
|
126
|
+
*/
|
|
127
|
+
async function main() {
|
|
128
|
+
const command = process.argv[2];
|
|
129
|
+
switch (command) {
|
|
130
|
+
case 'compile':
|
|
131
|
+
await compileConfig();
|
|
132
|
+
break;
|
|
133
|
+
case 'validate':
|
|
134
|
+
await validateConfig();
|
|
135
|
+
break;
|
|
136
|
+
case 'generate':
|
|
137
|
+
case undefined:
|
|
138
|
+
// Default to generate for backwards compatibility
|
|
139
|
+
await generateVercelConfig();
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
console.error(`Unknown command: ${command}`);
|
|
143
|
+
console.error('Available commands: compile, validate, generate');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
118
147
|
// Run if this file is executed directly
|
|
119
148
|
if (require.main === module) {
|
|
120
|
-
|
|
149
|
+
main();
|
|
121
150
|
}
|