theokit 0.72.1 → 0.74.0
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 +2 -0
- package/dist/{actions-virtual-module-OHENNMQG.js → actions-virtual-module-J2HYO7QZ.js} +4 -4
- package/dist/{actions-virtual-module-EAKYEMGF.js → actions-virtual-module-JV7URROJ.js} +7 -7
- package/dist/adapters/agent-mount.js +3 -3
- package/dist/adapters/security-headers.d.ts +27 -11
- package/dist/adapters/security-headers.js +9 -4
- package/dist/adapters/security-headers.js.map +1 -1
- package/dist/{agent-VJTZ4DQ7.js → agent-GU6JIEFJ.js} +3 -3
- package/dist/{app-typed-client-ILLQYTXP.js → app-typed-client-EOA3A2AR.js} +5 -5
- package/dist/{app-typed-client-ILLQYTXP.js.map → app-typed-client-EOA3A2AR.js.map} +1 -1
- package/dist/{app-typed-client-LHH77QDB.js → app-typed-client-XD4DZBV7.js} +8 -8
- package/dist/app-typed-client-XD4DZBV7.js.map +1 -0
- package/dist/{aws-lambda-7AZNJGWU.js → aws-lambda-ZYSPTD3O.js} +61 -27
- package/dist/aws-lambda-ZYSPTD3O.js.map +1 -0
- package/dist/{build-23QF5FNQ.js → build-6FVZKORI.js} +81 -74
- package/dist/build-6FVZKORI.js.map +1 -0
- package/dist/{bun-NKVHOFSJ.js → bun-I7YM3RDB.js} +82 -21
- package/dist/bun-I7YM3RDB.js.map +1 -0
- package/dist/{chunk-WBB3MEEN.js → chunk-2NG5T77O.js} +47 -12
- package/dist/{chunk-WBB3MEEN.js.map → chunk-2NG5T77O.js.map} +1 -1
- package/dist/{chunk-NO6HA4FG.js → chunk-4WP7A7RX.js} +41 -35
- package/dist/chunk-4WP7A7RX.js.map +1 -0
- package/dist/chunk-4X43VTST.js +31 -0
- package/dist/chunk-4X43VTST.js.map +1 -0
- package/dist/{chunk-FHQP23Z5.js → chunk-6R5F5YF2.js} +17 -14
- package/dist/chunk-6R5F5YF2.js.map +1 -0
- package/dist/chunk-72RSCKMW.js +53 -0
- package/dist/chunk-72RSCKMW.js.map +1 -0
- package/dist/{chunk-V5SSTT3C.js → chunk-C43AHOHI.js} +1 -1
- package/dist/chunk-C43AHOHI.js.map +1 -0
- package/dist/{chunk-C5CAL3DX.js → chunk-EQJF2EH5.js} +8 -7
- package/dist/chunk-EQJF2EH5.js.map +1 -0
- package/dist/{chunk-QD5X56I3.js → chunk-FNJVSFEC.js} +1 -1
- package/dist/chunk-FNJVSFEC.js.map +1 -0
- package/dist/{chunk-6U67SO5U.js → chunk-HK57MPSZ.js} +2 -2
- package/dist/{chunk-R7G2B2WH.js → chunk-HKF6YNY4.js} +17 -14
- package/dist/{chunk-R7G2B2WH.js.map → chunk-HKF6YNY4.js.map} +1 -1
- package/dist/chunk-IJQQNHL7.js +34 -0
- package/dist/chunk-IJQQNHL7.js.map +1 -0
- package/dist/{chunk-RE2WE7CD.js → chunk-LOOOB46A.js} +2 -2
- package/dist/{chunk-PEL3MJLM.js → chunk-MX63AWEK.js} +1 -1
- package/dist/{chunk-PEL3MJLM.js.map → chunk-MX63AWEK.js.map} +1 -1
- package/dist/chunk-NPQ5A3RU.js +53 -0
- package/dist/chunk-NPQ5A3RU.js.map +1 -0
- package/dist/{chunk-DKX7LF5Q.js → chunk-ODYLKWRT.js} +3 -3
- package/dist/{chunk-L6UHMWXU.js → chunk-QAS5SKZP.js} +3 -3
- package/dist/chunk-QAS5SKZP.js.map +1 -0
- package/dist/{chunk-4EQEJ4PH.js → chunk-RFZ263XP.js} +68 -23
- package/dist/chunk-RFZ263XP.js.map +1 -0
- package/dist/{chunk-XLSJWKSP.js → chunk-S5QN3O22.js} +66 -21
- package/dist/{chunk-XLSJWKSP.js.map → chunk-S5QN3O22.js.map} +1 -1
- package/dist/{chunk-E2RC367T.js → chunk-SHIXTMQE.js} +49 -14
- package/dist/{chunk-E2RC367T.js.map → chunk-SHIXTMQE.js.map} +1 -1
- package/dist/{chunk-G7U7FQVC.js → chunk-UFBBFP75.js} +13 -3
- package/dist/chunk-UFBBFP75.js.map +1 -0
- package/dist/{chunk-4CIHLTSI.js → chunk-V7ISZGNS.js} +45 -39
- package/dist/chunk-V7ISZGNS.js.map +1 -0
- package/dist/{chunk-RCFD5W5V.js → chunk-WR5B2XNT.js} +6 -6
- package/dist/chunk-WR5B2XNT.js.map +1 -0
- package/dist/{chunk-IB5VIXLR.js → chunk-XLFDYTWO.js} +2 -2
- package/dist/cli/index.js +8 -8
- package/dist/client/index.d.ts +18 -1
- package/dist/client/index.js +15 -1
- package/dist/client/index.js.map +1 -1
- package/dist/{cloudflare-4M4XVNUH.js → cloudflare-AMH4TJNL.js} +104 -82
- package/dist/cloudflare-AMH4TJNL.js.map +1 -0
- package/dist/{config-support-SB5NDQZB.js → config-support-MOZYHRWG.js} +13 -2
- package/dist/{config-support-SB5NDQZB.js.map → config-support-MOZYHRWG.js.map} +1 -1
- package/dist/{deno-deploy-IVACZ62D.js → deno-deploy-6H354VRA.js} +17 -7
- package/dist/deno-deploy-6H354VRA.js.map +1 -0
- package/dist/{dev-JDJWMRLH.js → dev-HJUD6X3R.js} +9 -9
- package/dist/{dev-emit-7KZFUA7M.js → dev-emit-T3X6RR7M.js} +5 -5
- package/dist/{dev-emit-7KZFUA7M.js.map → dev-emit-T3X6RR7M.js.map} +1 -1
- package/dist/{dev-emit-JPJJFBXL.js → dev-emit-ZK5GCHXN.js} +6 -6
- package/dist/dev-emit-ZK5GCHXN.js.map +1 -0
- package/dist/index.js +5 -5
- package/dist/{internal-api-VDYOXOT7.js → internal-api-GKPJYL3G.js} +7 -7
- package/dist/{internal-api-6XNLCNI5.js → internal-api-ZUBUYGCQ.js} +4 -4
- package/dist/{mcp-WJNCTM7M.js → mcp-MVKDWZEQ.js} +3 -3
- package/dist/{netlify-3HEWV375.js → netlify-ALPCTQFO.js} +158 -48
- package/dist/netlify-ALPCTQFO.js.map +1 -0
- package/dist/{node-QUGTW6XV.js → node-4HQO6KKZ.js} +2 -2
- package/dist/{observability-bootstrap-FP6LMMJE.js → observability-bootstrap-DOWRMADT.js} +2 -2
- package/dist/{openapi-Q53YOBIU.js → openapi-C4UX2SFV.js} +5 -5
- package/dist/openapi-C4UX2SFV.js.map +1 -0
- package/dist/{preview-BARW75PN.js → preview-5HUID27O.js} +3 -3
- package/dist/registry-OMLCP4AS.js +34 -0
- package/dist/registry-OMLCP4AS.js.map +1 -0
- package/dist/{routes-FDF4SLOB.js → routes-3PTNISSO.js} +2 -2
- package/dist/server/index.js +2 -2
- package/dist/server/scan/index.d.ts +38 -2
- package/dist/server/scan/index.js +2 -2
- package/dist/{server-boundary-AO6EELRF.js → server-boundary-QCJNECJP.js} +7 -7
- package/dist/{server-boundary-E5GFVPLB.js → server-boundary-RTRPHX5I.js} +4 -4
- package/dist/{start-4JTYXQQJ.js → start-EREUCSN6.js} +10 -10
- package/dist/{static-NQPLPAB6.js → static-7LP7LPGN.js} +2 -2
- package/dist/{vercel-5PMYEEKF.js → vercel-VLR52RXT.js} +173 -73
- package/dist/vercel-VLR52RXT.js.map +1 -0
- package/dist/vite-plugin/index.js +5 -5
- package/dist/{vite-plugin-3ON45MQE.js → vite-plugin-JVGI6QUO.js} +9 -9
- package/package.json +4 -4
- package/dist/app-typed-client-LHH77QDB.js.map +0 -1
- package/dist/aws-lambda-7AZNJGWU.js.map +0 -1
- package/dist/build-23QF5FNQ.js.map +0 -1
- package/dist/bun-NKVHOFSJ.js.map +0 -1
- package/dist/chunk-4CIHLTSI.js.map +0 -1
- package/dist/chunk-4EQEJ4PH.js.map +0 -1
- package/dist/chunk-C5CAL3DX.js.map +0 -1
- package/dist/chunk-FHQP23Z5.js.map +0 -1
- package/dist/chunk-G7U7FQVC.js.map +0 -1
- package/dist/chunk-L6UHMWXU.js.map +0 -1
- package/dist/chunk-NO6HA4FG.js.map +0 -1
- package/dist/chunk-QD5X56I3.js.map +0 -1
- package/dist/chunk-RCFD5W5V.js.map +0 -1
- package/dist/chunk-V5SSTT3C.js.map +0 -1
- package/dist/cloudflare-4M4XVNUH.js.map +0 -1
- package/dist/deno-deploy-IVACZ62D.js.map +0 -1
- package/dist/dev-emit-JPJJFBXL.js.map +0 -1
- package/dist/netlify-3HEWV375.js.map +0 -1
- package/dist/openapi-Q53YOBIU.js.map +0 -1
- package/dist/registry-SDBODRU6.js +0 -23
- package/dist/registry-SDBODRU6.js.map +0 -1
- package/dist/vercel-5PMYEEKF.js.map +0 -1
- /package/dist/{actions-virtual-module-OHENNMQG.js.map → actions-virtual-module-J2HYO7QZ.js.map} +0 -0
- /package/dist/{actions-virtual-module-EAKYEMGF.js.map → actions-virtual-module-JV7URROJ.js.map} +0 -0
- /package/dist/{agent-VJTZ4DQ7.js.map → agent-GU6JIEFJ.js.map} +0 -0
- /package/dist/{chunk-6U67SO5U.js.map → chunk-HK57MPSZ.js.map} +0 -0
- /package/dist/{chunk-RE2WE7CD.js.map → chunk-LOOOB46A.js.map} +0 -0
- /package/dist/{chunk-DKX7LF5Q.js.map → chunk-ODYLKWRT.js.map} +0 -0
- /package/dist/{chunk-IB5VIXLR.js.map → chunk-XLFDYTWO.js.map} +0 -0
- /package/dist/{dev-JDJWMRLH.js.map → dev-HJUD6X3R.js.map} +0 -0
- /package/dist/{internal-api-VDYOXOT7.js.map → internal-api-GKPJYL3G.js.map} +0 -0
- /package/dist/{internal-api-6XNLCNI5.js.map → internal-api-ZUBUYGCQ.js.map} +0 -0
- /package/dist/{mcp-WJNCTM7M.js.map → mcp-MVKDWZEQ.js.map} +0 -0
- /package/dist/{node-QUGTW6XV.js.map → node-4HQO6KKZ.js.map} +0 -0
- /package/dist/{observability-bootstrap-FP6LMMJE.js.map → observability-bootstrap-DOWRMADT.js.map} +0 -0
- /package/dist/{preview-BARW75PN.js.map → preview-5HUID27O.js.map} +0 -0
- /package/dist/{routes-FDF4SLOB.js.map → routes-3PTNISSO.js.map} +0 -0
- /package/dist/{server-boundary-AO6EELRF.js.map → server-boundary-QCJNECJP.js.map} +0 -0
- /package/dist/{server-boundary-E5GFVPLB.js.map → server-boundary-RTRPHX5I.js.map} +0 -0
- /package/dist/{start-4JTYXQQJ.js.map → start-EREUCSN6.js.map} +0 -0
- /package/dist/{static-NQPLPAB6.js.map → static-7LP7LPGN.js.map} +0 -0
- /package/dist/{vite-plugin-3ON45MQE.js.map → vite-plugin-JVGI6QUO.js.map} +0 -0
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
|
+
import {
|
|
4
|
+
readDocumentShell
|
|
5
|
+
} from "./chunk-IJQQNHL7.js";
|
|
6
|
+
import {
|
|
7
|
+
bundleDeployedFunction
|
|
8
|
+
} from "./chunk-NPQ5A3RU.js";
|
|
9
|
+
import {
|
|
10
|
+
renderBakedRoutes,
|
|
11
|
+
routeRuntimeLines
|
|
12
|
+
} from "./chunk-72RSCKMW.js";
|
|
3
13
|
import {
|
|
4
14
|
deployedEntryPreamble
|
|
5
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-XLFDYTWO.js";
|
|
6
16
|
import {
|
|
7
17
|
JSON_NOT_FOUND_RESPONSE,
|
|
8
|
-
agentsDirLiteral,
|
|
9
18
|
deployedAgentsFragment,
|
|
10
19
|
deployedRateLimitFragment,
|
|
11
20
|
deployedRuntimeConfigFragment,
|
|
12
21
|
deployedTraceFragment,
|
|
13
22
|
describeDeployedSecurityHeaders,
|
|
14
23
|
rateLimitCheckFragment,
|
|
15
|
-
scannedFromLoaderCache,
|
|
16
24
|
serverDirLiteral
|
|
17
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-EQJF2EH5.js";
|
|
18
26
|
import {
|
|
19
27
|
nodeAdapter
|
|
20
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-UFBBFP75.js";
|
|
29
|
+
import "./chunk-3PWQQWT6.js";
|
|
21
30
|
import {
|
|
22
31
|
buildSecurityHeaders
|
|
23
32
|
} from "./chunk-WSMLSIS5.js";
|
|
@@ -28,13 +37,13 @@ import {
|
|
|
28
37
|
|
|
29
38
|
// src/adapters/vercel.ts
|
|
30
39
|
import { existsSync, mkdirSync, writeFileSync, cpSync } from "fs";
|
|
31
|
-
import { resolve } from "path";
|
|
40
|
+
import { basename, resolve } from "path";
|
|
32
41
|
function vercelHandlerFragment(rateLimit) {
|
|
33
42
|
return [
|
|
34
43
|
// B-027 — only when a limit is declared. `createRateLimiterWeb` is used at module scope by
|
|
35
44
|
// the fragment; `resolveClientIpFromRequest` reads the forwarded headers behind `trustProxy`.
|
|
36
45
|
...rateLimit === void 0 ? [] : [
|
|
37
|
-
`import { createRateLimiterWeb } from 'theokit/server'`,
|
|
46
|
+
`import { createRateLimiterWeb } from 'theokit/server/rate-limit'`,
|
|
38
47
|
`import { resolveClientIpFromRequest } from 'theokit/server/rate-limit'`
|
|
39
48
|
],
|
|
40
49
|
...deployedRateLimitFragment(
|
|
@@ -145,20 +154,25 @@ function vercelHandlerFragment(rateLimit) {
|
|
|
145
154
|
``
|
|
146
155
|
];
|
|
147
156
|
}
|
|
148
|
-
function vercelRouteRequestFragment(runtimeSpread, agentsBranch, agentsHostBypass) {
|
|
157
|
+
function vercelRouteRequestFragment(runtimeSpread, agentsBranch, agentsHostBypass, document) {
|
|
149
158
|
return [
|
|
150
159
|
`async function routeRequest(nodeReq) {`,
|
|
151
160
|
` const url = new URL(nodeReq.url ?? '/', 'http://' + (nodeReq.headers?.host ?? 'localhost'))`,
|
|
152
161
|
``,
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
`
|
|
156
|
-
|
|
157
|
-
`
|
|
158
|
-
|
|
162
|
+
// B-317 — emitted only when this function does NOT render the document. With a document branch
|
|
163
|
+
// every path is legitimate: `/api/*` is a route and everything else is a page, so refusing
|
|
164
|
+
// non-`/api` paths here would make that branch unreachable — which is exactly what it did, and
|
|
165
|
+
// the first version of the fix shipped it: the branch was present, asserted present, and never
|
|
166
|
+
// entered. `/` answered this 9-byte `Not Found` instead of a document.
|
|
167
|
+
...document === void 0 ? [
|
|
168
|
+
` if (!url.pathname.startsWith('/api/')${agentsHostBypass}) {`,
|
|
169
|
+
` return new Response('Not Found', {`,
|
|
170
|
+
` status: 404,`,
|
|
171
|
+
` headers: { 'content-type': 'text/plain; charset=utf-8' },`,
|
|
172
|
+
` })`,
|
|
173
|
+
` }`
|
|
174
|
+
] : [],
|
|
159
175
|
``,
|
|
160
|
-
` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,
|
|
161
|
-
` if (!loaderCache) loaderCache = createProductionLoader()`,
|
|
162
176
|
``,
|
|
163
177
|
// B-235 — the Node-to-Web conversion is hoisted ABOVE the agents branch, which names
|
|
164
178
|
// `request` like every other host's, and an agent path never reaches a route match. The
|
|
@@ -189,8 +203,30 @@ function vercelRouteRequestFragment(runtimeSpread, agentsBranch, agentsHostBypas
|
|
|
189
203
|
``,
|
|
190
204
|
...agentsBranch,
|
|
191
205
|
``,
|
|
192
|
-
` const match = matchRoute(url.pathname,
|
|
193
|
-
|
|
206
|
+
` const match = matchRoute(url.pathname, routes)`,
|
|
207
|
+
...document !== void 0 ? [
|
|
208
|
+
` if (!match) {`,
|
|
209
|
+
` // B-317 \u2014 a path with no matching file arrives here because config.json routes it to this`,
|
|
210
|
+
` // function. Before this branch it answered a JSON 404, so the config sent every page to the`,
|
|
211
|
+
` // static shell instead and an SSR project was served an empty \`<div id="root">\` while the`,
|
|
212
|
+
` // build announced SSR.`,
|
|
213
|
+
` //`,
|
|
214
|
+
` // Only OUTSIDE \`/api/\`: a path under it that matches no route is a routing miss and owes a`,
|
|
215
|
+
` // JSON 404, not a document. Rendering one there would answer a fetch with HTML.`,
|
|
216
|
+
` if (!url.pathname.startsWith('/api/')) {`,
|
|
217
|
+
` const nonce = generateNonce()`,
|
|
218
|
+
` return withSecurityHeaders(`,
|
|
219
|
+
` await renderStreamingWeb(request, {`,
|
|
220
|
+
` htmlHead: ${JSON.stringify(document.htmlHead ?? "")},`,
|
|
221
|
+
` htmlTail: ${JSON.stringify(document.htmlTail ?? "")},`,
|
|
222
|
+
` nonce,`,
|
|
223
|
+
` }),`,
|
|
224
|
+
` buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true }, { nonce }),`,
|
|
225
|
+
` )`,
|
|
226
|
+
` }`,
|
|
227
|
+
` return ${JSON_NOT_FOUND_RESPONSE}`,
|
|
228
|
+
` }`
|
|
229
|
+
] : [` if (!match) return ${JSON_NOT_FOUND_RESPONSE}`],
|
|
194
230
|
``,
|
|
195
231
|
` const { req, res, toResponse } = createWebShim(request)`,
|
|
196
232
|
...deployedTraceFragment("request", " "),
|
|
@@ -198,28 +234,39 @@ function vercelRouteRequestFragment(runtimeSpread, agentsBranch, agentsHostBypas
|
|
|
198
234
|
` // toResponse() settles at the headers and carries a live body.`,
|
|
199
235
|
` return toResponse(executeRoute({`,
|
|
200
236
|
` route: match.route, method, params: match.params,`,
|
|
201
|
-
` req, res, loadModule
|
|
237
|
+
` req, res, loadModule, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread}`,
|
|
202
238
|
` }))`,
|
|
203
239
|
`}`
|
|
204
240
|
];
|
|
205
241
|
}
|
|
206
242
|
function renderVercelFunctionEntry(opts = {}) {
|
|
207
243
|
const runtimeConfig = deployedRuntimeConfigFragment(opts);
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
244
|
+
const { routeImports, routeModuleEntries, routeTableEntries } = renderBakedRoutes(
|
|
245
|
+
opts.routes ?? []
|
|
246
|
+
);
|
|
247
|
+
const agentsFragment = deployedAgentsFragment(
|
|
248
|
+
{ kind: "baked", agents: opts.agents ?? [], contextModule: opts.contextModule },
|
|
249
|
+
{ notFound: JSON_NOT_FOUND_RESPONSE }
|
|
250
|
+
);
|
|
211
251
|
return [
|
|
212
252
|
`// Generated by Theo \u2014 Vercel Functions adapter`,
|
|
213
253
|
`// Environment variables are resolved at RUNTIME, not build time.`,
|
|
214
254
|
``,
|
|
215
255
|
`import { resolve } from 'node:path'`,
|
|
216
|
-
`import {
|
|
256
|
+
`import { matchRoute, compilePattern } from 'theokit/server/scan'
|
|
257
|
+
import { executeRoute, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server/http'`,
|
|
258
|
+
...routeImports,
|
|
217
259
|
`import { createWebShim } from 'theokit/adapters/web-shim'`,
|
|
218
|
-
`import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,
|
|
260
|
+
opts.ssr === true ? `import { buildSecurityHeaders, generateNonce, withSecurityHeaders } from 'theokit/adapters/security-headers'` : `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,
|
|
261
|
+
...opts.ssr === true ? [`import { renderStreamingWeb } from '../server/entry-server.js'`] : [],
|
|
219
262
|
``,
|
|
220
|
-
|
|
221
|
-
`
|
|
222
|
-
`
|
|
263
|
+
...routeRuntimeLines(routeModuleEntries, routeTableEntries, "vercel"),
|
|
264
|
+
// B-318 / B-319 — `const cwd` used to be declared here, because the agents fragment emitted
|
|
265
|
+
// `scanAgents(cwd, …)` and this was the one of its four callers that never declared the name.
|
|
266
|
+
// B-319 then removed the scan entirely from this target — there is no source tree to read on a
|
|
267
|
+
// platform that uploads only its bundle — so the declaration became dead code. The pairing is
|
|
268
|
+
// still enforced for the three adapters that DO scan, by
|
|
269
|
+
// `tests/unit/a-generated-entry-declares-every-name-it-uses.test.ts`.
|
|
223
270
|
`const serverDir = resolve(process.cwd(), ${serverDirLiteral(opts)})`,
|
|
224
271
|
``,
|
|
225
272
|
`// #410 \u2014 the security baseline \`theokit start\` puts on every response,`,
|
|
@@ -238,11 +285,12 @@ function renderVercelFunctionEntry(opts = {}) {
|
|
|
238
285
|
...vercelRouteRequestFragment(
|
|
239
286
|
runtimeConfig.executeRouteSpread,
|
|
240
287
|
agentsFragment.branch,
|
|
241
|
-
agentsFragment.hostBypass
|
|
288
|
+
agentsFragment.hostBypass,
|
|
289
|
+
opts.ssr === true ? { htmlHead: opts.htmlHead, htmlTail: opts.htmlTail } : void 0
|
|
242
290
|
)
|
|
243
291
|
].join("\n");
|
|
244
292
|
}
|
|
245
|
-
function renderVercelConfigJson(securityHeaders) {
|
|
293
|
+
function renderVercelConfigJson(securityHeaders, opts = {}) {
|
|
246
294
|
return {
|
|
247
295
|
version: 3,
|
|
248
296
|
routes: [
|
|
@@ -253,7 +301,12 @@ function renderVercelConfigJson(securityHeaders) {
|
|
|
253
301
|
},
|
|
254
302
|
{ src: "/api/(.*)", dest: "/api" },
|
|
255
303
|
{ handle: "filesystem" },
|
|
256
|
-
{
|
|
304
|
+
// B-317 — where a path with no matching file goes. `{ handle: 'filesystem' }` above still
|
|
305
|
+
// serves every real file, so this is reached only by a page request: to the function when the
|
|
306
|
+
// project renders one, and to the static shell when it does not. It sent every page to the shell
|
|
307
|
+
// regardless, so an SSR project was served an empty `<div id="root">` while the build announced
|
|
308
|
+
// SSR.
|
|
309
|
+
{ src: "/(.*)", dest: opts.ssr === true ? "/api" : "/index.html" }
|
|
257
310
|
]
|
|
258
311
|
};
|
|
259
312
|
}
|
|
@@ -271,7 +324,93 @@ function renderVercelVcConfigJson() {
|
|
|
271
324
|
supportsResponseStreaming: true
|
|
272
325
|
};
|
|
273
326
|
}
|
|
327
|
+
function shouldCopyIntoStatic(source, ssr) {
|
|
328
|
+
if (!ssr) return true;
|
|
329
|
+
return basename(source) !== "index.html";
|
|
330
|
+
}
|
|
331
|
+
function resolveVercelDeps(deps) {
|
|
332
|
+
return {
|
|
333
|
+
runNodeBuild: deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter),
|
|
334
|
+
bundleFunction: deps.bundleFunction ?? bundleDeployedFunction
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
async function buildVercel(config, cwd, deps = {}, ctx) {
|
|
338
|
+
const { runNodeBuild, bundleFunction } = resolveVercelDeps(deps);
|
|
339
|
+
assertServicesUnsupported("vercel", readManifest(cwd));
|
|
340
|
+
await runNodeBuild(config, cwd, ctx);
|
|
341
|
+
const clientDir = resolve(cwd, ".theokit/client");
|
|
342
|
+
const outputDir = resolve(cwd, ".vercel/output");
|
|
343
|
+
mkdirSync(resolve(outputDir, "static"), { recursive: true });
|
|
344
|
+
mkdirSync(resolve(outputDir, "functions/api.func"), { recursive: true });
|
|
345
|
+
if (existsSync(clientDir)) {
|
|
346
|
+
cpSync(clientDir, resolve(outputDir, "static"), {
|
|
347
|
+
recursive: true,
|
|
348
|
+
filter: (source) => shouldCopyIntoStatic(source, config.ssr)
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
const scanned = ctx?.scanRoutes?.(config.serverDir);
|
|
352
|
+
await bundleFunction({
|
|
353
|
+
projectRoot: cwd,
|
|
354
|
+
entrySource: renderVercelFunctionEntry({
|
|
355
|
+
// B-317 — the three options the renderer honoured and no build passed, which is the shape
|
|
356
|
+
// B-185, B-235, B-312 and B-315 each fixed one target at a time. The shell is read here
|
|
357
|
+
// rather than in the renderer because reading a file is the build's job, not a string
|
|
358
|
+
// emitter's.
|
|
359
|
+
ssr: config.ssr,
|
|
360
|
+
...readDocumentShell(cwd, config.ssr),
|
|
361
|
+
routes: scanned?.routes,
|
|
362
|
+
agents: scanned?.agents,
|
|
363
|
+
contextModule: scanned?.contextModule,
|
|
364
|
+
securityHeaders: config.security?.headers,
|
|
365
|
+
// B-315 — the option existed, the renderer honoured it, and this build never passed
|
|
366
|
+
// it, so a project declaring `src/server` got a deployed entry resolving `server`.
|
|
367
|
+
// The fourth occurrence of that exact shape: B-185 (bun, deno), B-235 (`agentsDir`
|
|
368
|
+
// here), B-312 (the build's agents scan). Measured on the emitted Vercel function.
|
|
369
|
+
serverDir: config.serverDir,
|
|
370
|
+
// B-235 — pillar (a): the option existed and no build passed it, so a project with a
|
|
371
|
+
// configured agents directory got the default `agents` on this target. Same defect
|
|
372
|
+
// B-185 fixed for bun and deno, one target over.
|
|
373
|
+
agentsDir: config.agentsDir,
|
|
374
|
+
csrf: config.security?.csrf,
|
|
375
|
+
disallowed: config.security?.disallowed,
|
|
376
|
+
cors: config.security?.cors,
|
|
377
|
+
// #425 — a selector, not a transformer, so it rides as a literal like the values above.
|
|
378
|
+
serialization: config.serialization
|
|
379
|
+
}),
|
|
380
|
+
stagePath: ".theokit/vercel/entry.mjs",
|
|
381
|
+
outDir: resolve(outputDir, "functions/api.func"),
|
|
382
|
+
entryFileName: "index.mjs"
|
|
383
|
+
});
|
|
384
|
+
writeFileSync(
|
|
385
|
+
resolve(outputDir, "functions/api.func/.vc-config.json"),
|
|
386
|
+
JSON.stringify(renderVercelVcConfigJson(), null, 2)
|
|
387
|
+
);
|
|
388
|
+
writeFileSync(
|
|
389
|
+
resolve(outputDir, "config.json"),
|
|
390
|
+
JSON.stringify(renderVercelConfigJson(config.security?.headers, { ssr: config.ssr }), null, 2)
|
|
391
|
+
);
|
|
392
|
+
console.log("\n \u2713 Vercel output \u2192 .vercel/output/");
|
|
393
|
+
console.log(
|
|
394
|
+
`${describeDeployedSecurityHeaders({
|
|
395
|
+
target: "vercel",
|
|
396
|
+
securityHeaders: config.security?.headers,
|
|
397
|
+
// Derived, and it was a literal `false` for the hours between B-317 shipping and B-334. The
|
|
398
|
+
// function B-317 emits calls `generateNonce()` and feeds the value to both `renderStreamingWeb`
|
|
399
|
+
// and `buildSecurityHeaders`, so the deployment DID mint one while the build told the operator
|
|
400
|
+
// it did not — and the printed advice was to move inline scripts out to work around a
|
|
401
|
+
// restriction that was no longer there.
|
|
402
|
+
mintsNonce: config.ssr,
|
|
403
|
+
documentHeaders: "platform-configured"
|
|
404
|
+
})}
|
|
405
|
+
`
|
|
406
|
+
);
|
|
407
|
+
}
|
|
274
408
|
var vercelAdapter = {
|
|
409
|
+
// B-316 / B-319 — Build Output API v3 uploads the `.func` directory as it is: nothing
|
|
410
|
+
// installs and nothing bundles. Driven 2026-09-29 from a directory with no `node_modules`:
|
|
411
|
+
// 200 with the trace header and the CSP (`records/acceptance/evidence/b263-vercel-function-driven-locally.txt`).
|
|
412
|
+
readsSourceAtRunTime: false,
|
|
413
|
+
specifiersResolvedBy: "this-adapter",
|
|
275
414
|
name: "vercel",
|
|
276
415
|
streamsResponses: true,
|
|
277
416
|
// #409 / #410 — the generated entry calls `executeRoute` with routes, loader
|
|
@@ -287,54 +426,15 @@ var vercelAdapter = {
|
|
|
287
426
|
// B-257 — per-invocation: an in-process counter does not survive, so a declared limit needs a durable store.
|
|
288
427
|
enforcesRateLimit: "with-a-store",
|
|
289
428
|
async build(config, cwd, ctx) {
|
|
290
|
-
|
|
291
|
-
await nodeAdapter.build(config, cwd, ctx);
|
|
292
|
-
const clientDir = resolve(cwd, ".theokit/client");
|
|
293
|
-
const outputDir = resolve(cwd, ".vercel/output");
|
|
294
|
-
mkdirSync(resolve(outputDir, "static"), { recursive: true });
|
|
295
|
-
mkdirSync(resolve(outputDir, "functions/api.func"), { recursive: true });
|
|
296
|
-
if (existsSync(clientDir)) {
|
|
297
|
-
cpSync(clientDir, resolve(outputDir, "static"), { recursive: true });
|
|
298
|
-
}
|
|
299
|
-
writeFileSync(
|
|
300
|
-
resolve(outputDir, "functions/api.func/index.mjs"),
|
|
301
|
-
renderVercelFunctionEntry({
|
|
302
|
-
securityHeaders: config.security?.headers,
|
|
303
|
-
// B-235 — pillar (a): the option existed and no build passed it, so a project with a
|
|
304
|
-
// configured agents directory got the default `agents` on this target. Same defect
|
|
305
|
-
// B-185 fixed for bun and deno, one target over.
|
|
306
|
-
agentsDir: config.agentsDir,
|
|
307
|
-
csrf: config.security?.csrf,
|
|
308
|
-
disallowed: config.security?.disallowed,
|
|
309
|
-
cors: config.security?.cors,
|
|
310
|
-
// #425 — a selector, not a transformer, so it rides as a literal like the values above.
|
|
311
|
-
serialization: config.serialization
|
|
312
|
-
})
|
|
313
|
-
);
|
|
314
|
-
writeFileSync(
|
|
315
|
-
resolve(outputDir, "functions/api.func/.vc-config.json"),
|
|
316
|
-
JSON.stringify(renderVercelVcConfigJson(), null, 2)
|
|
317
|
-
);
|
|
318
|
-
writeFileSync(
|
|
319
|
-
resolve(outputDir, "config.json"),
|
|
320
|
-
JSON.stringify(renderVercelConfigJson(config.security?.headers), null, 2)
|
|
321
|
-
);
|
|
322
|
-
console.log("\n \u2713 Vercel output \u2192 .vercel/output/");
|
|
323
|
-
console.log(
|
|
324
|
-
`${describeDeployedSecurityHeaders({
|
|
325
|
-
target: "vercel",
|
|
326
|
-
securityHeaders: config.security?.headers,
|
|
327
|
-
mintsNonce: false,
|
|
328
|
-
documentHeaders: "platform-configured"
|
|
329
|
-
})}
|
|
330
|
-
`
|
|
331
|
-
);
|
|
429
|
+
return buildVercel(config, cwd, {}, ctx);
|
|
332
430
|
}
|
|
333
431
|
};
|
|
334
432
|
export {
|
|
433
|
+
buildVercel,
|
|
335
434
|
renderVercelConfigJson,
|
|
336
435
|
renderVercelFunctionEntry,
|
|
337
436
|
renderVercelVcConfigJson,
|
|
437
|
+
shouldCopyIntoStatic,
|
|
338
438
|
vercelAdapter
|
|
339
439
|
};
|
|
340
|
-
//# sourceMappingURL=vercel-
|
|
440
|
+
//# sourceMappingURL=vercel-VLR52RXT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/vercel.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Vercel deploy adapter. All paths derived from `cwd` and a fixed\n * `.theokit/vercel/` output layout. Build-time tool — no HTTP input.\n */\nimport { existsSync, mkdirSync, writeFileSync, cpSync } from 'node:fs'\nimport { basename, resolve } from 'node:path'\n\nimport type { TheoConfig } from '../config/schema.js'\nimport type { SecurityHeadersConfig } from '../core/contracts/security-headers.js'\nimport { assertServicesUnsupported, readManifest } from '../services/index.js'\n\nimport {\n bundleDeployedFunction,\n type BundleDeployedFunctionOptions,\n} from './bundle-deployed-function.js'\nimport { deployedAgentsFragment, JSON_NOT_FOUND_RESPONSE } from './deployed-agents.js'\nimport { renderBakedRoutes, routeRuntimeLines, type BakedRoute } from './deployed-baked-routes.js'\nimport { readDocumentShell } from './deployed-document-shell.js'\nimport { deployedEntryPreamble } from './deployed-preamble.js'\nimport {\n deployedRateLimitFragment,\n rateLimitCheckFragment,\n type DeployedRateLimitOptions,\n} from './deployed-rate-limit.js'\nimport { deployedRuntimeConfigFragment, serverDirLiteral } from './deployed-runtime-config.js'\nimport { deployedTraceFragment } from './deployed-trace.js'\nimport { nodeAdapter } from './node.js'\nimport { buildSecurityHeaders, describeDeployedSecurityHeaders } from './security-headers.js'\nimport type { AdapterBuildContext, DeployAdapter, DeployedEntryOptions } from './types.js'\n\n/**\n * T2.2 — Vercel adapter rewritten to consume `theokit/adapters/web-shim`\n * instead of emitting an inline plain-object Request/Response shim and\n * lazy-importing internal `theo-server/` paths.\n */\n\n// Generated-code fragments — extracted so the parent emitter stays under the\n// max-lines-per-function ceiling.\n/** The exported function Vercel invokes: one security-header call, then the drain. */\nfunction vercelHandlerFragment(\n /** B-027 — passed, not read: this is a separate function from the parent emitter. */\n rateLimit: DeployedRateLimitOptions['rateLimit'],\n): string[] {\n return [\n // B-027 — only when a limit is declared. `createRateLimiterWeb` is used at module scope by\n // the fragment; `resolveClientIpFromRequest` reads the forwarded headers behind `trustProxy`.\n ...(rateLimit === undefined\n ? []\n : [\n `import { createRateLimiterWeb } from 'theokit/server/rate-limit'`,\n `import { resolveClientIpFromRequest } from 'theokit/server/rate-limit'`,\n ]),\n ...deployedRateLimitFragment(\n rateLimit,\n 'vercel',\n // The handler builds a real Web `Request` at the top — `corsRequest` — so the exported Web\n // resolver applies directly and nothing new has to parse a header. The plan expected a Node\n // sibling here on the ground that this handler \"has no Web Request\"; reading the emitted code\n // refuted that. With no `trustProxy` declared the resolver returns `undefined`, which is the\n // named 503: on this platform the socket address is always the platform's proxy, so a\n // fallback to it would be one shared bucket wearing a client's clothes.\n `resolveClientIpFromRequest(corsRequest, TRUST_PROXY)`,\n 'corsRequest',\n ),\n ...(rateLimit === undefined\n ? []\n : [\n ``,\n `/**`,\n ` * Write a small, known response and finish.`,\n ` *`,\n ` * Not the drain below: that one exists to stream an arbitrary route response chunk by`,\n ` * chunk, honouring backpressure. A 429 or a 503 is a short JSON literal, so reusing the`,\n ` * streaming path would buy nothing and duplicating it would be worse.`,\n ` */`,\n `async function sendSmall(res, response) {`,\n ` const h = {}`,\n ` response.headers.forEach((v, k) => { h[k] = v })`,\n ` res.writeHead(response.status, h)`,\n ` res.end(await response.text())`,\n `}`,\n ]),\n ``,\n `export default async function handler(nodeReq, nodeRes) {`,\n ` // #409 — CORS reads only the method and the \\`origin\\` / \\`access-control-request-method\\``,\n ` // headers, so this carries exactly those and no body. It is deliberately NOT the routing`,\n ` // Request: that one drains the request stream, and only after a route matched — building it`,\n ` // here would drain the body of every static path too.`,\n ` const corsHeaders = new Headers()`,\n ` for (const [k, v] of Object.entries(nodeReq.headers ?? {})) {`,\n ` if (typeof v === 'string') corsHeaders.set(k, v)`,\n ` }`,\n ` const corsRequest = new Request(`,\n ` new URL(nodeReq.url ?? '/', 'http://' + (nodeReq.headers?.host ?? 'localhost')),`,\n ` { method: (nodeReq.method ?? 'GET').toUpperCase(), headers: corsHeaders },`,\n ` )`,\n ``,\n ` // The preflight is answered BEFORE anything routes: an OPTIONS the router handles is an`,\n ` // OPTIONS the browser never gets a CORS answer to.`,\n ` const preflight = corsPreflight(corsRequest)`,\n ...rateLimitCheckFragment(\n rateLimit,\n ' ',\n 'corsRequest',\n // This handler returns NOTHING — it drains into `nodeRes`. A bare `return <Response>` would\n // answer the caller with nothing at all.\n 'return sendSmall(nodeRes, withCors(corsRequest, withSecurityHeaders(rateLimited(limit), SECURITY_HEADERS)))',\n 'return sendSmall(nodeRes, withCors(corsRequest, withSecurityHeaders(unnamedCaller(), SECURITY_HEADERS)))',\n ),\n ` const webResponse = preflight !== null`,\n ` ? withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ` : withCors(corsRequest, withSecurityHeaders(await routeRequest(nodeReq), SECURITY_HEADERS))`,\n ``,\n ` // \\`outHeaders\\`, not \\`headers\\`: this used to live in the same scope as the`,\n ` // request-side \\`const headers\\` below, which made the whole module a`,\n ` // SyntaxError — every Vercel build between #382 and #411 emitted a function`,\n ` // that could not be loaded.`,\n ` const outHeaders = {}`,\n ` webResponse.headers.forEach((v, k) => { outHeaders[k] = v })`,\n ` nodeRes.writeHead(webResponse.status, outHeaders)`,\n ` if (typeof nodeRes.flushHeaders === 'function') nodeRes.flushHeaders()`,\n ``,\n ` // #382 — this used to materialize the entire body as a string and hand`,\n ` // it to a single end(), which re-buffered the whole response inside the`,\n ` // function even after the shim was fixed. Drain chunk by chunk instead,`,\n ` // honouring Node backpressure so a slow client cannot grow the queue.`,\n ` if (webResponse.body === null) {`,\n ` nodeRes.end()`,\n ` return`,\n ` }`,\n ` const reader = webResponse.body.getReader()`,\n ` try {`,\n ` for (;;) {`,\n ` const { done, value } = await reader.read()`,\n ` if (done) break`,\n ` if (nodeRes.write(value) === false) {`,\n ` await new Promise((resolveDrain) => {`,\n ` const finish = () => {`,\n ` nodeRes.off('drain', finish)`,\n ` nodeRes.off('close', finish)`,\n ` nodeRes.off('error', finish)`,\n ` resolveDrain()`,\n ` }`,\n ` nodeRes.once('drain', finish)`,\n ` nodeRes.once('close', finish)`,\n ` nodeRes.once('error', finish)`,\n ` })`,\n ` }`,\n ` }`,\n ` nodeRes.end()`,\n ` } catch (streamErr) {`,\n ` // The handler failed after the head went out. Destroying the socket is`,\n ` // the only signal left that the body is incomplete — ending normally`,\n ` // would report a truncated response as a complete one (ADR-0002).`,\n ` nodeRes.destroy(streamErr)`,\n ` } finally {`,\n ` reader.releaseLock()`,\n ` }`,\n `}`,\n ``,\n ]\n}\n\n// Generated-code fragments — extracted so the parent emitter stays under the\n// max-lines-per-function ceiling.\n/** Everything that decides WHAT the response is, as a Web Response for every outcome. */\nfunction vercelRouteRequestFragment(\n runtimeSpread: string,\n agentsBranch: readonly string[],\n agentsHostBypass: string,\n /**\n * The document shell, when this function renders one (B-317).\n *\n * Its PRESENCE is the signal rather than a separate boolean: a shell with no renderer and a\n * renderer with no shell are both states this cannot be in, and a flag beside the data would\n * allow them.\n */\n document?: { htmlHead?: string; htmlTail?: string },\n): string[] {\n return [\n `async function routeRequest(nodeReq) {`,\n ` const url = new URL(nodeReq.url ?? '/', 'http://' + (nodeReq.headers?.host ?? 'localhost'))`,\n ``,\n // B-317 — emitted only when this function does NOT render the document. With a document branch\n // every path is legitimate: `/api/*` is a route and everything else is a page, so refusing\n // non-`/api` paths here would make that branch unreachable — which is exactly what it did, and\n // the first version of the fix shipped it: the branch was present, asserted present, and never\n // entered. `/` answered this 9-byte `Not Found` instead of a document.\n ...(document === undefined\n ? [\n ` if (!url.pathname.startsWith('/api/')${agentsHostBypass}) {`,\n ` return new Response('Not Found', {`,\n ` status: 404,`,\n ` headers: { 'content-type': 'text/plain; charset=utf-8' },`,\n ` })`,\n ` }`,\n ]\n : []),\n ``,\n ``,\n // B-235 — the Node-to-Web conversion is hoisted ABOVE the agents branch, which names\n // `request` like every other host's, and an agent path never reaches a route match. The\n // rename from `webRequest` is what lets this target share the one fragment instead of a\n // fourth near-copy of it.\n //\n // The body is therefore drained before `matchRoute` rather than after, so an unmatched POST\n // now has its body read. That is a real change and the safer direction: an unconsumed Node\n // request socket is what keeps a connection open, and the drain already happened for every\n // request that matched.\n ` // Convert Node-style req to a Web Request — for the agents branch and for the shim`,\n ` const headers = new Headers()`,\n ` for (const [k, v] of Object.entries(nodeReq.headers ?? {})) {`,\n ` if (typeof v === 'string') headers.set(k, v)`,\n ` }`,\n ` let body`,\n ` const method = (nodeReq.method ?? 'GET').toUpperCase()`,\n ` if (method !== 'GET' && method !== 'HEAD') {`,\n ` const chunks = []`,\n ` await new Promise((resolveProm, rejectProm) => {`,\n ` nodeReq.on('data', (c) => chunks.push(c))`,\n ` nodeReq.on('end', () => resolveProm())`,\n ` nodeReq.on('error', rejectProm)`,\n ` })`,\n ` body = Buffer.concat(chunks)`,\n ` }`,\n ` const request = new Request(url.toString(), { method, headers, body })`,\n ``,\n ...agentsBranch,\n ``,\n ` const match = matchRoute(url.pathname, routes)`,\n ...(document !== undefined\n ? [\n ` if (!match) {`,\n ` // B-317 — a path with no matching file arrives here because config.json routes it to this`,\n ` // function. Before this branch it answered a JSON 404, so the config sent every page to the`,\n ` // static shell instead and an SSR project was served an empty \\`<div id=\"root\">\\` while the`,\n ` // build announced SSR.`,\n ` //`,\n ` // Only OUTSIDE \\`/api/\\`: a path under it that matches no route is a routing miss and owes a`,\n ` // JSON 404, not a document. Rendering one there would answer a fetch with HTML.`,\n ` if (!url.pathname.startsWith('/api/')) {`,\n ` const nonce = generateNonce()`,\n ` return withSecurityHeaders(`,\n ` await renderStreamingWeb(request, {`,\n ` htmlHead: ${JSON.stringify(document.htmlHead ?? '')},`,\n ` htmlTail: ${JSON.stringify(document.htmlTail ?? '')},`,\n ` nonce,`,\n ` }),`,\n ` buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true }, { nonce }),`,\n ` )`,\n ` }`,\n ` return ${JSON_NOT_FOUND_RESPONSE}`,\n ` }`,\n ]\n : [` if (!match) return ${JSON_NOT_FOUND_RESPONSE}`]),\n ``,\n ` const { req, res, toResponse } = createWebShim(request)`,\n ...deployedTraceFragment('request', ' '),\n ` // #382 — executeRoute() is NOT awaited before the Response is taken:`,\n ` // toResponse() settles at the headers and carries a live body.`,\n ` return toResponse(executeRoute({`,\n ` route: match.route, method, params: match.params,`,\n ` req, res, loadModule, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread}`,\n ` }))`,\n `}`,\n ]\n}\n\nexport function renderVercelFunctionEntry(\n opts: DeployedEntryOptions & {\n /**\n * The routes, scanned on the BUILD machine (B-319).\n *\n * Build Output API v3 uploads a `.func` directory as it is, so the emitted entry's runtime\n * `scanServerRoutes` was a `readdirSync` against a directory that is not there — measured on a\n * deployed function: every `/api/*` answered its own JSON 404. Baked here for the reason\n * Cloudflare bakes (#369), through the same emitter, so the two cannot drift.\n */\n routes?: readonly BakedRoute[]\n /** The agents, for the same reason and from the same scan. */\n agents?: readonly { filePath: string; agentPath: string; name: string }[]\n /**\n * Whether this function renders the DOCUMENT as well as the routes (B-317).\n *\n * `renderVercelConfigJson` sends a path with no matching file here when it is on, and Vercel's\n * `{ handle: 'filesystem' }` has already served every real file — so the branch below needs no\n * asset fallthrough, unlike the Cloudflare worker's, which owns `/` and therefore also receives\n * `/robots.txt`.\n */\n ssr?: boolean\n /** The document up to `<div id=\"root\">`, read from the built client shell. */\n htmlHead?: string\n /** The document from `<div id=\"root\">` on. */\n htmlTail?: string\n /** The app's identity module, when it has one. */\n contextModule?: string\n } = {},\n): string {\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n const { routeImports, routeModuleEntries, routeTableEntries } = renderBakedRoutes(\n opts.routes ?? [],\n )\n // B-235. This is the target the item's evidence was right about in form and wrong about in\n // consequence: the handler IS Node-shaped, and it already converts to a Web `Request` before\n // handing anything to the shim. Threading `nodeReq` through twelve sites says how the entry\n // RECEIVES a request, not whether it can produce the one this branch needs.\n // B-319 — ALWAYS baked, with no scan fallback. This platform uploads only what the build\n // bundled, so `scanAgents` cannot work here at any value: there is no source tree to read. A\n // fallback would preserve a behaviour that is broken by construction — an entry that scans, finds\n // nothing, and answers 404 while looking like it tried. With nothing baked the agents fragment is\n // empty, `/api/agents/<name>` falls through to the route matcher, and the 404 is honest.\n const agentsFragment = deployedAgentsFragment(\n { kind: 'baked', agents: opts.agents ?? [], contextModule: opts.contextModule },\n { notFound: JSON_NOT_FOUND_RESPONSE },\n )\n return [\n `// Generated by Theo — Vercel Functions adapter`,\n `// Environment variables are resolved at RUNTIME, not build time.`,\n ``,\n `import { resolve } from 'node:path'`,\n `import { matchRoute, compilePattern } from 'theokit/server/scan'\\nimport { executeRoute, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server/http'`,\n ...routeImports,\n `import { createWebShim } from 'theokit/adapters/web-shim'`,\n opts.ssr === true\n ? `import { buildSecurityHeaders, generateNonce, withSecurityHeaders } from 'theokit/adapters/security-headers'`\n : `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,\n ...(opts.ssr === true\n ? [`import { renderStreamingWeb } from '../server/entry-server.js'`]\n : []),\n ``,\n ...routeRuntimeLines(routeModuleEntries, routeTableEntries, 'vercel'),\n // B-318 / B-319 — `const cwd` used to be declared here, because the agents fragment emitted\n // `scanAgents(cwd, …)` and this was the one of its four callers that never declared the name.\n // B-319 then removed the scan entirely from this target — there is no source tree to read on a\n // platform that uploads only its bundle — so the declaration became dead code. The pairing is\n // still enforced for the three adapters that DO scan, by\n // `tests/unit/a-generated-entry-declares-every-name-it-uses.test.ts`.\n `const serverDir = resolve(process.cwd(), ${serverDirLiteral(opts)})`,\n ``,\n `// #410 — the security baseline \\`theokit start\\` puts on every response,`,\n `// carried here as a literal because the deployed function has no`,\n `// theo.config.ts to read. config.json routes only /api/* here, so this`,\n `// covers the API and not the document Vercel's static host serves`,\n `// (usetheokit/theokit#412).`,\n ...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, 'vercel'),\n ``,\n `// Vercel Functions invoke this default export with a (req, res) pair`,\n `// (Node IncomingMessage-style). \\`routeRequest\\` produces a Web Response for`,\n `// every outcome — including the two 404s — so the security baseline is`,\n `// applied at ONE place and no branch can be added that skips it.`,\n ...vercelHandlerFragment(opts.rateLimit),\n ``,\n ...vercelRouteRequestFragment(\n runtimeConfig.executeRouteSpread,\n agentsFragment.branch,\n agentsFragment.hostBypass,\n opts.ssr === true ? { htmlHead: opts.htmlHead, htmlTail: opts.htmlTail } : undefined,\n ),\n ].join('\\n')\n}\n\nexport interface VercelRoutingRule {\n src?: string\n dest?: string\n handle?: string\n /** Build Output API v3 — response headers this rule adds. */\n headers?: Record<string, string>\n /**\n * Keep routing after this rule matches.\n *\n * Load-bearing for the header rule: without it a matching rule TERMINATES routing in Build\n * Output v3, so every request would receive the headers and no content.\n */\n continue?: boolean\n}\n\n/**\n * The routing table, plus the security baseline for the responses this build does NOT serve.\n *\n * The emitted function applies the baseline to every response IT returns — and it never returns the\n * HTML document: `{ handle: 'filesystem' }` hands the page to Vercel's static host, so the JSON was\n * protected and the page it renders in was not (usetheokit/theokit#412).\n *\n * The values come from `buildSecurityHeaders`, the same function the handler calls, rather than\n * being written out here. Two lists of headers that must agree are two lists that eventually do\n * not.\n *\n * Order matters twice: the header rule sits FIRST, because a rule after `handle: 'filesystem'`\n * never runs for a static file, and it carries `continue: true`, because a matching rule otherwise\n * ends routing and the request would get headers with no body.\n *\n * What this does NOT prove: that a deployed page carries them. That needs a deployment, and this\n * repository deploys to no Vercel project from CI. The emitted configuration is verifiable; the\n * platform honouring it is not, and the difference is stated rather than glossed.\n */\nexport function renderVercelConfigJson(\n securityHeaders?: SecurityHeadersConfig,\n opts: {\n /**\n * Whether a path with no matching file reaches the function instead of the static shell.\n *\n * A SECOND parameter rather than a field on the first, and the reason is a trap: the first is\n * `SecurityHeadersConfig`, which is all-optional, so `renderVercelConfigJson({ ssr: true })`\n * compiles, passes the flag as a headers object and does nothing. A bag in the position of another\n * all-optional bag is accepted by the type system and ignored by the code (B-317).\n */\n ssr?: boolean\n } = {},\n): {\n version: number\n routes: VercelRoutingRule[]\n} {\n return {\n version: 3,\n routes: [\n {\n src: '/(.*)',\n headers: buildSecurityHeaders(securityHeaders ?? {}, { production: true }),\n continue: true,\n },\n { src: '/api/(.*)', dest: '/api' },\n { handle: 'filesystem' },\n // B-317 — where a path with no matching file goes. `{ handle: 'filesystem' }` above still\n // serves every real file, so this is reached only by a page request: to the function when the\n // project renders one, and to the static shell when it does not. It sent every page to the shell\n // regardless, so an SSR project was served an empty `<div id=\"root\">` while the build announced\n // SSR.\n { src: '/(.*)', dest: opts.ssr === true ? '/api' : '/index.html' },\n ],\n }\n}\n\nexport function renderVercelVcConfigJson(): {\n runtime: string\n handler: string\n launcherType: string\n shouldAddHelpers: boolean\n supportsResponseStreaming: boolean\n} {\n return {\n runtime: 'nodejs22.x',\n handler: 'index.mjs',\n launcherType: 'Nodejs',\n shouldAddHelpers: true,\n // #382 — Build Output API v3 opt-in. Without it the platform buffers the\n // function's response no matter how the handler writes it, so the emitted\n // chunk-by-chunk drain above would never reach the client. We cannot\n // verify the platform side from here; see the streaming note in\n // `adapters/web-shim.ts` and the adapter's `streamsResponses` flag.\n supportsResponseStreaming: true,\n }\n}\n\n/**\n * Whether a file from the client build belongs in `.vercel/output/static`.\n *\n * With `ssr: true` the shell does NOT, and the reason is the routing layer rather than the file:\n * Vercel's `{ handle: 'filesystem' }` satisfies a directory path with the `index.html` inside it, so\n * `/` is a REAL FILE whenever the build copied one — and the SSR route below the handler is never\n * reached. Measured on the first real deploy of this adapter, 2026-09-29: `GET /` answered 200 with\n * 694 bytes and `<div id=\"root\">` carrying zero, while the build announced `(SSR)`.\n *\n * B-317 already made the last route point at the function when `ssr` is on, and its comment states\n * the premise that made that sufficient — *\"`{ handle: 'filesystem' }` above still serves every real\n * file, so this is reached only by a page request\"*. That premise is false for a path the platform\n * resolves to an `index.html`. This closes the half B-317 could not see without a deployment.\n *\n * **The basename is the mechanism, not a heuristic.** It is what the platform uses to satisfy a\n * directory path, so it is what shadows a page route, at any depth. `foo.html` is served at the\n * explicit `/foo.html`, which no page route claims, and dropping it would take a document the\n * project meant to publish.\n *\n * Directories always pass: `cpSync`'s filter is asked about them too, and refusing one prunes the\n * whole subtree — refusing `assets/` would turn one empty page into a site with no stylesheet.\n */\nexport function shouldCopyIntoStatic(source: string, ssr: boolean): boolean {\n if (!ssr) return true\n return basename(source) !== 'index.html'\n}\n\nexport interface VercelBuildDeps {\n runNodeBuild?: (config: TheoConfig, cwd: string, ctx?: AdapterBuildContext) => Promise<void>\n bundleFunction?: (options: BundleDeployedFunctionOptions) => Promise<void>\n}\n\n/**\n * The Vercel build, as a function with a dependency seam — the shape `buildNetlify` and\n * `buildAwsLambda` already have.\n *\n * It was inline on the adapter object until B-346, and nothing could drive it: measured, NO test\n * ran it to completion, so `buildVercel` carried zero coverage while a defect shipped inside it and\n * reached a live deployment. The seam is what lets a test assert the wiring — that the copy is\n * handed the filter that withholds the shell — without a client bundle.\n */\n/**\n * The injectable seam's defaults, in one place.\n *\n * The same shape `resolveNetlifyDeps` and `resolveAwsLambdaDeps` already have, and here for the same\n * reason plus one measured one: the two `??` defaults lived inside `buildVercel`, which put it at a\n * complexity of 16 against a maximum of 15. The body was unchanged from the method it was extracted\n * from — 14 — so the seam that made the copy testable is what crossed the line. Moving the defaults\n * out is the convention this file was not following, not a contortion to satisfy the counter.\n */\nfunction resolveVercelDeps(deps: VercelBuildDeps): {\n runNodeBuild: NonNullable<VercelBuildDeps['runNodeBuild']>\n bundleFunction: NonNullable<VercelBuildDeps['bundleFunction']>\n} {\n return {\n runNodeBuild: deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter),\n bundleFunction: deps.bundleFunction ?? bundleDeployedFunction,\n }\n}\n\nexport async function buildVercel(\n config: TheoConfig,\n cwd: string,\n deps: VercelBuildDeps = {},\n ctx?: AdapterBuildContext,\n): Promise<void> {\n const { runNodeBuild, bundleFunction } = resolveVercelDeps(deps)\n\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n // Per 2026-05-27 owner decision, polyglot is wired via `node` (local\n // docker-compose harness) + `theo-cloud` (Wave 3). Vercel adapter\n // wire-up is deferred to a fresh ADR with demand evidence.\n assertServicesUnsupported('vercel', readManifest(cwd))\n\n // 1. Run the standard Node build first (ctx forwarded so nodeAdapter has makeVitePlugins)\n await runNodeBuild(config, cwd, ctx)\n\n const clientDir = resolve(cwd, '.theokit/client')\n const outputDir = resolve(cwd, '.vercel/output')\n\n // 2. Create .vercel/output structure\n mkdirSync(resolve(outputDir, 'static'), { recursive: true })\n mkdirSync(resolve(outputDir, 'functions/api.func'), { recursive: true })\n\n // 3. Copy static assets\n if (existsSync(clientDir)) {\n // B-346 — the shell is withheld when this project renders its own document. See\n // `shouldCopyIntoStatic`: shipping it makes `/` a real file, and the SSR route never runs.\n cpSync(clientDir, resolve(outputDir, 'static'), {\n recursive: true,\n filter: (source) => shouldCopyIntoStatic(source, config.ssr),\n })\n }\n\n // B-319 — the routes, agents and identity module are resolved HERE, on the build machine, for\n // the reason #369 gives for Cloudflare: Build Output API v3 uploads the `.func` directory as it\n // is, so a runtime `scanServerRoutes` reads a directory that is not there. Measured on a\n // deployed function — every `/api/*` answered its own JSON 404 with the route files present in\n // the project. An absent provider bakes nothing and the entry falls back to the scan, which is\n // what it did before.\n const scanned = ctx?.scanRoutes?.(config.serverDir)\n\n // 4. Emit the serverless function, BUNDLED.\n //\n // B-316 / ADR 0020 — Build Output API v3 uploads a `.func` directory as it is: nothing installs\n // dependencies for it and nothing bundles it. Writing the rendered entry straight out produced a\n // function that could not start, measured on this repository's own scaffold:\n //\n // cp -a .vercel/output/functions/api.func/. /tmp/fn/ && cd /tmp/fn\n // node -e \"import('./index.mjs')\"\n // -> ERR_MODULE_NOT_FOUND: Cannot find package 'theokit'\n //\n // The staged entry goes inside the project root because a specifier resolves relative to the\n // importing file — an entry in `/tmp` makes rollup resolve `theokit/server/scan` from `/tmp`.\n await bundleFunction({\n projectRoot: cwd,\n entrySource: renderVercelFunctionEntry({\n // B-317 — the three options the renderer honoured and no build passed, which is the shape\n // B-185, B-235, B-312 and B-315 each fixed one target at a time. The shell is read here\n // rather than in the renderer because reading a file is the build's job, not a string\n // emitter's.\n ssr: config.ssr,\n ...readDocumentShell(cwd, config.ssr),\n routes: scanned?.routes,\n agents: scanned?.agents,\n contextModule: scanned?.contextModule,\n securityHeaders: config.security?.headers,\n // B-315 — the option existed, the renderer honoured it, and this build never passed\n // it, so a project declaring `src/server` got a deployed entry resolving `server`.\n // The fourth occurrence of that exact shape: B-185 (bun, deno), B-235 (`agentsDir`\n // here), B-312 (the build's agents scan). Measured on the emitted Vercel function.\n serverDir: config.serverDir,\n // B-235 — pillar (a): the option existed and no build passed it, so a project with a\n // configured agents directory got the default `agents` on this target. Same defect\n // B-185 fixed for bun and deno, one target over.\n agentsDir: config.agentsDir,\n csrf: config.security?.csrf,\n disallowed: config.security?.disallowed,\n cors: config.security?.cors,\n // #425 — a selector, not a transformer, so it rides as a literal like the values above.\n serialization: config.serialization,\n }),\n stagePath: '.theokit/vercel/entry.mjs',\n outDir: resolve(outputDir, 'functions/api.func'),\n entryFileName: 'index.mjs',\n })\n\n // 5. Emit .vc-config.json\n writeFileSync(\n resolve(outputDir, 'functions/api.func/.vc-config.json'),\n JSON.stringify(renderVercelVcConfigJson(), null, 2),\n )\n\n // 6. Emit config.json (routing)\n writeFileSync(\n resolve(outputDir, 'config.json'),\n JSON.stringify(renderVercelConfigJson(config.security?.headers, { ssr: config.ssr }), null, 2),\n )\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ Vercel output → .vercel/output/')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'vercel',\n securityHeaders: config.security?.headers,\n // Derived, and it was a literal `false` for the hours between B-317 shipping and B-334. The\n // function B-317 emits calls `generateNonce()` and feeds the value to both `renderStreamingWeb`\n // and `buildSecurityHeaders`, so the deployment DID mint one while the build told the operator\n // it did not — and the printed advice was to move inline scripts out to work around a\n // restriction that was no longer there.\n mintsNonce: config.ssr,\n documentHeaders: 'platform-configured',\n })}\\n`,\n )\n}\n\nexport const vercelAdapter: DeployAdapter = {\n // B-316 / B-319 — Build Output API v3 uploads the `.func` directory as it is: nothing\n // installs and nothing bundles. Driven 2026-09-29 from a directory with no `node_modules`:\n // 200 with the trace header and the CSP (`records/acceptance/evidence/b263-vercel-function-driven-locally.txt`).\n readsSourceAtRunTime: false,\n specifiersResolvedBy: 'this-adapter',\n name: 'vercel',\n streamsResponses: true,\n // #409 / #410 — the generated entry calls `executeRoute` with routes, loader\n // and serverDir only. CSRF, route policy, file middleware and Zod validation\n // still run because they live inside `executeRoute`; none of the remaining\n // configurable concerns reach it. Declared explicitly rather than omitted so\n // the gap is a statement in the source and not an absence.\n //\n // `securityHeaders` IS applied -- to every response this function returns.\n // The document is served from `.vercel/output/static` and does not pass\n // through it (usetheokit/theokit#412).\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization'],\n // B-257 — per-invocation: an in-process counter does not survive, so a declared limit needs a durable store.\n enforcesRateLimit: 'with-a-store',\n\n async build(config: TheoConfig, cwd: string, ctx?: AdapterBuildContext): Promise<void> {\n return buildVercel(config, cwd, {}, ctx)\n },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
defineTheoIntegration,
|
|
6
6
|
theoPlugin,
|
|
7
7
|
theoPluginAsync
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-S5QN3O22.js";
|
|
9
9
|
import "../chunk-7NRFZBAL.js";
|
|
10
10
|
import "../chunk-SSYDEKWF.js";
|
|
11
11
|
import "../chunk-D7STTNQN.js";
|
|
12
|
-
import "../chunk-
|
|
13
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-HK57MPSZ.js";
|
|
13
|
+
import "../chunk-2NG5T77O.js";
|
|
14
14
|
import "../chunk-OIGJOYX6.js";
|
|
15
15
|
import "../chunk-U3SPBLJF.js";
|
|
16
16
|
import "../chunk-WSOAN4KN.js";
|
|
@@ -30,8 +30,8 @@ import "../chunk-AVQU5CQF.js";
|
|
|
30
30
|
import "../chunk-VSLTKX5L.js";
|
|
31
31
|
import "../chunk-SFGGRC35.js";
|
|
32
32
|
import "../chunk-4ERYQBL6.js";
|
|
33
|
-
import "../chunk-
|
|
34
|
-
import "../chunk-
|
|
33
|
+
import "../chunk-V7ISZGNS.js";
|
|
34
|
+
import "../chunk-6R5F5YF2.js";
|
|
35
35
|
import "../chunk-DV34VG3N.js";
|
|
36
36
|
import "../chunk-V6Y2SMRG.js";
|
|
37
37
|
import "../chunk-ACKBVBUI.js";
|
|
@@ -7,22 +7,22 @@ import {
|
|
|
7
7
|
defineTheoIntegration,
|
|
8
8
|
theoPlugin,
|
|
9
9
|
theoPluginAsync
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-RFZ263XP.js";
|
|
11
|
+
import "./chunk-QAS5SKZP.js";
|
|
12
12
|
import "./chunk-BDH5GKFZ.js";
|
|
13
13
|
import "./chunk-3PWQQWT6.js";
|
|
14
14
|
import "./chunk-FDOOBTXJ.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-SHIXTMQE.js";
|
|
16
16
|
import "./chunk-BINRCILF.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-FNJVSFEC.js";
|
|
18
18
|
import "./chunk-WSMLSIS5.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-MX63AWEK.js";
|
|
20
20
|
import "./chunk-C27VRUVN.js";
|
|
21
21
|
import "./chunk-7UZZHCRN.js";
|
|
22
22
|
import "./chunk-47MM2JUK.js";
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-WR5B2XNT.js";
|
|
24
|
+
import "./chunk-HKF6YNY4.js";
|
|
25
|
+
import "./chunk-4WP7A7RX.js";
|
|
26
26
|
import "./chunk-Z7CJHDLS.js";
|
|
27
27
|
import "./chunk-SZWGXHY3.js";
|
|
28
28
|
import "./chunk-3QPVEJ7D.js";
|
|
@@ -40,4 +40,4 @@ export {
|
|
|
40
40
|
theoPlugin,
|
|
41
41
|
theoPluginAsync
|
|
42
42
|
};
|
|
43
|
-
//# sourceMappingURL=vite-plugin-
|
|
43
|
+
//# sourceMappingURL=vite-plugin-JVGI6QUO.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theokit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
4
4
|
"description": "The TheoKit web framework — file-based routing, typed server surfaces, the Vite plugin, the CLI and the deploy adapters, around agents served from agents/*.ts.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -150,12 +150,12 @@
|
|
|
150
150
|
"tsx": "^4.22.4",
|
|
151
151
|
"typescript": "^5.9.3",
|
|
152
152
|
"vite": "^7.0.0",
|
|
153
|
-
"@theokit/agents": "^15.0.
|
|
153
|
+
"@theokit/agents": "^15.0.2",
|
|
154
154
|
"@theokit/http": "^2.3.0",
|
|
155
155
|
"@theokit/presenter": "^0.10.0"
|
|
156
156
|
},
|
|
157
157
|
"peerDependencies": {
|
|
158
|
-
"@theokit/sdk": "^5.
|
|
158
|
+
"@theokit/sdk": "^5.9.2",
|
|
159
159
|
"@theokit/ui": "^1.1.0",
|
|
160
160
|
"db0": "^0.3.0",
|
|
161
161
|
"react": "^19.0.0",
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
}
|
|
184
184
|
},
|
|
185
185
|
"devDependencies": {
|
|
186
|
-
"@theokit/sdk": "^5.
|
|
186
|
+
"@theokit/sdk": "^5.9.2",
|
|
187
187
|
"@types/busboy": "^1.5.4",
|
|
188
188
|
"@types/picomatch": "^4.0.3",
|
|
189
189
|
"better-sqlite3": "^12.11.1",
|