theokit 0.68.0 → 0.69.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 +21 -0
- package/dist/{actions-virtual-module-SE44BKR4.js → actions-virtual-module-DH3N34I6.js} +6 -6
- package/dist/{actions-virtual-module-3OPYLD76.js → actions-virtual-module-OMIFGXK6.js} +3 -3
- package/dist/adapters/agent-mount.d.ts +190 -2
- package/dist/adapters/agent-mount.js +18 -3
- package/dist/adapters/security-headers.d.ts +17 -1
- package/dist/adapters/security-headers.js +7 -0
- package/dist/adapters/security-headers.js.map +1 -1
- package/dist/{agent-UBDDP2L5.js → agent-7RPGAKTY.js} +3 -3
- package/dist/{app-typed-client-RAFEBA7S.js → app-typed-client-C4LRUSIS.js} +6 -6
- package/dist/{app-typed-client-BE3PV3JY.js → app-typed-client-R6OUJZEE.js} +3 -3
- package/dist/{aws-lambda-R76PWR27.js → aws-lambda-OCJM5YGB.js} +35 -23
- package/dist/aws-lambda-OCJM5YGB.js.map +1 -0
- package/dist/{build-U4HVYY6F.js → build-CGFKWZ73.js} +10 -5
- package/dist/build-CGFKWZ73.js.map +1 -0
- package/dist/{bun-NPBIAWSU.js → bun-KRUAWYRW.js} +51 -39
- package/dist/bun-KRUAWYRW.js.map +1 -0
- package/dist/{chunk-GQNBZDYK.js → chunk-2FHNJ7LI.js} +1 -1
- package/dist/{chunk-GQNBZDYK.js.map → chunk-2FHNJ7LI.js.map} +1 -1
- package/dist/chunk-3T5XLDOH.js +807 -0
- package/dist/chunk-3T5XLDOH.js.map +1 -0
- package/dist/{chunk-GDF2XQOO.js → chunk-425FJKKO.js} +5 -3
- package/dist/chunk-425FJKKO.js.map +1 -0
- package/dist/{chunk-7THO4PRL.js → chunk-4WB62S22.js} +7 -4
- package/dist/{chunk-7THO4PRL.js.map → chunk-4WB62S22.js.map} +1 -1
- package/dist/chunk-BDPD5HEO.js +554 -0
- package/dist/chunk-BDPD5HEO.js.map +1 -0
- package/dist/{chunk-UETVDZBE.js → chunk-BINRCILF.js} +4 -1
- package/dist/{chunk-UETVDZBE.js.map → chunk-BINRCILF.js.map} +1 -1
- package/dist/{chunk-AROOYXI5.js → chunk-BTDTHXUI.js} +2 -2
- package/dist/chunk-FFGP2LGQ.js +465 -0
- package/dist/chunk-FFGP2LGQ.js.map +1 -0
- package/dist/{chunk-CO7Q75IS.js → chunk-I2H6KRCQ.js} +8 -8
- package/dist/{chunk-ENRT6DAU.js → chunk-IDWN2OSG.js} +15 -2
- package/dist/chunk-IDWN2OSG.js.map +1 -0
- package/dist/{chunk-GAJOZJWD.js → chunk-MOGTMGGA.js} +5 -2
- package/dist/chunk-MOGTMGGA.js.map +1 -0
- package/dist/{chunk-LADTWXOB.js → chunk-QVXMAHZC.js} +40 -551
- package/dist/chunk-QVXMAHZC.js.map +1 -0
- package/dist/{chunk-G2NWAVGG.js → chunk-SJ4AW54X.js} +44 -3
- package/dist/chunk-SJ4AW54X.js.map +1 -0
- package/dist/{chunk-Q7T3UQ4L.js → chunk-SRJBH5E5.js} +16 -738
- package/dist/chunk-SRJBH5E5.js.map +1 -0
- package/dist/{chunk-QGNSZ2ZK.js → chunk-T2LDLVVV.js} +3 -3
- package/dist/{chunk-FYYKMPST.js → chunk-TJPENLGQ.js} +3 -3
- package/dist/chunk-V5SSTT3C.js +52 -0
- package/dist/chunk-V5SSTT3C.js.map +1 -0
- package/dist/chunk-XG6SQUEP.js +27 -0
- package/dist/chunk-XG6SQUEP.js.map +1 -0
- package/dist/cli/index.js +6 -6
- package/dist/client/index.d.ts +20 -0
- package/dist/client/index.js.map +1 -1
- package/dist/{cloudflare-5HU56XIH.js → cloudflare-GK4VD3EU.js} +36 -13
- package/dist/cloudflare-GK4VD3EU.js.map +1 -0
- package/dist/{define-middleware-D2n71Svm.d.ts → define-middleware-BOHpPOBs.d.ts} +1 -1
- package/dist/{deno-deploy-BXOQ45LD.js → deno-deploy-WMNXRVGL.js} +37 -36
- package/dist/deno-deploy-WMNXRVGL.js.map +1 -0
- package/dist/{dev-E3USPAWQ.js → dev-72ISY3BP.js} +5 -5
- package/dist/{index-B9iVBHJI.d.ts → index-DZ_G5iY2.d.ts} +31 -4
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/{internal-api-OOTVIOH2.js → internal-api-CEZSXGRB.js} +3 -3
- package/dist/{internal-api-VAKXXW6F.js → internal-api-XRIBUACB.js} +8 -7
- package/dist/match-DaKsL73w.d.ts +28 -0
- package/dist/{mcp-7UOQM4FW.js → mcp-S2AOB3RE.js} +3 -3
- package/dist/{match-Dw4CNXJH.d.ts → module-loader-DCip7NoL.d.ts} +1 -28
- package/dist/{netlify-LPJAPMQ2.js → netlify-VOL54SC7.js} +23 -20
- package/dist/netlify-VOL54SC7.js.map +1 -0
- package/dist/{preview-GPMF43QX.js → preview-WA4HORUQ.js} +3 -3
- package/dist/{registry-UOWTDUFL.js → registry-DDBXDHJ2.js} +7 -7
- package/dist/server/cost/index.d.ts +14 -1
- package/dist/server/cost/index.js +1 -1
- package/dist/server/define/index.d.ts +1 -1
- package/dist/server/define/index.js +2 -3
- package/dist/server/http/index.d.ts +4 -3
- package/dist/server/http/index.js +11 -8
- package/dist/server/index.d.ts +5 -4
- package/dist/server/index.js +13 -10
- package/dist/server/index.js.map +1 -1
- package/dist/server/scan/index.d.ts +3 -2
- package/dist/{server-boundary-A3HW27C7.js → server-boundary-S3G4CSNK.js} +3 -3
- package/dist/{server-boundary-V6PCM22J.js → server-boundary-YN5HAICY.js} +6 -6
- package/dist/{start-6WEPXA3X.js → start-ZTMQLNJI.js} +4 -4
- package/dist/{vercel-YUZADKGV.js → vercel-LZTDSDJF.js} +42 -28
- package/dist/vercel-LZTDSDJF.js.map +1 -0
- package/dist/vite-plugin/index.js +7 -6
- package/dist/{vite-plugin-WBF5NXGW.js → vite-plugin-Z7AJG3M2.js} +5 -5
- package/package.json +4 -4
- package/dist/aws-lambda-R76PWR27.js.map +0 -1
- package/dist/build-U4HVYY6F.js.map +0 -1
- package/dist/bun-NPBIAWSU.js.map +0 -1
- package/dist/chunk-6B3CMPE4.js +0 -192
- package/dist/chunk-6B3CMPE4.js.map +0 -1
- package/dist/chunk-7L7LQ2GU.js +0 -16
- package/dist/chunk-7L7LQ2GU.js.map +0 -1
- package/dist/chunk-ENRT6DAU.js.map +0 -1
- package/dist/chunk-G2NWAVGG.js.map +0 -1
- package/dist/chunk-GAJOZJWD.js.map +0 -1
- package/dist/chunk-GDF2XQOO.js.map +0 -1
- package/dist/chunk-LADTWXOB.js.map +0 -1
- package/dist/chunk-O55RLSGG.js +0 -127
- package/dist/chunk-O55RLSGG.js.map +0 -1
- package/dist/chunk-Q7T3UQ4L.js.map +0 -1
- package/dist/cloudflare-5HU56XIH.js.map +0 -1
- package/dist/deno-deploy-BXOQ45LD.js.map +0 -1
- package/dist/netlify-LPJAPMQ2.js.map +0 -1
- package/dist/vercel-YUZADKGV.js.map +0 -1
- /package/dist/{actions-virtual-module-SE44BKR4.js.map → actions-virtual-module-DH3N34I6.js.map} +0 -0
- /package/dist/{actions-virtual-module-3OPYLD76.js.map → actions-virtual-module-OMIFGXK6.js.map} +0 -0
- /package/dist/{agent-UBDDP2L5.js.map → agent-7RPGAKTY.js.map} +0 -0
- /package/dist/{app-typed-client-RAFEBA7S.js.map → app-typed-client-C4LRUSIS.js.map} +0 -0
- /package/dist/{app-typed-client-BE3PV3JY.js.map → app-typed-client-R6OUJZEE.js.map} +0 -0
- /package/dist/{chunk-AROOYXI5.js.map → chunk-BTDTHXUI.js.map} +0 -0
- /package/dist/{chunk-CO7Q75IS.js.map → chunk-I2H6KRCQ.js.map} +0 -0
- /package/dist/{chunk-QGNSZ2ZK.js.map → chunk-T2LDLVVV.js.map} +0 -0
- /package/dist/{chunk-FYYKMPST.js.map → chunk-TJPENLGQ.js.map} +0 -0
- /package/dist/{dev-E3USPAWQ.js.map → dev-72ISY3BP.js.map} +0 -0
- /package/dist/{internal-api-OOTVIOH2.js.map → internal-api-CEZSXGRB.js.map} +0 -0
- /package/dist/{internal-api-VAKXXW6F.js.map → internal-api-XRIBUACB.js.map} +0 -0
- /package/dist/{mcp-7UOQM4FW.js.map → mcp-S2AOB3RE.js.map} +0 -0
- /package/dist/{preview-GPMF43QX.js.map → preview-WA4HORUQ.js.map} +0 -0
- /package/dist/{registry-UOWTDUFL.js.map → registry-DDBXDHJ2.js.map} +0 -0
- /package/dist/{server-boundary-A3HW27C7.js.map → server-boundary-S3G4CSNK.js.map} +0 -0
- /package/dist/{server-boundary-V6PCM22J.js.map → server-boundary-YN5HAICY.js.map} +0 -0
- /package/dist/{start-6WEPXA3X.js.map → start-ZTMQLNJI.js.map} +0 -0
- /package/dist/{vite-plugin-WBF5NXGW.js.map → vite-plugin-Z7AJG3M2.js.map} +0 -0
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
3
|
import {
|
|
4
|
-
deployedAgentsFragment,
|
|
5
4
|
planDeployedPlugins
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V5SSTT3C.js";
|
|
6
|
+
import {
|
|
7
|
+
deployedEntryPreamble
|
|
8
|
+
} from "./chunk-XG6SQUEP.js";
|
|
7
9
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
agentsDirLiteral,
|
|
11
|
+
deployedAgentsFragment,
|
|
10
12
|
deployedRuntimeConfigFragment,
|
|
11
13
|
deployedTraceFragment,
|
|
12
14
|
describeDeployedSecurityHeaders,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
scannedFromLoaderCache,
|
|
16
|
+
serverDirLiteral
|
|
17
|
+
} from "./chunk-FFGP2LGQ.js";
|
|
15
18
|
import {
|
|
16
19
|
nodeAdapter
|
|
17
20
|
} from "./chunk-KI4DOTN4.js";
|
|
@@ -24,17 +27,25 @@ import {
|
|
|
24
27
|
// src/adapters/deno-deploy.ts
|
|
25
28
|
import { mkdirSync, writeFileSync } from "fs";
|
|
26
29
|
import { resolve } from "path";
|
|
30
|
+
var FRAMEWORK_IMPORTS = [
|
|
31
|
+
`// Use npm: specifier so Deno resolves theokit from the user's package.json`,
|
|
32
|
+
`// equivalent (works in both local 'deno run' and Deno Deploy).`,
|
|
33
|
+
`import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, scanWebSocketRoutes, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'npm:theokit/server'`,
|
|
34
|
+
`import { createWebShim } from 'npm:theokit/adapters/web-shim'`,
|
|
35
|
+
`import { buildSecurityHeaders, withSecurityHeaders } from 'npm:theokit/adapters/security-headers'`,
|
|
36
|
+
`// T3.3 \u2014 WS bridge for Deno runtime`,
|
|
37
|
+
`import { createDenoWsBridge } from 'npm:theokit/adapters/ws-shim'`
|
|
38
|
+
];
|
|
27
39
|
function renderDenoEntry(port, opts = {}) {
|
|
28
40
|
const runtimeConfig = deployedRuntimeConfigFragment(opts);
|
|
29
|
-
const agentsFragment = deployedAgentsFragment(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
);
|
|
41
|
+
const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {
|
|
42
|
+
notFound: "notFound()",
|
|
43
|
+
importPrefix: "npm:",
|
|
44
|
+
// B-185 — bound only when the runtime-config fragment declared the const, which is
|
|
45
|
+
// exactly when a plugins module was emitted. Referencing it otherwise would emit an
|
|
46
|
+
// identifier the entry never declares.
|
|
47
|
+
pluginRunnerExpr: opts.runtimeConfigModule === void 0 ? void 0 : "await THEO_PLUGIN_RUNNER"
|
|
48
|
+
});
|
|
38
49
|
return [
|
|
39
50
|
`// Generated by Theo \u2014 Deno Deploy Adapter`,
|
|
40
51
|
`// Deploy: deployctl deploy --project=<name> .theokit/deno/server.ts`,
|
|
@@ -45,17 +56,11 @@ function renderDenoEntry(port, opts = {}) {
|
|
|
45
56
|
` throw new Error('TheoDenoDeployAdapter must run inside Deno.')`,
|
|
46
57
|
`}`,
|
|
47
58
|
``,
|
|
48
|
-
|
|
49
|
-
`// equivalent (works in both local 'deno run' and Deno Deploy).`,
|
|
50
|
-
`import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, scanWebSocketRoutes, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'npm:theokit/server'`,
|
|
51
|
-
`import { createWebShim } from 'npm:theokit/adapters/web-shim'`,
|
|
52
|
-
`import { buildSecurityHeaders, withSecurityHeaders } from 'npm:theokit/adapters/security-headers'`,
|
|
53
|
-
`// T3.3 \u2014 WS bridge for Deno runtime`,
|
|
54
|
-
`import { createDenoWsBridge } from 'npm:theokit/adapters/ws-shim'`,
|
|
59
|
+
...FRAMEWORK_IMPORTS,
|
|
55
60
|
``,
|
|
56
61
|
`const port = Number(Deno.env.get('PORT') ?? '${port}')`,
|
|
57
62
|
`const cwd = Deno.cwd()`,
|
|
58
|
-
`const serverDir = cwd + '/
|
|
63
|
+
`const serverDir = cwd + '/' + ${serverDirLiteral(opts)}`,
|
|
59
64
|
`let routesCache = null`,
|
|
60
65
|
`let wsRoutesCache = null`,
|
|
61
66
|
`let loaderCache = null`,
|
|
@@ -65,16 +70,7 @@ function renderDenoEntry(port, opts = {}) {
|
|
|
65
70
|
`// theo.config.ts to read. Non-API paths 404 here and are served by Deno`,
|
|
66
71
|
`// Deploy's static asset handler, so this covers the API and not the`,
|
|
67
72
|
`// document (usetheokit/theokit#412).`,
|
|
68
|
-
|
|
69
|
-
`const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,
|
|
70
|
-
``,
|
|
71
|
-
...runtimeConfig.imports,
|
|
72
|
-
...agentsFragment.imports,
|
|
73
|
-
...runtimeConfig.declarations,
|
|
74
|
-
...agentsFragment.declarations,
|
|
75
|
-
...deployedCsrfFragment(opts),
|
|
76
|
-
``,
|
|
77
|
-
...deployedCorsFragment(opts.cors, "deno-deploy"),
|
|
73
|
+
...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, "deno-deploy"),
|
|
78
74
|
``,
|
|
79
75
|
`function notFound() {`,
|
|
80
76
|
` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,
|
|
@@ -108,7 +104,7 @@ function renderDenoEntry(port, opts = {}) {
|
|
|
108
104
|
`async function handleRequest(request) {`,
|
|
109
105
|
` const url = new URL(request.url)`,
|
|
110
106
|
``,
|
|
111
|
-
` if (!url.pathname.startsWith('/api/')) {`,
|
|
107
|
+
` if (!url.pathname.startsWith('/api/')${agentsFragment.hostBypass}) {`,
|
|
112
108
|
` // Static + SPA fallback are served by Deno Deploy's static asset handler.`,
|
|
113
109
|
` return notFound()`,
|
|
114
110
|
` }`,
|
|
@@ -150,7 +146,12 @@ async function buildDeno(config, cwd, deps = {}, ctx) {
|
|
|
150
146
|
// #425 — the ONE concern that is not a literal. A closure cannot be baked, so a plugin
|
|
151
147
|
// declared by module specifier is imported by the emitted module instead; a constructed one
|
|
152
148
|
// is refused by name at build time rather than dropped in silence.
|
|
153
|
-
runtimeConfigModule: pluginsPlan?.moduleSpecifier
|
|
149
|
+
runtimeConfigModule: pluginsPlan?.moduleSpecifier,
|
|
150
|
+
// #95 — the configured directories, which `build.ts:210` already threads into the Vite
|
|
151
|
+
// plugins. Without these two lines the literals above fall to their defaults and a project
|
|
152
|
+
// with a custom dir deploys an entry that resolves a directory it does not have.
|
|
153
|
+
serverDir: config.serverDir,
|
|
154
|
+
agentsDir: config.agentsDir
|
|
154
155
|
});
|
|
155
156
|
const write = deps.writeEntry ?? ((p, c) => {
|
|
156
157
|
writeFileSync(p, c);
|
|
@@ -193,4 +194,4 @@ export {
|
|
|
193
194
|
denoDeployAdapter,
|
|
194
195
|
renderDenoEntry
|
|
195
196
|
};
|
|
196
|
-
//# sourceMappingURL=deno-deploy-
|
|
197
|
+
//# sourceMappingURL=deno-deploy-WMNXRVGL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/deno-deploy.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Deno Deploy adapter. Writes to `cwd/.theokit/deno-deploy/`. Build-time.\n */\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { TheoConfig } from '../config/schema.js'\nimport { assertServicesUnsupported, readManifest } from '../services/index.js'\n\nimport { deployedAgentsFragment, scannedFromLoaderCache } from './deployed-agents.js'\nimport { planDeployedPlugins } from './deployed-plugins-module.js'\nimport { deployedEntryPreamble } from './deployed-preamble.js'\nimport {\n agentsDirLiteral,\n deployedRuntimeConfigFragment,\n serverDirLiteral,\n} from './deployed-runtime-config.js'\nimport { deployedTraceFragment } from './deployed-trace.js'\nimport { nodeAdapter } from './node.js'\nimport { describeDeployedSecurityHeaders } from './security-headers.js'\nimport type { AdapterBuildContext, DeployAdapter, DeployedEntryOptions } from './types.js'\n\nexport interface DenoBuildDeps {\n runNodeBuild?: (config: TheoConfig, cwd: string, ctx?: AdapterBuildContext) => Promise<void>\n writeEntry?: (path: string, content: string) => void\n ensureDir?: (path: string) => void\n}\n\n/**\n * The framework imports this entry opens with, as `npm:` specifiers.\n *\n * Extracted from `renderDenoEntry` when adding the configured-directory literal pushed it past the\n * per-function line budget. A cohesive block — every line is one import of the same package family\n * — so lifting it keeps the budget a signal about the renderer rather than about its preamble.\n */\nconst FRAMEWORK_IMPORTS: readonly string[] = [\n `// Use npm: specifier so Deno resolves theokit from the user's package.json`,\n `// equivalent (works in both local 'deno run' and Deno Deploy).`,\n `import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, scanWebSocketRoutes, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'npm:theokit/server'`,\n `import { createWebShim } from 'npm:theokit/adapters/web-shim'`,\n `import { buildSecurityHeaders, withSecurityHeaders } from 'npm:theokit/adapters/security-headers'`,\n `// T3.3 — WS bridge for Deno runtime`,\n `import { createDenoWsBridge } from 'npm:theokit/adapters/ws-shim'`,\n]\n\nexport function renderDenoEntry(port: number, opts: DeployedEntryOptions = {}): string {\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {\n notFound: 'notFound()',\n importPrefix: 'npm:',\n // B-185 — bound only when the runtime-config fragment declared the const, which is\n // exactly when a plugins module was emitted. Referencing it otherwise would emit an\n // identifier the entry never declares.\n pluginRunnerExpr:\n opts.runtimeConfigModule === undefined ? undefined : 'await THEO_PLUGIN_RUNNER',\n })\n return [\n `// Generated by Theo — Deno Deploy Adapter`,\n `// Deploy: deployctl deploy --project=<name> .theokit/deno/server.ts`,\n `// Requires Deno >= 1.40 (Deno.serve + npm: specifier support)`,\n ``,\n `// Runtime guard`,\n `if (typeof Deno === 'undefined') {`,\n ` throw new Error('TheoDenoDeployAdapter must run inside Deno.')`,\n `}`,\n ``,\n ...FRAMEWORK_IMPORTS,\n ``,\n `const port = Number(Deno.env.get('PORT') ?? '${port}')`,\n `const cwd = Deno.cwd()`,\n `const serverDir = cwd + '/' + ${serverDirLiteral(opts)}`,\n `let routesCache = null`,\n `let wsRoutesCache = null`,\n `let loaderCache = null`,\n ``,\n `// #410 — the security baseline \\`theokit start\\` puts on every response,`,\n `// carried here as a literal because the deployed isolate has no`,\n `// theo.config.ts to read. Non-API paths 404 here and are served by Deno`,\n `// Deploy's static asset handler, so this covers the API and not the`,\n `// document (usetheokit/theokit#412).`,\n ...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, 'deno-deploy'),\n ``,\n `function notFound() {`,\n ` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,\n ` status: 404,`,\n ` headers: { 'Content-Type': 'application/json' },`,\n ` })`,\n `}`,\n ``,\n `Deno.serve({ port }, async (request) => {`,\n ` // T3.3 — Detect WebSocket upgrade and delegate to the Deno bridge.`,\n ` // A 101 carries no document and no script, so the security baseline does`,\n ` // not apply to it.`,\n ` if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {`,\n ` if (!wsRoutesCache) wsRoutesCache = scanWebSocketRoutes(serverDir)`,\n ` if (wsRoutesCache.length === 0) return notFound()`,\n ` const denoWs = createDenoWsBridge({`,\n ` onOpen: () => {},`,\n ` onMessage: (ws, data) => { ws.send(data) },`,\n ` onClose: () => {},`,\n ` }, Deno)`,\n ` return denoWs.handle(request)`,\n ` }`,\n ``,\n ` // #409 — the preflight is answered BEFORE anything routes: an OPTIONS the router`,\n ` // handles is an OPTIONS the browser never gets a CORS answer to.`,\n ` const preflight = corsPreflight(request)`,\n ` if (preflight !== null) return withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ` return withCors(request, withSecurityHeaders(await handleRequest(request), SECURITY_HEADERS))`,\n `})`,\n ``,\n `async function handleRequest(request) {`,\n ` const url = new URL(request.url)`,\n ``,\n ` if (!url.pathname.startsWith('/api/')${agentsFragment.hostBypass}) {`,\n ` // Static + SPA fallback are served by Deno Deploy's static asset handler.`,\n ` return notFound()`,\n ` }`,\n ``,\n ` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,\n ` if (!loaderCache) loaderCache = createProductionLoader()`,\n ``,\n ...agentsFragment.branch,\n ``,\n ` const match = matchRoute(url.pathname, routesCache)`,\n ` if (!match) return notFound()`,\n ``,\n ` const { req, res, toResponse } = createWebShim(request)`,\n ...deployedTraceFragment('request', ' '),\n ` const method = request.method.toUpperCase()`,\n ` // #382 — not awaited: toResponse() settles at the headers and carries a`,\n ` // live body, so Deno.serve streams while the handler writes.`,\n ` return toResponse(executeRoute({ route: match.route, method, params: match.params, req, res, loadModule: loaderCache, serverDir, requestId, ...CSRF_CONFIG, ${runtimeConfig.executeRouteSpread} }))`,\n `}`,\n ``,\n `console.log('Theo (Deno Deploy) listening on :' + port)`,\n ].join('\\n')\n}\n\nexport async function buildDeno(\n config: TheoConfig,\n cwd: string,\n deps: DenoBuildDeps = {},\n ctx?: AdapterBuildContext,\n): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('deno-deploy', readManifest(cwd))\n\n const runNodeBuild = deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter)\n await runNodeBuild(config, cwd, ctx)\n\n const outputDir = resolve(cwd, '.theokit/deno')\n const ensureDir = deps.ensureDir ?? ((p: string) => mkdirSync(p, { recursive: true }))\n ensureDir(outputDir)\n\n const pluginsPlan = planDeployedPlugins(config.plugins, denoDeployAdapter.name)\n const entry = renderDenoEntry(config.port, {\n securityHeaders: config.security?.headers,\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 // #425 — the ONE concern that is not a literal. A closure cannot be baked, so a plugin\n // declared by module specifier is imported by the emitted module instead; a constructed one\n // is refused by name at build time rather than dropped in silence.\n runtimeConfigModule: pluginsPlan?.moduleSpecifier,\n // #95 — the configured directories, which `build.ts:210` already threads into the Vite\n // plugins. Without these two lines the literals above fall to their defaults and a project\n // with a custom dir deploys an entry that resolves a directory it does not have.\n serverDir: config.serverDir,\n agentsDir: config.agentsDir,\n })\n const write =\n deps.writeEntry ??\n ((p, c) => {\n writeFileSync(p, c)\n })\n if (pluginsPlan !== undefined) {\n // Beside the entry, so the emitted import is a sibling. Written through the same seam as\n // the entry so a test that captures one captures both (#425).\n write(resolve(outputDir, 'theo.plugins.mjs'), pluginsPlan.source)\n }\n write(resolve(outputDir, 'server.ts'), entry)\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ Deno Deploy output → .theokit/deno/server.ts')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'deno-deploy',\n securityHeaders: config.security?.headers,\n mintsNonce: false,\n documentHeaders: 'platform-unmanaged',\n })}\\n`,\n )\n}\n\nexport const denoDeployAdapter: DeployAdapter = {\n name: 'deno-deploy',\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 isolate returns. The\n // document comes from Deno Deploy's static asset handler and does not pass\n // through it (usetheokit/theokit#412).\n servesAgents: true,\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization', 'plugins'],\n build(config, cwd, ctx) {\n return buildDeno(config, cwd, {}, ctx)\n },\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,SAAS,WAAW,qBAAqB;AACzC,SAAS,eAAe;AA+BxB,IAAM,oBAAuC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,gBAAgB,MAAc,OAA6B,CAAC,GAAW;AACrF,QAAM,gBAAgB,8BAA8B,IAAI;AACxD,QAAM,iBAAiB,uBAAuB,uBAAuB,iBAAiB,IAAI,CAAC,GAAG;AAAA,IAC5F,UAAU;AAAA,IACV,cAAc;AAAA;AAAA;AAAA;AAAA,IAId,kBACE,KAAK,wBAAwB,SAAY,SAAY;AAAA,EACzD,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA,gDAAgD,IAAI;AAAA,IACpD;AAAA,IACA,iCAAiC,iBAAiB,IAAI,CAAC;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,sBAAsB,eAAe,gBAAgB,MAAM,aAAa;AAAA,IAC3E;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,0CAA0C,eAAe,UAAU;AAAA,IACnE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,eAAe;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,sBAAsB,WAAW,IAAI;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,iKAAiK,cAAc,kBAAkB;AAAA,IACjM;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,eAAsB,UACpB,QACA,KACA,OAAsB,CAAC,GACvB,KACe;AAEf,4BAA0B,eAAe,aAAa,GAAG,CAAC;AAE1D,QAAM,eAAe,KAAK,gBAAgB,YAAY,MAAM,KAAK,WAAW;AAC5E,QAAM,aAAa,QAAQ,KAAK,GAAG;AAEnC,QAAM,YAAY,QAAQ,KAAK,eAAe;AAC9C,QAAM,YAAY,KAAK,cAAc,CAAC,MAAc,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AACpF,YAAU,SAAS;AAEnB,QAAM,cAAc,oBAAoB,OAAO,SAAS,kBAAkB,IAAI;AAC9E,QAAM,QAAQ,gBAAgB,OAAO,MAAM;AAAA,IACzC,iBAAiB,OAAO,UAAU;AAAA,IAClC,MAAM,OAAO,UAAU;AAAA,IACvB,YAAY,OAAO,UAAU;AAAA,IAC7B,MAAM,OAAO,UAAU;AAAA;AAAA,IAEvB,eAAe,OAAO;AAAA;AAAA;AAAA;AAAA,IAItB,qBAAqB,aAAa;AAAA;AAAA;AAAA;AAAA,IAIlC,WAAW,OAAO;AAAA,IAClB,WAAW,OAAO;AAAA,EACpB,CAAC;AACD,QAAM,QACJ,KAAK,eACJ,CAAC,GAAG,MAAM;AACT,kBAAc,GAAG,CAAC;AAAA,EACpB;AACF,MAAI,gBAAgB,QAAW;AAG7B,UAAM,QAAQ,WAAW,kBAAkB,GAAG,YAAY,MAAM;AAAA,EAClE;AACA,QAAM,QAAQ,WAAW,WAAW,GAAG,KAAK;AAG5C,UAAQ,IAAI,8DAAoD;AAEhE,UAAQ;AAAA,IACN,GAAG,gCAAgC;AAAA,MACjC,QAAQ;AAAA,MACR,iBAAiB,OAAO,UAAU;AAAA,MAClC,YAAY;AAAA,MACZ,iBAAiB;AAAA,IACnB,CAAC,CAAC;AAAA;AAAA,EACJ;AACF;AAEO,IAAM,oBAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlB,cAAc;AAAA,EACd,eAAe,CAAC,mBAAmB,QAAQ,cAAc,QAAQ,iBAAiB,SAAS;AAAA,EAC3F,MAAM,QAAQ,KAAK,KAAK;AACtB,WAAO,UAAU,QAAQ,KAAK,CAAC,GAAG,GAAG;AAAA,EACvC;AACF;","names":[]}
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
} from "./chunk-KTMQUYED.js";
|
|
12
12
|
import {
|
|
13
13
|
theoPluginAsync
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-I2H6KRCQ.js";
|
|
15
|
+
import "./chunk-4WB62S22.js";
|
|
16
16
|
import "./chunk-BDH5GKFZ.js";
|
|
17
17
|
import "./chunk-3PWQQWT6.js";
|
|
18
18
|
import "./chunk-FDOOBTXJ.js";
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-SJ4AW54X.js";
|
|
20
|
+
import "./chunk-BINRCILF.js";
|
|
21
21
|
import "./chunk-QD5X56I3.js";
|
|
22
22
|
import "./chunk-WSMLSIS5.js";
|
|
23
23
|
import "./chunk-MS4A7N77.js";
|
|
@@ -128,4 +128,4 @@ export {
|
|
|
128
128
|
devCommand,
|
|
129
129
|
startDevServer
|
|
130
130
|
};
|
|
131
|
-
//# sourceMappingURL=dev-
|
|
131
|
+
//# sourceMappingURL=dev-72ISY3BP.js.map
|
|
@@ -3,10 +3,11 @@ import { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
3
3
|
import { P as PluginContext, W as WebOnRequestHook, g as WebPreHandlerHook, h as WebOnResponseHook, i as WebOnErrorHook } from './plugin-types-BUVfUQ0V.js';
|
|
4
4
|
import { P as PluginRunner } from './plugin-runner-BVMOSxvb.js';
|
|
5
5
|
import { J as JobBackend } from './job-backend-CgC8Xf33.js';
|
|
6
|
-
import {
|
|
6
|
+
import { S as ServerRouteNode } from './match-DaKsL73w.js';
|
|
7
|
+
import { L as LoadModule } from './module-loader-DCip7NoL.js';
|
|
7
8
|
import { C as CsrfMode, D as DisallowedConfig } from './csrf-Dgot9qSM.js';
|
|
8
9
|
import { z } from 'zod';
|
|
9
|
-
import { a as MiddlewareNext, R as RouteConfig } from './define-middleware-
|
|
10
|
+
import { a as MiddlewareNext, R as RouteConfig } from './define-middleware-BOHpPOBs.js';
|
|
10
11
|
import './action-protocol-tGm3NKRg.js';
|
|
11
12
|
|
|
12
13
|
interface ExecuteActionOptions {
|
|
@@ -543,6 +544,32 @@ interface MiddlewareResult {
|
|
|
543
544
|
aborted: boolean;
|
|
544
545
|
}
|
|
545
546
|
declare function _resetMiddlewareCacheForTests(): void;
|
|
547
|
+
/**
|
|
548
|
+
* Run a Web-shaped middleware — the one `middleware()` and `defineMiddleware()` produce (#345).
|
|
549
|
+
*
|
|
550
|
+
* This used to REFUSE the shape by name, because the runner could only invoke `(req, res, next)`
|
|
551
|
+
* and calling a Web handler that way hands it `res` as its `next`. Refusing was better than the
|
|
552
|
+
* blank response it replaced, and it was never the end state: the README documented the builder as
|
|
553
|
+
* the way to write middleware, so the documented path was loud instead of silent, but still broken.
|
|
554
|
+
*
|
|
555
|
+
* It runs now because the published contract became the one that fits this model:
|
|
556
|
+
* `(request, context) => Response | void`. No continuation is needed — returning a `Response`
|
|
557
|
+
* answers the request, returning nothing continues — which is exactly what a runner that executes
|
|
558
|
+
* BEFORE routing can honestly offer.
|
|
559
|
+
*
|
|
560
|
+
* The `Request` is built by the same converter the agent and action branches use, so a middleware
|
|
561
|
+
* reads the request the way every other Web-shaped surface in the framework does.
|
|
562
|
+
*/
|
|
563
|
+
/**
|
|
564
|
+
* Raised when a `server/middleware/*.ts` middleware awaits `next`.
|
|
565
|
+
*
|
|
566
|
+
* Typed rather than a bare `Error` so a caller can tell this apart from a failure inside the
|
|
567
|
+
* middleware's own body — `rules/error-handling.md` § 2, and the same shape as
|
|
568
|
+
* `http/in-process-caller.ts`'s three.
|
|
569
|
+
*/
|
|
570
|
+
declare class MiddlewareNextUnavailableError extends Error {
|
|
571
|
+
constructor();
|
|
572
|
+
}
|
|
546
573
|
declare function runMiddlewareAndContext(req: IncomingMessage, res: ServerResponse, loadModule: LoadModule, serverDir: string): Promise<MiddlewareResult>;
|
|
547
574
|
/**
|
|
548
575
|
* Run ONLY the application's `server/context.ts` factory and return what it produced.
|
|
@@ -692,7 +719,7 @@ type WebNext = MiddlewareNext;
|
|
|
692
719
|
* `docs/adr/0006` clause 5, which rests that claim on a measured call site
|
|
693
720
|
* rather than on confidence.
|
|
694
721
|
*/
|
|
695
|
-
type WebMiddleware = (request: Request, context: Record<string, unknown>, next
|
|
722
|
+
type WebMiddleware = (request: Request, context: Record<string, unknown>, next: WebNext) => Response | undefined | void | Promise<Response | undefined | void>;
|
|
696
723
|
|
|
697
724
|
/**
|
|
698
725
|
* The route module exported by a `server/routes/*.ts` file (after T2.6 G6
|
|
@@ -951,4 +978,4 @@ interface OpenApiDocsOptions {
|
|
|
951
978
|
*/
|
|
952
979
|
declare function createOpenApiHandler(opts?: OpenApiDocsOptions): (request: Request) => Response | null;
|
|
953
980
|
|
|
954
|
-
export {
|
|
981
|
+
export { extractTraceId as $, appendCookieToHeaders as A, BATCH_PATH as B, type CookieOptions as C, appendDeleteCookieToHeaders as D, type ExecuteActionOptions as E, FileTooLargeError as F, callProcedure as G, type HandleBatchOptions as H, createCorsHandler as I, createCorsWebHandler as J, createOpenApiHandler as K, createServerContext as L, MAX_ERROR_HTML_BYTES as M, NotFoundError as N, type OpenApiDocsOptions as O, type ParsedBody as P, deleteCookie as Q, type RawRouteInput as R, STRIPPED_HEADERS as S, TRACE_HEADER as T, type UploadedFile as U, envelopeCodeToStatus as V, type W3CTraceContext as W, executeAction as X, executeRoute as Y, executeWebRequest as Z, _resetMiddlewareCacheForTests as _, type BatchExecuteFn as a, extractTraceIdFromRequest as a0, extractW3CTraceContext as a1, fromUnknown as a2, getCookie as a3, getCookieFromRequest as a4, handleBatchRequest as a5, handleRequestError as a6, handleWebRequestError as a7, injectModulePreloads as a8, jsonTransformer as a9, loadCustomErrorPages as aa, matchesOrigin as ab, parseCookieHeader as ac, parseRequestBody as ad, parseTraceparent as ae, parseTraceparentContext as af, resolveTransformer as ag, runMiddlewareAndContext as ah, sendError as ai, sendJson as aj, serializeCookie as ak, serveStaticFile as al, serverErrorToEnvelope as am, setCookie as an, superjsonTransformer as ao, validateRouteInput as ap, BatchPathConflictError as b, type BatchPayload as c, type BatchRequestItem as d, type BatchResponse as e, type BatchResultItem as f, type BodyParserOptions as g, type CorsConfig as h, type CorsHandler as i, type CorsOrigin as j, type CorsWebHandler as k, type CustomErrorPages as l, type ExecuteRouteContext as m, MiddlewareNextUnavailableError as n, type MiddlewareResult as o, type ProcedureInput as p, ProcedureInputError as q, ProcedureOutputError as r, type RouteInputChannel as s, type RouteInputSchemas as t, type RouteInputValidation as u, type SendErrorInput as v, type SendErrorOptions as w, TRACE_PARENT_HEADER as x, TheoError as y, type TheoTransformer as z };
|
package/dist/index.js
CHANGED
|
@@ -8,21 +8,22 @@ import {
|
|
|
8
8
|
scanRoutes,
|
|
9
9
|
theoConfigSchema,
|
|
10
10
|
theoPlugin
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QVXMAHZC.js";
|
|
12
12
|
import "./chunk-7NRFZBAL.js";
|
|
13
13
|
import "./chunk-SSYDEKWF.js";
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-425FJKKO.js";
|
|
15
|
+
import "./chunk-BDPD5HEO.js";
|
|
16
|
+
import "./chunk-MOGTMGGA.js";
|
|
16
17
|
import "./chunk-OIGJOYX6.js";
|
|
17
18
|
import "./chunk-U3SPBLJF.js";
|
|
18
19
|
import "./chunk-WSOAN4KN.js";
|
|
19
20
|
import "./chunk-ENSFCKP6.js";
|
|
20
21
|
import "./chunk-OGLS76RN.js";
|
|
21
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-SRJBH5E5.js";
|
|
23
|
+
import "./chunk-3T5XLDOH.js";
|
|
22
24
|
import "./chunk-P6OS7652.js";
|
|
23
25
|
import "./chunk-ZDUO4IYN.js";
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-ENRT6DAU.js";
|
|
26
|
+
import "./chunk-IDWN2OSG.js";
|
|
26
27
|
import "./chunk-47FFT43U.js";
|
|
27
28
|
import "./chunk-NTDN54XO.js";
|
|
28
29
|
import "./chunk-PVNMLZ5G.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/define-config.ts","../src/config/config-builder.ts","../src/config/validate-structure.ts","../src/core/errors.ts"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/config/define-config.ts","../src/config/config-builder.ts","../src/config/validate-structure.ts","../src/core/errors.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOO,SAAS,aAAaA,SAAkD;AAC7E,SAAOA;AACT;;;ACuCA,SAAS,kBAAkB,MAA0C;AACnE,QAAM,QAAQ,CAAC,UACb,kBAAkB,EAAE,GAAG,MAAM,GAAG,MAAM,CAAC;AACzC,SAAO;AAAA,IACL,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,WAAW,CAAC,UAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,QAAQ,CAAC,UAAU,MAAM,EAAE,QAAQ,MAAM,CAAC;AAAA,IAC1C,WAAW,CAAC,UAAU,MAAM,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,SAAS,CAAC,UAAU,MAAM,EAAE,SAAS,MAAM,CAAC;AAAA,IAC5C,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,MAAM,CAAC,UAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAAA,IACtC,cAAc,CAAC,UAAU,MAAM,EAAE,cAAc,MAAM,CAAC;AAAA,IACtD,KAAK,CAAC,UAAU,MAAM,EAAE,KAAK,MAAM,CAAC;AAAA,IACpC,KAAK,CAAC,YAAY,MAAM,OAAO;AAAA,IAC/B,OAAO,MAAM,aAAa,IAAI;AAAA,EAChC;AACF;AAKO,SAAS,SAAwB;AACtC,SAAO,kBAAkB,CAAC,CAAC;AAC7B;;;ACnEA,SAAS,kBAAkB;AAC3B,SAAS,YAAY;;;ACLd,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1B;AAAA,EACA;AAAA,EAEhB,YAAY,QAAkB,SAAiB;AAC7C,UAAM,aAAa,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAE1D;AAAA,MACE;AAAA;AAAA,UACa,OAAO;AAAA;AAAA,KACjB,aAAa;AAAA,EAAc,UAAU;AAAA,IAAO;AAAA,IACjD;AAEA,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AACF;;;ADHA,IAAM,iBAAmC;AAAA,EACvC;AAAA,IACE,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,cAAc;AAAA,EAChB;AACF;AAIO,SAAS,yBAAyB,SAAiB,SAAS,OAAa;AAC9E,MAAI,CAAC,WAAW,OAAO,GAAG;AACxB,UAAM,IAAI,iBAAiB,CAAC,qCAAqC,OAAO,EAAE,GAAG,OAAO;AAAA,EACtF;AAEA,QAAM,SAAmB,CAAC;AAE1B,QAAM,eAAiC;AAAA,IACrC,EAAE,MAAM,QAAQ,cAAc,+BAA+B,MAAM,IAAI;AAAA,EACzE;AAEA,aAAW,QAAQ,cAAc;AAC/B,QAAI,CAAC,WAAW,KAAK,SAAS,KAAK,IAAI,CAAC,GAAG;AACzC,aAAO,KAAK,KAAK,YAAY;AAAA,IAC/B;AAAA,EACF;AAEA,aAAW,QAAQ,gBAAgB;AACjC,QAAI,CAAC,WAAW,KAAK,SAAS,KAAK,IAAI,CAAC,GAAG;AACzC,aAAO,KAAK,KAAK,YAAY;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,IAAI,iBAAiB,QAAQ,OAAO;AAAA,EAC5C;AACF;","names":["config"]}
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
handleCspReport,
|
|
17
17
|
handleCsrfReadiness,
|
|
18
18
|
mountAgent
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-SJ4AW54X.js";
|
|
20
20
|
import {
|
|
21
21
|
resolveProvider
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-BINRCILF.js";
|
|
23
23
|
import {
|
|
24
24
|
dispatchControllerRequest,
|
|
25
25
|
incomingMessageToHandlerRequest,
|
|
@@ -87,4 +87,4 @@ export {
|
|
|
87
87
|
scanWebSocketRoutes,
|
|
88
88
|
sendError
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=internal-api-
|
|
90
|
+
//# sourceMappingURL=internal-api-CEZSXGRB.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dispatchControllerRequest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-425FJKKO.js";
|
|
4
4
|
import {
|
|
5
5
|
mountAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MOGTMGGA.js";
|
|
7
7
|
import {
|
|
8
8
|
CSP_REPORT_PATH,
|
|
9
9
|
CsrfReadinessStore,
|
|
@@ -17,14 +17,15 @@ import {
|
|
|
17
17
|
createCorsHandler,
|
|
18
18
|
executeAction,
|
|
19
19
|
executeRoute,
|
|
20
|
-
handleBatchRequest
|
|
20
|
+
handleBatchRequest
|
|
21
|
+
} from "./chunk-SRJBH5E5.js";
|
|
22
|
+
import {
|
|
21
23
|
incomingMessageToHandlerRequest,
|
|
22
24
|
sendError
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-3T5XLDOH.js";
|
|
24
26
|
import "./chunk-P6OS7652.js";
|
|
25
27
|
import "./chunk-ZDUO4IYN.js";
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-ENRT6DAU.js";
|
|
28
|
+
import "./chunk-IDWN2OSG.js";
|
|
28
29
|
import "./chunk-47FFT43U.js";
|
|
29
30
|
import {
|
|
30
31
|
findSuggestion
|
|
@@ -107,4 +108,4 @@ export {
|
|
|
107
108
|
scanWebSocketRoutes,
|
|
108
109
|
sendError
|
|
109
110
|
};
|
|
110
|
-
//# sourceMappingURL=internal-api-
|
|
111
|
+
//# sourceMappingURL=internal-api-XRIBUACB.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface ServerRouteNode {
|
|
2
|
+
filePath: string;
|
|
3
|
+
routePath: string;
|
|
4
|
+
paramNames: string[];
|
|
5
|
+
pattern: RegExp;
|
|
6
|
+
/** HTTP methods (uppercase) the route file exports. Optional for backward
|
|
7
|
+
* compatibility with manifests generated before G1. Empty array means the
|
|
8
|
+
* file has no HTTP exports (util-only); undefined means "not detected". */
|
|
9
|
+
methods?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* The subset of `methods` whose policy is the literal `'public'` (ADR 0001).
|
|
12
|
+
*
|
|
13
|
+
* `undefined` means "not detected" — a manifest built before the field existed — and is NOT the
|
|
14
|
+
* same as `[]`, which means "detected, and nothing is public". `public-exposure-gate.ts` depends
|
|
15
|
+
* on that distinction: reading absence as safety is the failure it exists to prevent.
|
|
16
|
+
*/
|
|
17
|
+
publicMethods?: string[];
|
|
18
|
+
}
|
|
19
|
+
declare function compilePattern(routePath: string): {
|
|
20
|
+
pattern: RegExp;
|
|
21
|
+
paramNames: string[];
|
|
22
|
+
};
|
|
23
|
+
declare function matchRoute(url: string, routes: ServerRouteNode[]): {
|
|
24
|
+
route: ServerRouteNode;
|
|
25
|
+
params: Record<string, string>;
|
|
26
|
+
} | null;
|
|
27
|
+
|
|
28
|
+
export { type ServerRouteNode as S, compilePattern as c, matchRoute as m };
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import "tsx/esm";
|
|
3
3
|
import {
|
|
4
4
|
createAgentSsrLoader
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TJPENLGQ.js";
|
|
6
6
|
import {
|
|
7
7
|
extractAppResources,
|
|
8
8
|
handleMcpJsonRpc
|
|
9
9
|
} from "./chunk-BDH5GKFZ.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-BINRCILF.js";
|
|
11
11
|
import {
|
|
12
12
|
scanAgents
|
|
13
13
|
} from "./chunk-5NNFO7R7.js";
|
|
@@ -75,4 +75,4 @@ async function mcpCommand(name, deps = {}) {
|
|
|
75
75
|
export {
|
|
76
76
|
mcpCommand
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=mcp-
|
|
78
|
+
//# sourceMappingURL=mcp-S2AOB3RE.js.map
|
|
@@ -22,31 +22,4 @@ declare function createViteLoader(vite: ViteDevServer): LoadModule;
|
|
|
22
22
|
*/
|
|
23
23
|
declare function createProductionLoader(): LoadModule;
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
filePath: string;
|
|
27
|
-
routePath: string;
|
|
28
|
-
paramNames: string[];
|
|
29
|
-
pattern: RegExp;
|
|
30
|
-
/** HTTP methods (uppercase) the route file exports. Optional for backward
|
|
31
|
-
* compatibility with manifests generated before G1. Empty array means the
|
|
32
|
-
* file has no HTTP exports (util-only); undefined means "not detected". */
|
|
33
|
-
methods?: string[];
|
|
34
|
-
/**
|
|
35
|
-
* The subset of `methods` whose policy is the literal `'public'` (ADR 0001).
|
|
36
|
-
*
|
|
37
|
-
* `undefined` means "not detected" — a manifest built before the field existed — and is NOT the
|
|
38
|
-
* same as `[]`, which means "detected, and nothing is public". `public-exposure-gate.ts` depends
|
|
39
|
-
* on that distinction: reading absence as safety is the failure it exists to prevent.
|
|
40
|
-
*/
|
|
41
|
-
publicMethods?: string[];
|
|
42
|
-
}
|
|
43
|
-
declare function compilePattern(routePath: string): {
|
|
44
|
-
pattern: RegExp;
|
|
45
|
-
paramNames: string[];
|
|
46
|
-
};
|
|
47
|
-
declare function matchRoute(url: string, routes: ServerRouteNode[]): {
|
|
48
|
-
route: ServerRouteNode;
|
|
49
|
-
params: Record<string, string>;
|
|
50
|
-
} | null;
|
|
51
|
-
|
|
52
|
-
export { type LoadModule as L, type ServerRouteNode as S, createProductionLoader as a, createViteLoader as b, compilePattern as c, matchRoute as m };
|
|
25
|
+
export { type LoadModule as L, createViteLoader as a, createProductionLoader as c };
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
deployedEntryPreamble
|
|
5
|
+
} from "./chunk-XG6SQUEP.js";
|
|
6
|
+
import {
|
|
7
|
+
JSON_NOT_FOUND_RESPONSE,
|
|
8
|
+
agentsDirLiteral,
|
|
9
|
+
deployedAgentsFragment,
|
|
6
10
|
deployedRuntimeConfigFragment,
|
|
7
11
|
deployedTraceFragment,
|
|
8
12
|
describeDeployedSecurityHeaders,
|
|
9
|
-
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
scannedFromLoaderCache
|
|
14
|
+
} from "./chunk-FFGP2LGQ.js";
|
|
11
15
|
import {
|
|
12
16
|
nodeAdapter
|
|
13
17
|
} from "./chunk-KI4DOTN4.js";
|
|
@@ -32,6 +36,11 @@ var NetlifyConflictError = class extends Error {
|
|
|
32
36
|
};
|
|
33
37
|
function renderNetlifyFunction(opts = {}) {
|
|
34
38
|
const runtimeConfig = deployedRuntimeConfigFragment(opts);
|
|
39
|
+
const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {
|
|
40
|
+
// Netlify answers its own 404 inline rather than through a helper, so the fragment is given
|
|
41
|
+
// the expression instead of a call it would have to declare.
|
|
42
|
+
notFound: `new Response('Not Found', { status: 404 })`
|
|
43
|
+
});
|
|
35
44
|
return [
|
|
36
45
|
`// Generated by Theo \u2014 Netlify Functions adapter`,
|
|
37
46
|
`import { resolve } from 'node:path'`,
|
|
@@ -49,14 +58,7 @@ function renderNetlifyFunction(opts = {}) {
|
|
|
49
58
|
`// theo.config.ts to read. The netlify.toml redirect routes only /api/* here,`,
|
|
50
59
|
`// so this covers the API and not the document Netlify's static host serves`,
|
|
51
60
|
`// (usetheokit/theokit#412).`,
|
|
52
|
-
|
|
53
|
-
`const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,
|
|
54
|
-
``,
|
|
55
|
-
...runtimeConfig.imports,
|
|
56
|
-
...runtimeConfig.declarations,
|
|
57
|
-
...deployedCsrfFragment(opts),
|
|
58
|
-
``,
|
|
59
|
-
...deployedCorsFragment(opts.cors, "netlify"),
|
|
61
|
+
...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, "netlify"),
|
|
60
62
|
``,
|
|
61
63
|
`export default async (request, context) => {`,
|
|
62
64
|
` // #409 \u2014 the preflight is answered BEFORE anything routes: an OPTIONS the router`,
|
|
@@ -68,20 +70,17 @@ function renderNetlifyFunction(opts = {}) {
|
|
|
68
70
|
``,
|
|
69
71
|
`async function handleRequest(request) {`,
|
|
70
72
|
` const url = new URL(request.url)`,
|
|
71
|
-
` if (!url.pathname.startsWith('/api/')) {`,
|
|
73
|
+
` if (!url.pathname.startsWith('/api/')${agentsFragment.hostBypass}) {`,
|
|
72
74
|
` return new Response('Not Found', { status: 404 })`,
|
|
73
75
|
` }`,
|
|
74
76
|
``,
|
|
75
77
|
` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,
|
|
76
78
|
` if (!loaderCache) loaderCache = createProductionLoader()`,
|
|
77
79
|
``,
|
|
80
|
+
...agentsFragment.branch,
|
|
81
|
+
``,
|
|
78
82
|
` const match = matchRoute(url.pathname, routesCache)`,
|
|
79
|
-
` if (!match) {`,
|
|
80
|
-
` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,
|
|
81
|
-
` status: 404,`,
|
|
82
|
-
` headers: { 'content-type': 'application/json' },`,
|
|
83
|
-
` })`,
|
|
84
|
-
` }`,
|
|
83
|
+
` if (!match) return ${JSON_NOT_FOUND_RESPONSE}`,
|
|
85
84
|
``,
|
|
86
85
|
` const { req, res, toResponse } = createWebShim(request)`,
|
|
87
86
|
...deployedTraceFragment("request", " "),
|
|
@@ -197,6 +196,10 @@ async function buildNetlify(config, cwd, deps = {}, ctx) {
|
|
|
197
196
|
resolve(fnDir, "theo.mjs"),
|
|
198
197
|
renderNetlifyFunction({
|
|
199
198
|
securityHeaders: config.security?.headers,
|
|
199
|
+
// B-235 — pillar (a): the option existed and no build passed it, so a project with a
|
|
200
|
+
// configured agents directory got the default `agents` on this target. Same defect
|
|
201
|
+
// B-185 fixed for bun and deno, one target over.
|
|
202
|
+
agentsDir: config.agentsDir,
|
|
200
203
|
csrf: config.security?.csrf,
|
|
201
204
|
disallowed: config.security?.disallowed,
|
|
202
205
|
cors: config.security?.cors,
|
|
@@ -242,4 +245,4 @@ export {
|
|
|
242
245
|
netlifyAdapter,
|
|
243
246
|
renderNetlifyFunction
|
|
244
247
|
};
|
|
245
|
-
//# sourceMappingURL=netlify-
|
|
248
|
+
//# sourceMappingURL=netlify-VOL54SC7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/netlify.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Netlify deploy adapter. All paths derived from `cwd` and a fixed\n * `.theokit/netlify/` output layout. Build-time tool — no HTTP input.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { 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 deployedAgentsFragment,\n JSON_NOT_FOUND_RESPONSE,\n scannedFromLoaderCache,\n} from './deployed-agents.js'\nimport { type DeployedCorsOptions } from './deployed-cors.js'\nimport { type DeployedCsrfOptions } from './deployed-csrf.js'\nimport { deployedEntryPreamble } from './deployed-preamble.js'\nimport {\n agentsDirLiteral,\n type DeployedAgentsDirOptions,\n deployedRuntimeConfigFragment,\n type DeployedRuntimeConfigOptions,\n} 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 } from './types.js'\n\nexport class NetlifyConflictError extends Error {\n constructor(path: string, currentTo: string) {\n super(\n `netlify.toml has a conflicting redirect: \"${path}\" → \"${currentTo}\". ` +\n `Remove it manually or edit it to point to \"/.netlify/functions/theo\" ` +\n `before running the Netlify adapter again.`,\n )\n this.name = 'NetlifyConflictError'\n }\n}\n\nexport interface NetlifyBuildDeps {\n runNodeBuild?: (config: TheoConfig, cwd: string, ctx?: AdapterBuildContext) => Promise<void>\n writeFile?: (path: string, content: string) => void\n ensureDir?: (path: string) => void\n readTomlIfExists?: () => string | null\n}\n\nexport function renderNetlifyFunction(\n opts: { securityHeaders?: SecurityHeadersConfig } & DeployedAgentsDirOptions &\n DeployedCsrfOptions &\n DeployedRuntimeConfigOptions &\n DeployedCorsOptions = {},\n): string {\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n // B-235. Netlify's handler is `(request, context)` and already RECEIVES a Web `Request`, which\n // is the shape this branch needs — the item filed against it counted `new Request` occurrences\n // and concluded the opposite, measuring how the entry OBTAINS a request rather than whether it\n // has one. Deno is the model: same `loaderCache`, same filesystem `serverDir`, same guard.\n const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {\n // Netlify answers its own 404 inline rather than through a helper, so the fragment is given\n // the expression instead of a call it would have to declare.\n notFound: `new Response('Not Found', { status: 404 })`,\n })\n return [\n `// Generated by Theo — Netlify Functions adapter`,\n `import { resolve } from 'node:path'`,\n `import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`,\n `import { createWebShim } from 'theokit/adapters/web-shim'`,\n `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,\n ``,\n `const cwd = process.cwd()`,\n `const serverDir = resolve(cwd, 'server')`,\n `let routesCache = null`,\n `let loaderCache = null`,\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. The netlify.toml redirect routes only /api/* here,`,\n `// so this covers the API and not the document Netlify's static host serves`,\n `// (usetheokit/theokit#412).`,\n ...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, 'netlify'),\n ``,\n `export default async (request, context) => {`,\n ` // #409 — the preflight is answered BEFORE anything routes: an OPTIONS the router`,\n ` // handles is an OPTIONS the browser never gets a CORS answer to.`,\n ` const preflight = corsPreflight(request)`,\n ` if (preflight !== null) return withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ` return withCors(request, withSecurityHeaders(await handleRequest(request), SECURITY_HEADERS))`,\n `}`,\n ``,\n `async function handleRequest(request) {`,\n ` const url = new URL(request.url)`,\n ` if (!url.pathname.startsWith('/api/')${agentsFragment.hostBypass}) {`,\n ` return new Response('Not Found', { status: 404 })`,\n ` }`,\n ``,\n ` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,\n ` if (!loaderCache) loaderCache = createProductionLoader()`,\n ``,\n ...agentsFragment.branch,\n ``,\n ` const match = matchRoute(url.pathname, routesCache)`,\n ` if (!match) return ${JSON_NOT_FOUND_RESPONSE}`,\n ``,\n ` const { req, res, toResponse } = createWebShim(request)`,\n ...deployedTraceFragment('request', ' '),\n ` const method = request.method.toUpperCase()`,\n ` // #382 — the run is not awaited: toResponse() settles at the headers and`,\n ` // carries a live body, so Netlify streams while the handler writes.`,\n ` return toResponse(executeRoute({ route: match.route, method, params: match.params, req, res, loadModule: loaderCache, serverDir, requestId, ...CSRF_CONFIG, ${runtimeConfig.executeRouteSpread} }))`,\n `}`,\n ].join('\\n')\n}\n\nconst THEO_REDIRECT_FROM = '/api/*'\nconst THEO_REDIRECT_TO = '/.netlify/functions/theo'\n\n/**\n * TOML merge (EC-2) — non-destructive.\n *\n * We avoid adding a TOML parser dependency by working at the line level. The\n * supported subset is sufficient for the Netlify use case:\n * - detect existing `[[redirects]]` blocks\n * - find a block whose `from = \"...\"` matches our target\n * - error if such a block points elsewhere\n * - otherwise append our block\n *\n * Unknown sections (e.g. `[build]`, `[[headers]]`, `[context.production.environment]`)\n * are preserved as-is.\n */\ninterface NetlifyRedirectBlock {\n startLine: number\n endLine: number\n from?: string\n to?: string\n}\n\nfunction parseRedirectBlocks(lines: readonly string[]): NetlifyRedirectBlock[] {\n const blocks: NetlifyRedirectBlock[] = []\n let current: NetlifyRedirectBlock | null = null\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim()\n if (trimmed === '[[redirects]]') {\n if (current) {\n current.endLine = i - 1\n blocks.push(current)\n }\n current = { startLine: i, endLine: i }\n continue\n }\n if (current && /^\\[(\\[|[^[])/.test(trimmed)) {\n // Entering another section — close current.\n current.endLine = i - 1\n blocks.push(current)\n current = null\n }\n if (current) {\n const fromMatch = /^from\\s*=\\s*\"([^\"]+)\"/.exec(trimmed)\n if (fromMatch) current.from = fromMatch[1]\n const toMatch = /^to\\s*=\\s*\"([^\"]+)\"/.exec(trimmed)\n if (toMatch) current.to = toMatch[1]\n current.endLine = i\n }\n }\n if (current) blocks.push(current)\n return blocks\n}\n\nconst THEO_REDIRECT_TARGET = [\n '[[redirects]]',\n ' from = \"/api/*\"',\n ' to = \"/.netlify/functions/theo\"',\n ' status = 200',\n ' force = true',\n].join('\\n')\n\n/**\n * Marks the block this build owns, so it can be REGENERATED rather than merely not duplicated.\n *\n * Idempotence alone would be the wrong contract here: the block carries configuration, so a\n * `security.headers` change has to reach the file. Leaving an existing block in place — which is\n * what the redirect above correctly does, because its content is fixed — would silently pin the\n * baseline to whatever the first build emitted.\n */\nconst THEO_HEADERS_MARKER = '# Generated by Theo — security baseline (usetheokit/theokit#412)'\n\n/**\n * The `[[headers]]` block telling Netlify's static host the baseline.\n *\n * The emitted function applies these to every response IT returns, and it never returns the HTML\n * document: the `[[redirects]]` block routes only `/api/*`, so the page comes from Netlify's static\n * host and carried none of them. The values come from `buildSecurityHeaders` — the same function\n * the handler calls — rather than being written out here, because two lists of headers that must\n * agree are two lists that eventually do not.\n */\nfunction renderHeadersBlock(securityHeaders: SecurityHeadersConfig | undefined): string {\n const values = buildSecurityHeaders(securityHeaders ?? {}, { production: true })\n return [\n THEO_HEADERS_MARKER,\n '[[headers]]',\n ' for = \"/*\"',\n ' [headers.values]',\n ...Object.entries(values).map(([k, v]) => ` ${k} = ${JSON.stringify(v)}`),\n ].join('\\n')\n}\n\n/**\n * Drop a previously generated block, so the next one replaces it.\n *\n * Bounded by the marker and the next top-level section at column 0 (or EOF) — the shape TOML gives\n * a block. A user's own `[[headers]]` is untouched because it does not carry the marker: their\n * file, their rules, and Netlify applies both.\n */\nfunction withoutGeneratedHeaders(source: string): string {\n const lines = source.split(/\\r?\\n/)\n const start = lines.indexOf(THEO_HEADERS_MARKER)\n if (start < 0) return source\n\n const opensSection = (line: string | undefined): boolean => (line ?? '').startsWith('[')\n\n let end = start + 1\n while (end < lines.length && !opensSection(lines[end])) end += 1\n // The marker line itself opens the block, so `end` now sits on the NEXT section — but the block's\n // own `[[headers]]` is the first `[` after the marker, so step past it before scanning again.\n end += 1\n while (end < lines.length && !opensSection(lines[end])) end += 1\n\n return [...lines.slice(0, start), ...lines.slice(end)].join('\\n').replace(/\\n{3,}/gu, '\\n\\n')\n}\n\nexport function mergeNetlifyToml(\n existing: string | null,\n securityHeaders?: SecurityHeadersConfig,\n): string {\n const headersBlock = renderHeadersBlock(securityHeaders)\n\n if (existing === null || existing.trim().length === 0) {\n return `${THEO_REDIRECT_TARGET}\\n\\n${headersBlock}\\n`\n }\n\n existing = withoutGeneratedHeaders(existing)\n\n const blocks = parseRedirectBlocks(existing.split(/\\r?\\n/))\n\n // Detect conflict: every `/api/*` block must point at our function.\n for (const b of blocks) {\n if (b.from !== THEO_REDIRECT_FROM) continue\n if (b.to === THEO_REDIRECT_TO) {\n // The redirect is already there. The headers block is regenerated regardless, because it\n // carries configuration and the redirect does not.\n const sep = existing.endsWith('\\n') ? '' : '\\n'\n return `${existing}${sep}\\n${headersBlock}\\n`\n }\n throw new NetlifyConflictError(b.from, b.to ?? '(unknown)')\n }\n\n // No conflict — append target block.\n const sep = existing.endsWith('\\n') ? '' : '\\n'\n return `${existing}${sep}\\n${THEO_REDIRECT_TARGET}\\n\\n${headersBlock}\\n`\n}\n\nexport async function buildNetlify(\n config: TheoConfig,\n cwd: string,\n deps: NetlifyBuildDeps = {},\n ctx?: AdapterBuildContext,\n): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('netlify', readManifest(cwd))\n\n const runNodeBuild = deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter)\n await runNodeBuild(config, cwd, ctx)\n\n const ensureDir = deps.ensureDir ?? ((p: string) => mkdirSync(p, { recursive: true }))\n const writeFile =\n deps.writeFile ??\n ((p, c) => {\n writeFileSync(p, c)\n })\n const readTomlIfExists =\n deps.readTomlIfExists ??\n (() => {\n const p = resolve(cwd, 'netlify.toml')\n return existsSync(p) ? readFileSync(p, 'utf-8') : null\n })\n\n const fnDir = resolve(cwd, '.netlify/functions')\n ensureDir(fnDir)\n writeFile(\n resolve(fnDir, 'theo.mjs'),\n renderNetlifyFunction({\n securityHeaders: config.security?.headers,\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 )\n\n const existingToml = readTomlIfExists()\n const merged = mergeNetlifyToml(existingToml, config.security?.headers)\n writeFile(resolve(cwd, 'netlify.toml'), merged)\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ Netlify output → .netlify/functions/theo.mjs + netlify.toml')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'netlify',\n securityHeaders: config.security?.headers,\n mintsNonce: false,\n documentHeaders: 'platform-configured',\n })}\\n`,\n )\n}\n\nexport const netlifyAdapter: DeployAdapter = {\n name: 'netlify',\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 by Netlify's static host and does not pass through\n // it (usetheokit/theokit#412).\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization'],\n build(config, cwd, ctx) {\n return buildNetlify(config, cwd, {}, ctx)\n },\n}\n"],"mappings":"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","names":["sep"]}
|
|
@@ -4,8 +4,8 @@ import "tsx/esm";
|
|
|
4
4
|
// src/cli/commands/preview.ts
|
|
5
5
|
async function defaultSteps() {
|
|
6
6
|
const [{ buildCommand }, { startCommand }] = await Promise.all([
|
|
7
|
-
import("./build-
|
|
8
|
-
import("./start-
|
|
7
|
+
import("./build-CGFKWZ73.js"),
|
|
8
|
+
import("./start-ZTMQLNJI.js")
|
|
9
9
|
]);
|
|
10
10
|
return {
|
|
11
11
|
build: (opts) => buildCommand(opts),
|
|
@@ -20,4 +20,4 @@ async function previewCommand(options = {}, steps) {
|
|
|
20
20
|
export {
|
|
21
21
|
previewCommand
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=preview-
|
|
23
|
+
//# sourceMappingURL=preview-WA4HORUQ.js.map
|
|
@@ -4,13 +4,13 @@ import "tsx/esm";
|
|
|
4
4
|
// src/adapters/registry.ts
|
|
5
5
|
var adapterRegistry = {
|
|
6
6
|
node: async () => (await import("./node-OSVPYQ3D.js")).nodeAdapter,
|
|
7
|
-
vercel: async () => (await import("./vercel-
|
|
8
|
-
cloudflare: async () => (await import("./cloudflare-
|
|
7
|
+
vercel: async () => (await import("./vercel-LZTDSDJF.js")).vercelAdapter,
|
|
8
|
+
cloudflare: async () => (await import("./cloudflare-GK4VD3EU.js")).cloudflareAdapter,
|
|
9
9
|
static: async () => (await import("./static-7OJNB7D2.js")).staticAdapter,
|
|
10
|
-
bun: async () => (await import("./bun-
|
|
11
|
-
"deno-deploy": async () => (await import("./deno-deploy-
|
|
12
|
-
netlify: async () => (await import("./netlify-
|
|
13
|
-
"aws-lambda": async () => (await import("./aws-lambda-
|
|
10
|
+
bun: async () => (await import("./bun-KRUAWYRW.js")).bunAdapter,
|
|
11
|
+
"deno-deploy": async () => (await import("./deno-deploy-WMNXRVGL.js")).denoDeployAdapter,
|
|
12
|
+
netlify: async () => (await import("./netlify-VOL54SC7.js")).netlifyAdapter,
|
|
13
|
+
"aws-lambda": async () => (await import("./aws-lambda-OCJM5YGB.js")).awsLambdaAdapter,
|
|
14
14
|
"theo-cloud": async () => (await import("./theo-cloud-3ET4G5T6.js")).theoCloudAdapter
|
|
15
15
|
};
|
|
16
16
|
async function resolveAdapter(target) {
|
|
@@ -20,4 +20,4 @@ async function resolveAdapter(target) {
|
|
|
20
20
|
export {
|
|
21
21
|
resolveAdapter
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=registry-
|
|
23
|
+
//# sourceMappingURL=registry-DDBXDHJ2.js.map
|