@vesk/adapter 0.2.65 → 0.2.66

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.
@@ -1 +1 @@
1
- {"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAkDjG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AAkGD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkfxI"}
1
+ {"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAkDjG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AAkGD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkiBxI"}
@@ -281,6 +281,52 @@ export async function startProdServer(outDir, options) {
281
281
  }
282
282
  return origWriteHead(statusCode, headers);
283
283
  });
284
+ // Per-request security overrides (`request.setCsp()`, `.setSecurityHeader()`,
285
+ // `.setRateLimit()`, `.setCsrf()`) accumulate in the runtime's
286
+ // AsyncLocalStorage bag. The server cannot import the runtime directly (it
287
+ // is injected into generated code as a string), so it reads the bridge it
288
+ // registers on globalThis. Without this every one of those setters was a
289
+ // silent no-op.
290
+ const securityBridge = globalThis.__vesk_security;
291
+ // Rate limiting is enforced BEFORE the handler runs, so a per-request
292
+ // limit set inside the handler cannot apply to this same request. It is
293
+ // surfaced here for the next request on the connection-independent bag;
294
+ // the global limit configured in vesk.config is what gates this one.
295
+ // Wrap a handler call so overrides it records land in a fresh bag that is
296
+ // still readable when the response is written. Falls back to a pass-through
297
+ // when the runtime has not registered its bridge.
298
+ const securityRun = securityBridge?.run;
299
+ const withSecurityScope = securityRun
300
+ ? (fn) => securityRun(fn)
301
+ : (fn) => fn();
302
+ const applyOverrideHeaders = (headers) => {
303
+ const overrides = securityBridge?.get?.();
304
+ if (!overrides)
305
+ return headers;
306
+ const next = { ...headers };
307
+ if (typeof overrides.contentSecurityPolicy === 'string') {
308
+ next['Content-Security-Policy'] = overrides.contentSecurityPolicy;
309
+ }
310
+ const custom = overrides.customHeaders;
311
+ if (custom) {
312
+ for (const [name, value] of Object.entries(custom)) {
313
+ if (value === false)
314
+ delete next[name];
315
+ else
316
+ next[name] = value;
317
+ }
318
+ }
319
+ return next;
320
+ };
321
+ const origWriteHead2 = res.writeHead.bind(res);
322
+ let overridesApplied = false;
323
+ res.writeHead = ((statusCode, headers) => {
324
+ if (!overridesApplied) {
325
+ overridesApplied = true;
326
+ headers = applyOverrideHeaders((headers || {}));
327
+ }
328
+ return origWriteHead2(statusCode, headers);
329
+ });
284
330
  const publicDir = resolve(staticDir, 'public');
285
331
  const rootFile = url.pathname.length > 1 ? resolveWithin(publicDir, url.pathname.slice(1)) : null;
286
332
  if (rootFile && existsSync(rootFile) && statSync(rootFile).isFile()) {
@@ -427,7 +473,8 @@ export async function startProdServer(outDir, options) {
427
473
  }
428
474
  try {
429
475
  const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
430
- const response = await mod.handleAction(webRequest, actionId);
476
+ const handleAction = mod.handleAction.bind(mod);
477
+ const response = await withSecurityScope(() => handleAction(webRequest, actionId));
431
478
  await deliverResponse(res, response);
432
479
  }
433
480
  catch (e) {
@@ -449,7 +496,7 @@ export async function startProdServer(outDir, options) {
449
496
  if (mod) {
450
497
  try {
451
498
  const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
452
- const response = await mod.handle(webRequest);
499
+ const response = await withSecurityScope(() => mod.handle(webRequest));
453
500
  await deliverResponse(res, response);
454
501
  return;
455
502
  }
@@ -492,7 +539,7 @@ export async function startProdServer(outDir, options) {
492
539
  if (route.revalidate && route.revalidate > 0) {
493
540
  const { pageIsr } = await import('@vesk/runtime/src/index-server');
494
541
  cachedResult = await pageIsr(url.pathname, async () => {
495
- const response = await mod.handle(webRequest);
542
+ const response = await withSecurityScope(() => mod.handle(webRequest));
496
543
  return { html: await response.text(), headers: Object.fromEntries(response.headers) };
497
544
  }, { revalidate: route.revalidate, tags: route.tags || [] });
498
545
  }
@@ -501,7 +548,7 @@ export async function startProdServer(outDir, options) {
501
548
  res.end(cachedResult.html);
502
549
  return;
503
550
  }
504
- const response = await mod.handle(webRequest);
551
+ const response = await withSecurityScope(() => mod.handle(webRequest));
505
552
  const headers = Object.fromEntries(response.headers);
506
553
  if (!headers['content-type'] && !headers['Content-Type'])
507
554
  headers['Content-Type'] = 'text/html';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/adapter",
3
- "version": "0.2.65",
3
+ "version": "0.2.66",
4
4
  "type": "module",
5
5
  "description": "Vesk adapter — builds deployable .vesk/ output for Deno and Node serverless",
6
6
  "main": "./dist/index.js",
@@ -23,9 +23,9 @@
23
23
  "sharp": "^0.35.3"
24
24
  },
25
25
  "dependencies": {
26
- "@vesk/compiler": "^0.2.65",
27
- "@vesk/runtime": "^0.2.65",
28
- "@vesk/types": "^0.2.65"
26
+ "@vesk/compiler": "^0.2.66",
27
+ "@vesk/runtime": "^0.2.66",
28
+ "@vesk/types": "^0.2.66"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/ws": "^8.18.1",