@sveltejs/adapter-vercel 2.1.1 → 2.2.1

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/index.js +79 -5
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -6,6 +6,8 @@ import esbuild from 'esbuild';
6
6
 
7
7
  const VALID_RUNTIMES = ['edge', 'nodejs16.x', 'nodejs18.x'];
8
8
 
9
+ const DEFAULT_FUNCTION_NAME = 'fn';
10
+
9
11
  const get_default_runtime = () => {
10
12
  const major = process.version.slice(1).split('.')[0];
11
13
  if (major === '16') return 'nodejs16.x';
@@ -39,6 +41,12 @@ const plugin = function (defaults = {}) {
39
41
  builder.rimraf(dir);
40
42
  builder.rimraf(tmp);
41
43
 
44
+ if (fs.existsSync('vercel.json')) {
45
+ const vercel_file = fs.readFileSync('vercel.json', 'utf-8');
46
+ const vercel_config = JSON.parse(vercel_file);
47
+ validate_vercel_json(builder, vercel_config);
48
+ }
49
+
42
50
  const files = fileURLToPath(new URL('./files', import.meta.url).href);
43
51
 
44
52
  const dirs = {
@@ -208,7 +216,7 @@ const plugin = function (defaults = {}) {
208
216
  group.config.runtime === 'edge' ? generate_edge_function : generate_serverless_function;
209
217
 
210
218
  // generate one function for the group
211
- const name = singular ? 'fn' : `fn-${group.i}`;
219
+ const name = singular ? DEFAULT_FUNCTION_NAME : `fn-${group.i}`;
212
220
 
213
221
  await generate_function(
214
222
  name,
@@ -281,12 +289,25 @@ const plugin = function (defaults = {}) {
281
289
  }
282
290
  }
283
291
 
284
- if (singular) {
285
- // Common case: One function for all routes
286
- // Needs to happen after ISR or else regex swallows all other matches
287
- static_config.routes.push({ src: '/.*', dest: `/fn` });
292
+ if (!singular) {
293
+ // we need to create a catch-all route so that 404s are handled
294
+ // by SvelteKit rather than Vercel
295
+
296
+ const runtime = defaults.runtime ?? get_default_runtime();
297
+ const generate_function =
298
+ runtime === 'edge' ? generate_edge_function : generate_serverless_function;
299
+
300
+ await generate_function(
301
+ DEFAULT_FUNCTION_NAME,
302
+ /** @type {any} */ ({ runtime, ...defaults }),
303
+ []
304
+ );
288
305
  }
289
306
 
307
+ // Catch-all route must come at the end, otherwise it will swallow all other routes,
308
+ // including ISR aliases if there is only one function
309
+ static_config.routes.push({ src: '/.*', dest: `/${DEFAULT_FUNCTION_NAME}` });
310
+
290
311
  builder.log.minor('Copying assets...');
291
312
 
292
313
  builder.writeClient(dirs.static);
@@ -499,4 +520,57 @@ async function create_function_bundle(builder, entry, dir, config) {
499
520
  write(`${dir}/package.json`, JSON.stringify({ type: 'module' }));
500
521
  }
501
522
 
523
+ /**
524
+ *
525
+ * @param {import('@sveltejs/kit').Builder} builder
526
+ * @param {any} vercel_config
527
+ */
528
+ function validate_vercel_json(builder, vercel_config) {
529
+ if (builder.routes.length > 0 && !builder.routes[0].api) {
530
+ // bail — we're on an older SvelteKit version that doesn't
531
+ // populate `route.api.methods`, so we can't check
532
+ // to see if cron paths are valid
533
+ return;
534
+ }
535
+
536
+ const crons = /** @type {Array<unknown>} */ (
537
+ Array.isArray(vercel_config?.crons) ? vercel_config.crons : []
538
+ );
539
+
540
+ /** For a route to be considered 'valid', it must be an API route with a GET handler */
541
+ const valid_routes = builder.routes.filter((route) => route.api.methods.includes('GET'));
542
+
543
+ /** @type {Array<string>} */
544
+ const unmatched_paths = [];
545
+
546
+ for (const cron of crons) {
547
+ if (typeof cron !== 'object' || cron === null || !('path' in cron)) {
548
+ continue;
549
+ }
550
+
551
+ const { path } = cron;
552
+ if (typeof path !== 'string') {
553
+ continue;
554
+ }
555
+
556
+ for (const route of valid_routes) {
557
+ if (route.pattern.test(path)) {
558
+ continue;
559
+ }
560
+ }
561
+
562
+ unmatched_paths.push(path);
563
+ }
564
+
565
+ builder.log.warn(
566
+ `\nvercel.json defines cron tasks that use paths that do not correspond to an API route with a GET handler (ignore this if the request is handled in your \`handle\` hook):`
567
+ );
568
+
569
+ for (const path of unmatched_paths) {
570
+ console.log(` - ${path}`);
571
+ }
572
+
573
+ console.log('');
574
+ }
575
+
502
576
  export default plugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/adapter-vercel",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -29,7 +29,7 @@
29
29
  "devDependencies": {
30
30
  "@types/node": "^16.18.6",
31
31
  "typescript": "^4.9.4",
32
- "@sveltejs/kit": "^1.8.3"
32
+ "@sveltejs/kit": "^1.9.2"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@sveltejs/kit": "^1.5.0"