@vesk/vesk-cli 0.2.86 → 0.2.88

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/dist/cli.js +96 -18
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -37422,6 +37422,15 @@ function generatePlatformHandlerSource(input) {
37422
37422
  const hasEvents = !!input.hasEvents;
37423
37423
  let imports = "";
37424
37424
  const routeEntries = [];
37425
+ const routeSpecificity = (path) => {
37426
+ if (/:path\b|:rest\b|\[\.\.\./.test(path)) return 3;
37427
+ if (/:/.test(path)) return 2;
37428
+ return 1;
37429
+ };
37430
+ const pushEntry = (path, type, handler, extra) => {
37431
+ const entry = `{ path: ${JSON.stringify(path)}, type: '${type}', handler: ${handler}${extra}}`;
37432
+ routeEntries.push({ path, entry, specificity: routeSpecificity(path) });
37433
+ };
37425
37434
  for (const r of ssrRoutes) {
37426
37435
  const name = routeName2(r.fullPath.split("/").filter(Boolean));
37427
37436
  const id = `__ssr_${toId(name)}`;
@@ -37430,7 +37439,7 @@ function generatePlatformHandlerSource(input) {
37430
37439
  `;
37431
37440
  const revalidate2 = r._revalidate != null ? `revalidate: ${r._revalidate}, ` : "";
37432
37441
  const tags = r._isrTags ? `tags: ${JSON.stringify(r._isrTags)}, ` : "";
37433
- routeEntries.push(`{ path: ${JSON.stringify(r.fullPath)}, type: 'ssr', handler: ${id}, ${revalidate2}${tags}}`);
37442
+ pushEntry(r.fullPath, "ssr", id, `, ${revalidate2}${tags}`);
37434
37443
  }
37435
37444
  for (const r of apiRoutes) {
37436
37445
  const name = apiRouteName2(r.fullPath);
@@ -37438,8 +37447,9 @@ function generatePlatformHandlerSource(input) {
37438
37447
  const funcPath = `./server/api/${name}.js`;
37439
37448
  imports += `import { handle as ${id} } from ${JSON.stringify(funcPath)};
37440
37449
  `;
37441
- routeEntries.push(`{ path: ${JSON.stringify("/api" + r.fullPath)}, type: 'api', handler: ${id} }`);
37450
+ pushEntry("/api" + r.fullPath, "api", id, "");
37442
37451
  }
37452
+ routeEntries.sort((a, b) => a.specificity - b.specificity);
37443
37453
  const mwImport = hasMiddleware ? "import { execute as __executeMw } from './server/middleware.js';" : "";
37444
37454
  const hasMwLiteral = hasMiddleware ? "true" : "false";
37445
37455
  const eventsImport = hasEvents ? "import { executeStart as __eventsStart, executeRequest as __eventsRequest } from './server/events.js';" : "";
@@ -37461,7 +37471,7 @@ ${eventsImport}
37461
37471
  ${prerenderedList}
37462
37472
  ${isrCache}
37463
37473
  ${defaultNotFoundLine}
37464
- const __routes = [${routeEntries.join(",\n")}];
37474
+ const __routes = [${routeEntries.map((e) => e.entry).join(",\n")}];
37465
37475
 
37466
37476
  async function __invokeRoute(route, request) {
37467
37477
  try {
@@ -37513,9 +37523,10 @@ function __matchPath(pattern, pathname) {
37513
37523
  }
37514
37524
 
37515
37525
  export async function handleRequest(request) {
37516
- const url = new URL(request.url);
37517
- const pathname = url.pathname;
37518
- const isDataRequest = request.headers.get('x-vesk-data') === '1';
37526
+ try {
37527
+ const url = new URL(request.url);
37528
+ const pathname = url.pathname;
37529
+ const isDataRequest = request.headers.get('x-vesk-data') === '1';
37519
37530
  ${serverStoreLine}
37520
37531
 
37521
37532
  if (__prerendered.has(pathname) && !isDataRequest) {
@@ -37610,6 +37621,17 @@ ${eventsRequestLine}
37610
37621
  status: 404,
37611
37622
  headers: { 'Content-Type': 'text/html' },
37612
37623
  });
37624
+ } catch (e) {
37625
+ // Any error that escapes the route (a thrown exception, a bad import, a
37626
+ // middleware failure, ...) must not bubble out of handleRequest. On
37627
+ // serverless platforms (Vercel, Netlify, Cloudflare) an uncaught throw is
37628
+ // surfaced as FUNCTION_INVOCATION_FAILED \u2014 Next.js avoids this by wrapping
37629
+ // its entry points the same way. Convert it into a proper 500 response.
37630
+ return new Response(renderDefaultErrorPage({ url: request.url }), {
37631
+ status: 500,
37632
+ headers: { 'Content-Type': 'text/html' },
37633
+ });
37634
+ }
37613
37635
  }
37614
37636
  `;
37615
37637
  }
@@ -51087,13 +51109,39 @@ ${extracted.body}
51087
51109
  " nextResult = await run(index + 1);",
51088
51110
  " return nextResult;",
51089
51111
  " }",
51090
- " const result = await fn(ctx, next);",
51091
- " if (result instanceof Response) return result;",
51092
- " if (nextResult instanceof Response) return nextResult;",
51093
- " if (!nextCalled) return run(index + 1);",
51094
- " return null;",
51112
+ " try {",
51113
+ " const result = await fn(ctx, next);",
51114
+ " if (result instanceof Response) return result;",
51115
+ " if (nextResult instanceof Response) return nextResult;",
51116
+ " if (!nextCalled) return run(index + 1);",
51117
+ " return null;",
51118
+ " } catch (e) {",
51119
+ " if (e && typeof e === 'object' && e.name === 'Redirect') {",
51120
+ " return new Response(null, {",
51121
+ " status: Number(e.status) || 302,",
51122
+ " headers: { Location: String(e.url || '') },",
51123
+ " });",
51124
+ " }",
51125
+ " if (e instanceof TypeError && /Failed to parse URL from/.test(String(e.message))) {",
51126
+ " const msg = String(e.message);",
51127
+ " const prefix = 'Failed to parse URL from ';",
51128
+ " const start = msg.indexOf(prefix);",
51129
+ " const target = start === -1 ? '' : msg.slice(start + prefix.length).trim().split(' ')[0];",
51130
+ " return new Response(null, { status: 302, headers: { Location: target } });",
51131
+ " }",
51132
+ " throw e;",
51133
+ " }",
51134
+ " }",
51135
+ " let response = null;",
51136
+ " try {",
51137
+ " response = await run(0);",
51138
+ " } catch (e) {",
51139
+ " // Unexpected middleware errors must not crash the server. On serverless",
51140
+ " // platforms (Vercel, Netlify, Cloudflare) an uncaught throw surfaces as",
51141
+ " // FUNCTION_INVOCATION_FAILED \u2014 Next.js avoids this by wrapping entry",
51142
+ " // points the same way. Convert it into a 500 response.",
51143
+ " response = new Response(null, { status: 500 });",
51095
51144
  " }",
51096
- " const response = await run(0);",
51097
51145
  " return { response, rewriteUrl };",
51098
51146
  "}",
51099
51147
  ""
@@ -51132,13 +51180,39 @@ ${extracted.body}
51132
51180
  " ncResult = await run(index + 1);",
51133
51181
  " return ncResult;",
51134
51182
  " }",
51135
- " const result = await fn(ctx, next);",
51136
- " if (result instanceof Response) return result;",
51137
- " if (ncResult instanceof Response) return ncResult;",
51138
- " if (!nc) return run(index + 1);",
51139
- " return null;",
51183
+ " try {",
51184
+ " const result = await fn(ctx, next);",
51185
+ " if (result instanceof Response) return result;",
51186
+ " if (ncResult instanceof Response) return ncResult;",
51187
+ " if (!nc) return run(index + 1);",
51188
+ " return null;",
51189
+ " } catch (e) {",
51190
+ " if (e && typeof e === 'object' && e.name === 'Redirect') {",
51191
+ " return new Response(null, {",
51192
+ " status: Number(e.status) || 302,",
51193
+ " headers: { Location: String(e.url || '') },",
51194
+ " });",
51195
+ " }",
51196
+ " if (e instanceof TypeError && /Failed to parse URL from/.test(String(e.message))) {",
51197
+ " const msg = String(e.message);",
51198
+ " const prefix = 'Failed to parse URL from ';",
51199
+ " const start = msg.indexOf(prefix);",
51200
+ " const target = start === -1 ? '' : msg.slice(start + prefix.length).trim().split(' ')[0];",
51201
+ " return new Response(null, { status: 302, headers: { Location: target } });",
51202
+ " }",
51203
+ " throw e;",
51204
+ " }",
51205
+ " }",
51206
+ " let response = null;",
51207
+ " try {",
51208
+ " response = await run(0);",
51209
+ " } catch (e) {",
51210
+ " // Unexpected middleware errors must not crash the server. On serverless",
51211
+ " // platforms (Vercel, Netlify, Cloudflare) an uncaught throw surfaces as",
51212
+ " // FUNCTION_INVOCATION_FAILED \u2014 Next.js avoids this by wrapping entry",
51213
+ " // points the same way. Convert it into a 500 response.",
51214
+ " response = new Response(null, { status: 500 });",
51140
51215
  " }",
51141
- " const response = await run(0);",
51142
51216
  " return { response, rewriteUrl };",
51143
51217
  "}",
51144
51218
  ""
@@ -58339,6 +58413,10 @@ async function executeMiddlewareChain(chain, request, params, options = {}) {
58339
58413
  headers: { Location: err.url || "" }
58340
58414
  });
58341
58415
  }
58416
+ if (e instanceof TypeError && /Failed to parse URL from/.test(String(e.message))) {
58417
+ const target = /Failed to parse URL from (\S+)/.exec(String(e.message))?.[1] ?? "";
58418
+ return new Response(null, { status: 302, headers: { Location: target } });
58419
+ }
58342
58420
  throw e;
58343
58421
  }
58344
58422
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/vesk-cli",
3
- "version": "0.2.86",
3
+ "version": "0.2.88",
4
4
  "type": "module",
5
5
  "description": "Vesk — compiler-first framework for the post-VDOM web. vesk dev, vesk build.",
6
6
  "bin": {
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "main": "./dist/cli.js",
10
10
  "dependencies": {
11
- "@vesk/adapter": "^0.2.86",
12
- "@vesk/compiler": "^0.2.86",
13
- "@vesk/plugin-tailwind": "^0.2.86",
14
- "@vesk/runtime": "^0.2.86",
11
+ "@vesk/adapter": "^0.2.88",
12
+ "@vesk/compiler": "^0.2.88",
13
+ "@vesk/plugin-tailwind": "^0.2.88",
14
+ "@vesk/runtime": "^0.2.88",
15
15
  "esrap": "^2.3.0",
16
16
  "typescript": "^5.8.0",
17
17
  "ws": "^8.18.0",