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
package/README.md
CHANGED
|
@@ -38,6 +38,27 @@ Node `>= 22.12.0`. Peers: `react`, `react-dom`, `react-router`, `zod`, and — w
|
|
|
38
38
|
| `server/ws/chat.ts` | `ws://…/ws/chat` |
|
|
39
39
|
| `server/middleware/01-cors.ts` | request middleware, in filename order |
|
|
40
40
|
|
|
41
|
+
### `next` is supported on one of the two paths
|
|
42
|
+
|
|
43
|
+
A middleware receives `(request, context, next)`. What `next` does depends on which runner is
|
|
44
|
+
executing it, and the two differ today:
|
|
45
|
+
|
|
46
|
+
| path | `next` |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `executeWebRequest` — the Web runner | runs the rest of the chain **and the route**, so code after `await next()` observes the route's response |
|
|
49
|
+
| `server/middleware/*.ts` — the file-scan runner | **refuses.** It runs BEFORE routing, so there is no downstream to await |
|
|
50
|
+
|
|
51
|
+
The file-scan path throws `MiddlewareNextUnavailableError`, naming the alternative. It used to
|
|
52
|
+
accept the call and continue silently, which meant the code after `await next()` never ran and
|
|
53
|
+
nothing said so.
|
|
54
|
+
|
|
55
|
+
**This is a real limitation, not a bug being hidden.** Closing it means either folding the
|
|
56
|
+
file-scan path so the chain wraps the route, or retiring this contract for a single one; both are
|
|
57
|
+
large and the choice is open — `docs/adr/0003` § *AMENDED 2026-09-21* records what each costs.
|
|
58
|
+
|
|
59
|
+
Write a `server/middleware/*.ts` middleware that returns a `Response` to answer the request, or
|
|
60
|
+
returns nothing to continue. Use the Web path when you need code to run after the route.
|
|
61
|
+
|
|
41
62
|
## Authoring surfaces
|
|
42
63
|
|
|
43
64
|
Every surface is a fluent builder whose `.build()` is a compile error while a required link is
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-425FJKKO.js";
|
|
2
|
+
import "./chunk-MOGTMGGA.js";
|
|
3
3
|
import "./chunk-WSOAN4KN.js";
|
|
4
4
|
import "./chunk-ENSFCKP6.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-SRJBH5E5.js";
|
|
6
|
+
import "./chunk-3T5XLDOH.js";
|
|
6
7
|
import "./chunk-P6OS7652.js";
|
|
7
8
|
import "./chunk-ZDUO4IYN.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-ENRT6DAU.js";
|
|
9
|
+
import "./chunk-IDWN2OSG.js";
|
|
10
10
|
import "./chunk-47FFT43U.js";
|
|
11
11
|
import "./chunk-NTDN54XO.js";
|
|
12
12
|
import "./chunk-PVNMLZ5G.js";
|
|
@@ -234,4 +234,4 @@ export const actions = manifest
|
|
|
234
234
|
export {
|
|
235
235
|
actionsVirtualModule
|
|
236
236
|
};
|
|
237
|
-
//# sourceMappingURL=actions-virtual-module-
|
|
237
|
+
//# sourceMappingURL=actions-virtual-module-DH3N34I6.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
import "./chunk-SJ4AW54X.js";
|
|
4
|
+
import "./chunk-BINRCILF.js";
|
|
5
5
|
import "./chunk-QD5X56I3.js";
|
|
6
6
|
import "./chunk-WSMLSIS5.js";
|
|
7
7
|
import "./chunk-MS4A7N77.js";
|
|
@@ -218,4 +218,4 @@ export const actions = manifest
|
|
|
218
218
|
export {
|
|
219
219
|
actionsVirtualModule
|
|
220
220
|
};
|
|
221
|
-
//# sourceMappingURL=actions-virtual-module-
|
|
221
|
+
//# sourceMappingURL=actions-virtual-module-OMIFGXK6.js.map
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { a as RouteSubject, R as RoutePolicy } from '../route-policy-BHXQDzBF.js';
|
|
2
2
|
import { C as CsrfMode } from '../csrf-Dgot9qSM.js';
|
|
3
3
|
export { r as resolveProvider } from '../provider-resolver-Cc9C3-Rb.js';
|
|
4
|
+
import { A as AgentNode } from '../agent-scan-BZa-pagG.js';
|
|
4
5
|
export { s as scanAgents } from '../agent-scan-BZa-pagG.js';
|
|
5
|
-
import 'node:http';
|
|
6
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
|
+
import { P as PluginRunner } from '../plugin-runner-BVMOSxvb.js';
|
|
8
|
+
import { L as LoadModule } from '../module-loader-DCip7NoL.js';
|
|
6
9
|
import '../audit-log-BQWM5YLG.js';
|
|
10
|
+
import '../plugin-types-BUVfUQ0V.js';
|
|
11
|
+
import 'vite';
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* ADR 0001, applied to the agent surface (usetheokit/theokit#365).
|
|
@@ -132,4 +137,187 @@ interface MountAgentOptions {
|
|
|
132
137
|
*/
|
|
133
138
|
declare function mountAgent(mod: unknown, request: Request, apiKey: string | ApiKeyResolver, { source, csrfMode, projectRoot, agentName, policy, resolveSubject, }?: MountAgentOptions): Promise<Response>;
|
|
134
139
|
|
|
135
|
-
|
|
140
|
+
/** Dependencies the aux dispatcher needs from its caller (dev or prod). */
|
|
141
|
+
interface AuxRouteDeps {
|
|
142
|
+
/** Discovered agents (from `scanAgents`). */
|
|
143
|
+
agents: readonly AgentNode[];
|
|
144
|
+
/** Load an agent module from its file path (dev: vite loader; prod: dynamic import). */
|
|
145
|
+
loadModule: (filePath: string) => Promise<unknown>;
|
|
146
|
+
/** Absolute base URL (`http(s)://host`) for the agent-card endpoint URLs. */
|
|
147
|
+
baseUrl: string;
|
|
148
|
+
/**
|
|
149
|
+
* M34 (#97) — CSRF enforcement mode for the MCP route. `POST /api/agents/<name>/mcp` drives the
|
|
150
|
+
* agent (spends LLM tokens), so a cross-origin POST MUST be rejected in `'strict'` — parity with
|
|
151
|
+
* the agent-run route (`mount-agent.ts:83-91`). Defaults to `'strict'` (safe-by-default); a caller
|
|
152
|
+
* that already gated upstream may pass `'off'`.
|
|
153
|
+
*/
|
|
154
|
+
csrfMode?: CsrfMode;
|
|
155
|
+
/**
|
|
156
|
+
* M39 — lazily resolve the provider apiKey. Required only for the thread
|
|
157
|
+
* follow-up route (which drives the agent); resolved on demand so non-agent
|
|
158
|
+
* aux routes (card, approvals, stream) never need a provider key.
|
|
159
|
+
*
|
|
160
|
+
* theokit#328 — it receives the model the agent declares, so the credential matches the provider
|
|
161
|
+
* the agent asked for. It was called with no argument, before the module was even compiled, so
|
|
162
|
+
* an agent declaring `anthropic/…` was handed whichever key env priority found first.
|
|
163
|
+
*/
|
|
164
|
+
resolveApiKey?: ApiKeyResolver;
|
|
165
|
+
/**
|
|
166
|
+
* Who is asking (usetheokit/theokit#365). Invoked ONLY from {@link serveMatchedAuxRoute}, and only
|
|
167
|
+
* when the matched path's agent declares a policy — so the application's `createContext` never
|
|
168
|
+
* runs for a url this dispatcher merely declines. {@link matchAgentAuxRoute} is not given it, for
|
|
169
|
+
* the same reason it is not given the request body: deciding must cost nothing.
|
|
170
|
+
*/
|
|
171
|
+
resolveSubject?: AgentSubjectResolver;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* One aux route, already decided. Carries what the match resolved so the serve half re-derives
|
|
175
|
+
* nothing: the agent node it looked up, and for MCP the module it had to open in order to answer
|
|
176
|
+
* the opt-in question at all.
|
|
177
|
+
*/
|
|
178
|
+
type AgentAuxRoute = {
|
|
179
|
+
readonly kind: 'card';
|
|
180
|
+
readonly agent: AgentNode;
|
|
181
|
+
} | {
|
|
182
|
+
readonly kind: 'approvals';
|
|
183
|
+
readonly agent: AgentNode;
|
|
184
|
+
} | {
|
|
185
|
+
readonly kind: 'run-stream';
|
|
186
|
+
readonly agent: AgentNode;
|
|
187
|
+
readonly runId: string;
|
|
188
|
+
} | {
|
|
189
|
+
readonly kind: 'thread-stream';
|
|
190
|
+
readonly agent: AgentNode;
|
|
191
|
+
readonly sessionId: string;
|
|
192
|
+
} | {
|
|
193
|
+
readonly kind: 'thread-message';
|
|
194
|
+
readonly agent: AgentNode;
|
|
195
|
+
readonly sessionId: string;
|
|
196
|
+
} | {
|
|
197
|
+
readonly kind: 'mcp';
|
|
198
|
+
readonly agent: AgentNode;
|
|
199
|
+
readonly mod: unknown;
|
|
200
|
+
};
|
|
201
|
+
/**
|
|
202
|
+
* Does this dispatcher own `urlPath`? Returns the matched route, or `null` to fall through (not an
|
|
203
|
+
* aux path, wrong method, unknown agent, or an agent that did not opt into MCP).
|
|
204
|
+
*
|
|
205
|
+
* theokit#400 — this function is where the "convert only on a path you are about to answer" rule
|
|
206
|
+
* now lives, and it is enforced by the signature rather than by discipline: it is handed a method
|
|
207
|
+
* and a url and has no request to convert. Converting in order to decide is what drained the Node
|
|
208
|
+
* body stream on every path this dispatcher declined, so an ordinary `POST /api/…` file route then
|
|
209
|
+
* waited forever for an `'end'` that had already fired — no status, no timeout, no response.
|
|
210
|
+
*
|
|
211
|
+
* The one branch that does real work here is MCP, which must open the module to read its
|
|
212
|
+
* `export const mcp` opt-in. That is deliberate: a match that could still fall through would hand
|
|
213
|
+
* the caller a request it had already started a lifecycle for, and the span opened for it would
|
|
214
|
+
* either double-count or never close.
|
|
215
|
+
*/
|
|
216
|
+
declare function matchAgentAuxRoute(method: string, urlPath: string, deps: AuxRouteDeps): Promise<AgentAuxRoute | null>;
|
|
217
|
+
/**
|
|
218
|
+
* Answer a route {@link matchAgentAuxRoute} already claimed. Always returns a `Response` — every
|
|
219
|
+
* fall-through was decided upstream, which is what lets a caller open a request span before this
|
|
220
|
+
* runs and be sure something will close it.
|
|
221
|
+
*/
|
|
222
|
+
declare function serveMatchedAuxRoute(route: AgentAuxRoute, request: Request, deps: AuxRouteDeps): Promise<Response>;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Who is asking, on the Node dispatch path that serves the agent endpoints
|
|
226
|
+
* (usetheokit/theokit#365).
|
|
227
|
+
*
|
|
228
|
+
* `executeRoute` answers this with `subjectFromContext(ctx)`, where `ctx` is the run context built
|
|
229
|
+
* from the application's `server/context.ts` plus plugin decorations. The agent branches build no
|
|
230
|
+
* such context — which is why `mountAgent`'s `subject` option had nowhere to come from and every
|
|
231
|
+
* caller left it out. This builds the same context from the same two sources, so the agent surface
|
|
232
|
+
* reads identity from the seam the routes already read it from rather than from a second one.
|
|
233
|
+
*
|
|
234
|
+
* ## Why it returns a resolver instead of a subject
|
|
235
|
+
*
|
|
236
|
+
* `tryServeAgentAux` runs for EVERY url, including the ones it does not own. Resolving eagerly
|
|
237
|
+
* there would execute the application's `createContext` twice on every route request — once in the
|
|
238
|
+
* aux branch that falls through, once in the route executor. So callers get a memoized thunk and
|
|
239
|
+
* invoke it only on a path they are about to answer, which is the same discipline theokit#400
|
|
240
|
+
* imposed on `source.toRequest()` for the same dispatcher.
|
|
241
|
+
*
|
|
242
|
+
* ## What `createContext` can read here, and what it cannot (usetheokit/theokit#415)
|
|
243
|
+
*
|
|
244
|
+
* **Headers and cookies: yes. The request body: no.**
|
|
245
|
+
*
|
|
246
|
+
* This used to state the opposite as a MUST — "invoke it before converting the request to a Web
|
|
247
|
+
* `Request`" — and no caller could honour it. The laziness argued for directly above is what makes
|
|
248
|
+
* it unsatisfiable: the invocation necessarily happens INSIDE the handler, and the handler is
|
|
249
|
+
* entered after `serveThroughPluginLifecycle` has already called `source.toRequest()` at the top of
|
|
250
|
+
* its bracket. `incomingMessageToWebRequest` attaches the Node readable as the request body
|
|
251
|
+
* (`body: webStream, duplex: 'half'`), so by the time an application's `createContext` receives
|
|
252
|
+
* that `IncomingMessage`, the stream is consumed.
|
|
253
|
+
*
|
|
254
|
+
* The contract was written for an EAGER resolver and kept when the resolver became lazy. Both
|
|
255
|
+
* decisions were right on their own; the sentence joining them was not, and it pointed callers at
|
|
256
|
+
* something impossible while implying a capability that does not exist.
|
|
257
|
+
*
|
|
258
|
+
* Practically this costs little — identity is overwhelmingly a header or a cookie, and both survive
|
|
259
|
+
* the conversion untouched. What it costs an application that resolves identity from the BODY is an
|
|
260
|
+
* empty read or a wait for an `'end'` that already fired, which is why saying so plainly matters
|
|
261
|
+
* more than the frequency suggests.
|
|
262
|
+
*
|
|
263
|
+
* Restoring body access would mean resolving eagerly — running the application's `createContext`
|
|
264
|
+
* twice on every route request, which is exactly what the laziness exists to prevent — or buffering
|
|
265
|
+
* every agent request body to replay it, which is a cost paid by every caller for a case almost
|
|
266
|
+
* none has.
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
/** What {@link createAgentSubjectResolver} needs in order to build the run context. */
|
|
270
|
+
interface AgentSubjectSources {
|
|
271
|
+
req: IncomingMessage;
|
|
272
|
+
res: ServerResponse;
|
|
273
|
+
loadModule: LoadModule;
|
|
274
|
+
/** The app's `server/` directory. Absent ⇒ there is no `context.ts` to consult. */
|
|
275
|
+
serverDir: string | undefined;
|
|
276
|
+
pluginRunner: PluginRunner | undefined;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Build a memoized resolver for the caller's identity.
|
|
280
|
+
*
|
|
281
|
+
* Decorations are applied ON TOP of the factory's result, matching `executeRoute`: a plugin
|
|
282
|
+
* decoration wins only where `context.ts` did not set the same key.
|
|
283
|
+
*
|
|
284
|
+
* A `createContext` that throws is not swallowed — an application whose identity resolution is
|
|
285
|
+
* broken must not be treated as an anonymous caller, because that reads as a clean refusal and
|
|
286
|
+
* hides the fault. The throw reaches the branch's own error handler and becomes a 500.
|
|
287
|
+
*/
|
|
288
|
+
declare function createAgentSubjectResolver(sources: AgentSubjectSources): () => Promise<RouteSubject | null>;
|
|
289
|
+
/**
|
|
290
|
+
* The app's `createContext`, as a host that is not Node sees it.
|
|
291
|
+
*
|
|
292
|
+
* Deliberately NOT `middleware-runner`'s `ContextFactory`, which types its argument as
|
|
293
|
+
* `IncomingMessage`/`ServerResponse`. Those are exactly right for the dev path and wrong here: on
|
|
294
|
+
* every deploy target the pair is what `createWebShim` synthesises over a Web `Request`. Widening
|
|
295
|
+
* to `unknown` says what is actually true at this boundary rather than casting a lie past the
|
|
296
|
+
* type system — the app's own `createContext` is typed by the app, and a generated fragment is the
|
|
297
|
+
* one caller that cannot promise it Node objects.
|
|
298
|
+
*/
|
|
299
|
+
type HostContextFactory = (args: {
|
|
300
|
+
request: unknown;
|
|
301
|
+
response: unknown;
|
|
302
|
+
}) => unknown;
|
|
303
|
+
/**
|
|
304
|
+
* The half that CALLS an already-resolved context factory (B-185, ADR 0014).
|
|
305
|
+
*
|
|
306
|
+
* {@link createAgentSubjectResolver} does two things: it LOCATES `context.ts` on a filesystem —
|
|
307
|
+
* `existsSync` plus `loadModule`, inside `createServerContext` — and then CALLS what it found. A
|
|
308
|
+
* deploy target with no filesystem can do the second and not the first, so the generator bakes the
|
|
309
|
+
* module as a static import (the way routes, agents and plugins already are) and hands the factory
|
|
310
|
+
* here directly.
|
|
311
|
+
*
|
|
312
|
+
* Measured before this existed: passing `serverDir: undefined` to the resolver above takes its
|
|
313
|
+
* `produced = {}` branch, never touches `req`/`res`/`loadModule`, and returns
|
|
314
|
+
* `subjectFromContext({})` — which is null for every caller. Satisfying its types would have
|
|
315
|
+
* satisfied nothing.
|
|
316
|
+
*
|
|
317
|
+
* `request`/`response` are whatever the host has. On every deploy target that is the
|
|
318
|
+
* `ShimRequest`/`ShimResponse` pair `createWebShim` synthesises over a Web `Request`, which is the
|
|
319
|
+
* same contract routes on those targets have crossed since they were baked.
|
|
320
|
+
*/
|
|
321
|
+
declare function createSubjectResolverFromFactory(createContext: HostContextFactory | undefined, request: unknown, response: unknown, pluginRunner?: PluginRunner): () => Promise<RouteSubject | null>;
|
|
322
|
+
|
|
323
|
+
export { createAgentSubjectResolver, createSubjectResolverFromFactory, matchAgentAuxRoute, mountAgent, serveMatchedAuxRoute };
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAgentSubjectResolver,
|
|
3
|
+
createSubjectResolverFromFactory,
|
|
4
|
+
matchAgentAuxRoute,
|
|
5
|
+
serveMatchedAuxRoute
|
|
6
|
+
} from "../chunk-BDPD5HEO.js";
|
|
1
7
|
import {
|
|
2
8
|
mountAgent
|
|
3
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-MOGTMGGA.js";
|
|
10
|
+
import "../chunk-3T5XLDOH.js";
|
|
4
11
|
import "../chunk-P6OS7652.js";
|
|
5
|
-
import "../chunk-
|
|
12
|
+
import "../chunk-IDWN2OSG.js";
|
|
6
13
|
import "../chunk-PVNMLZ5G.js";
|
|
7
14
|
import "../chunk-ZDCCILMP.js";
|
|
8
15
|
import "../chunk-CHTAWXC2.js";
|
|
@@ -10,6 +17,10 @@ import "../chunk-AVQU5CQF.js";
|
|
|
10
17
|
import {
|
|
11
18
|
scanAgents
|
|
12
19
|
} from "../chunk-KDP2HURW.js";
|
|
20
|
+
import "../chunk-V6Y2SMRG.js";
|
|
21
|
+
import "../chunk-ACKBVBUI.js";
|
|
22
|
+
import "../chunk-IZ3TIL6K.js";
|
|
23
|
+
import "../chunk-TQEE36VD.js";
|
|
13
24
|
import {
|
|
14
25
|
resolveProvider
|
|
15
26
|
} from "../chunk-ICXXHV4V.js";
|
|
@@ -18,8 +29,12 @@ import "../chunk-SOYOYGWY.js";
|
|
|
18
29
|
import "../chunk-ZWN3AODA.js";
|
|
19
30
|
import "../chunk-XTHN6JBX.js";
|
|
20
31
|
export {
|
|
32
|
+
createAgentSubjectResolver,
|
|
33
|
+
createSubjectResolverFromFactory,
|
|
34
|
+
matchAgentAuxRoute,
|
|
21
35
|
mountAgent,
|
|
22
36
|
resolveProvider,
|
|
23
|
-
scanAgents
|
|
37
|
+
scanAgents,
|
|
38
|
+
serveMatchedAuxRoute
|
|
24
39
|
};
|
|
25
40
|
//# sourceMappingURL=agent-mount.js.map
|
|
@@ -57,6 +57,22 @@ export { b as buildSecurityHeaders } from '../security-headers-vris2MQq.js';
|
|
|
57
57
|
* (`cli/commands/start/index.ts`). An app with no security block gets the same
|
|
58
58
|
* baseline deployed as it gets locally.
|
|
59
59
|
*/
|
|
60
|
+
/**
|
|
61
|
+
* The two declarations every deploy entry emits to carry the security baseline.
|
|
62
|
+
*
|
|
63
|
+
* Four adapters wrote these same two lines — `netlify`, `vercel`, `aws-lambda`, `deno-deploy` —
|
|
64
|
+
* each under a comment naming its own host's static-asset boundary. The COMMENT differs and is
|
|
65
|
+
* meant to; the declarations do not.
|
|
66
|
+
*
|
|
67
|
+
* Extracted after SonarCloud's duplication gate failed a PR at 4.0% against a 3% ceiling and named
|
|
68
|
+
* this as the largest repeated block among the changed files. The gate was measuring something
|
|
69
|
+
* real: a literal renderer and a builder call, copied four times, is four places to update when
|
|
70
|
+
* either changes.
|
|
71
|
+
*
|
|
72
|
+
* Returns the lines rather than a joined string, because every caller splices them into an array
|
|
73
|
+
* of emitted lines.
|
|
74
|
+
*/
|
|
75
|
+
declare function securityHeadersDeclarations(config: SecurityHeadersConfig | undefined): string[];
|
|
60
76
|
declare function renderSecurityHeadersConfigLiteral(headers: SecurityHeadersConfig | undefined): string;
|
|
61
77
|
/**
|
|
62
78
|
* Put the headers on a response, without overruling the handler.
|
|
@@ -129,4 +145,4 @@ interface DeployedSecurityHeaderLimits {
|
|
|
129
145
|
*/
|
|
130
146
|
declare function describeDeployedSecurityHeaders(limits: DeployedSecurityHeaderLimits): string;
|
|
131
147
|
|
|
132
|
-
export { type DeployedSecurityHeaderLimits, describeDeployedSecurityHeaders, renderSecurityHeadersConfigLiteral, withSecurityHeaders };
|
|
148
|
+
export { type DeployedSecurityHeaderLimits, describeDeployedSecurityHeaders, renderSecurityHeadersConfigLiteral, securityHeadersDeclarations, withSecurityHeaders };
|
|
@@ -7,6 +7,12 @@ import {
|
|
|
7
7
|
import "../chunk-XTHN6JBX.js";
|
|
8
8
|
|
|
9
9
|
// src/adapters/security-headers.ts
|
|
10
|
+
function securityHeadersDeclarations(config) {
|
|
11
|
+
return [
|
|
12
|
+
`const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(config)}`,
|
|
13
|
+
`const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`
|
|
14
|
+
];
|
|
15
|
+
}
|
|
10
16
|
function renderSecurityHeadersConfigLiteral(headers) {
|
|
11
17
|
return JSON.stringify(headers ?? {});
|
|
12
18
|
}
|
|
@@ -59,6 +65,7 @@ export {
|
|
|
59
65
|
describeDeployedSecurityHeaders,
|
|
60
66
|
generateNonce,
|
|
61
67
|
renderSecurityHeadersConfigLiteral,
|
|
68
|
+
securityHeadersDeclarations,
|
|
62
69
|
withSecurityHeaders
|
|
63
70
|
};
|
|
64
71
|
//# sourceMappingURL=security-headers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/adapters/security-headers.ts"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/security-headers.ts"],"mappings":";;;;;;;;;AA6FO,SAAS,4BAA4B,QAAqD;AAC/F,SAAO;AAAA,IACL,mCAAmC,mCAAmC,MAAM,CAAC;AAAA,IAC7E;AAAA,EACF;AACF;AAEO,SAAS,mCACd,SACQ;AACR,SAAO,KAAK,UAAU,WAAW,CAAC,CAAC;AACrC;AAyBO,SAAS,oBAAoB,UAAoB,SAA2C;AACjG,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,QAAI,CAAC,SAAS,QAAQ,IAAI,GAAG,EAAG,UAAS,QAAQ,IAAI,KAAK,KAAK;AAAA,EACjE;AACA,SAAO;AACT;AAgDO,SAAS,gCAAgC,QAA8C;AAC5F,QAAM,UAAU,qBAAqB,OAAO,mBAAmB,CAAC,GAAG,EAAE,YAAY,KAAK,CAAC;AACvF,QAAM,QAAQ,OAAO,KAAK,OAAO;AACjC,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAEA,QAAM,QAAQ;AAAA,IACZ,iDAA4C,OAAO,MAAM,eAAe,MAAM,KAAK,IAAI,CAAC;AAAA,EAC1F;AACA,QAAM,WAAW,MAAM,KAAK,CAAC,SAAS,KAAK,WAAW,yBAAyB,CAAC;AAChF,MAAI,YAAY,CAAC,OAAO,YAAY;AAClC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,oBAAoB,uBAAuB;AACpD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,oBAAoB,sBAAsB;AACnD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
|
@@ -3,8 +3,8 @@ import "tsx/esm";
|
|
|
3
3
|
import {
|
|
4
4
|
agentCommand,
|
|
5
5
|
createAgentSsrLoader
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-TJPENLGQ.js";
|
|
7
|
+
import "./chunk-BINRCILF.js";
|
|
8
8
|
import "./chunk-5NNFO7R7.js";
|
|
9
9
|
import "./chunk-Z7CJHDLS.js";
|
|
10
10
|
import "./chunk-3QPVEJ7D.js";
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
agentCommand,
|
|
13
13
|
createAgentSsrLoader
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=agent-
|
|
15
|
+
//# sourceMappingURL=agent-7RPGAKTY.js.map
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
scanControllerModules
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-425FJKKO.js";
|
|
4
|
+
import "./chunk-MOGTMGGA.js";
|
|
5
5
|
import "./chunk-WSOAN4KN.js";
|
|
6
6
|
import "./chunk-ENSFCKP6.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-SRJBH5E5.js";
|
|
8
|
+
import "./chunk-3T5XLDOH.js";
|
|
8
9
|
import "./chunk-P6OS7652.js";
|
|
9
10
|
import "./chunk-ZDUO4IYN.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-ENRT6DAU.js";
|
|
11
|
+
import "./chunk-IDWN2OSG.js";
|
|
12
12
|
import "./chunk-47FFT43U.js";
|
|
13
13
|
import "./chunk-NTDN54XO.js";
|
|
14
14
|
import "./chunk-PVNMLZ5G.js";
|
|
@@ -427,4 +427,4 @@ export {
|
|
|
427
427
|
generateClientDts,
|
|
428
428
|
shouldReemitForFile
|
|
429
429
|
};
|
|
430
|
-
//# sourceMappingURL=app-typed-client-
|
|
430
|
+
//# sourceMappingURL=app-typed-client-C4LRUSIS.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
import "./chunk-SJ4AW54X.js";
|
|
4
|
+
import "./chunk-BINRCILF.js";
|
|
5
5
|
import {
|
|
6
6
|
scanControllerModules
|
|
7
7
|
} from "./chunk-QD5X56I3.js";
|
|
@@ -411,4 +411,4 @@ export {
|
|
|
411
411
|
generateClientDts,
|
|
412
412
|
shouldReemitForFile
|
|
413
413
|
};
|
|
414
|
-
//# sourceMappingURL=app-typed-client-
|
|
414
|
+
//# sourceMappingURL=app-typed-client-R6OUJZEE.js.map
|
|
@@ -1,14 +1,18 @@
|
|
|
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
|
-
|
|
13
|
+
scannedFromLoaderCache,
|
|
10
14
|
serverDirLiteral
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-FFGP2LGQ.js";
|
|
12
16
|
import {
|
|
13
17
|
nodeAdapter
|
|
14
18
|
} from "./chunk-KI4DOTN4.js";
|
|
@@ -59,7 +63,7 @@ function responseToLambdaResultV2(statusCode, headers, body) {
|
|
|
59
63
|
isBase64Encoded: isBinary
|
|
60
64
|
};
|
|
61
65
|
}
|
|
62
|
-
function awsLambdaHandlerFragment(runtimeSpread) {
|
|
66
|
+
function awsLambdaHandlerFragment(runtimeSpread, agentsBranch, agentsHostBypass) {
|
|
63
67
|
return [
|
|
64
68
|
`// #382 \u2014 this target is DELISTED for response streaming, by construction.`,
|
|
65
69
|
`// The Lambda v2 result object below carries \`body\` as a string, so the`,
|
|
@@ -119,7 +123,7 @@ function awsLambdaHandlerFragment(runtimeSpread) {
|
|
|
119
123
|
`}`,
|
|
120
124
|
``,
|
|
121
125
|
`async function routeRequest(event, path) {`,
|
|
122
|
-
` if (!path.startsWith('/api/')) {`,
|
|
126
|
+
` if (!path.startsWith('/api/')${agentsHostBypass}) {`,
|
|
123
127
|
` return new Response(`,
|
|
124
128
|
` 'Static assets must be served from CloudFront or a separate static host.',`,
|
|
125
129
|
` { status: 404, headers: { 'content-type': 'text/plain' } },`,
|
|
@@ -129,15 +133,18 @@ function awsLambdaHandlerFragment(runtimeSpread) {
|
|
|
129
133
|
` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,
|
|
130
134
|
` if (!loaderCache) loaderCache = createProductionLoader()`,
|
|
131
135
|
``,
|
|
136
|
+
// B-235 — hoisted above the agents branch, which names `request` like every other host's.
|
|
137
|
+
// It was declared below `matchRoute`, and an agent path never reaches a route match. Building
|
|
138
|
+
// it here costs nothing new: the outer handler already built one for the CORS matcher, and
|
|
139
|
+
// `eventV2ToRequest` reads a body the event already carries, so there is no stream to drain
|
|
140
|
+
// twice.
|
|
141
|
+
` const request = eventV2ToRequest(event)`,
|
|
142
|
+
``,
|
|
143
|
+
...agentsBranch,
|
|
144
|
+
``,
|
|
132
145
|
` const match = matchRoute(path, routesCache)`,
|
|
133
|
-
` if (!match) {`,
|
|
134
|
-
` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,
|
|
135
|
-
` status: 404,`,
|
|
136
|
-
` headers: { 'content-type': 'application/json' },`,
|
|
137
|
-
` })`,
|
|
138
|
-
` }`,
|
|
146
|
+
` if (!match) return ${JSON_NOT_FOUND_RESPONSE}`,
|
|
139
147
|
``,
|
|
140
|
-
` const request = eventV2ToRequest(event)`,
|
|
141
148
|
` const { req, res, toResponse } = createWebShim(request)`,
|
|
142
149
|
...deployedTraceFragment("request", " "),
|
|
143
150
|
` const method = request.method.toUpperCase()`,
|
|
@@ -147,6 +154,10 @@ function awsLambdaHandlerFragment(runtimeSpread) {
|
|
|
147
154
|
}
|
|
148
155
|
function renderAwsLambdaEntry(opts = {}) {
|
|
149
156
|
const runtimeConfig = deployedRuntimeConfigFragment(opts);
|
|
157
|
+
const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {
|
|
158
|
+
pathname: "path",
|
|
159
|
+
notFound: JSON_NOT_FOUND_RESPONSE
|
|
160
|
+
});
|
|
150
161
|
return [
|
|
151
162
|
`// Generated by Theo \u2014 AWS Lambda Adapter`,
|
|
152
163
|
`// Use with API Gateway HTTP API v2 (default).`,
|
|
@@ -166,14 +177,7 @@ function renderAwsLambdaEntry(opts = {}) {
|
|
|
166
177
|
`// theo.config.ts to read. Non-API paths 404 here and the document is served`,
|
|
167
178
|
`// from CloudFront or another static host, so this covers the API and not the`,
|
|
168
179
|
`// page (usetheokit/theokit#412).`,
|
|
169
|
-
|
|
170
|
-
`const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,
|
|
171
|
-
``,
|
|
172
|
-
...runtimeConfig.imports,
|
|
173
|
-
...runtimeConfig.declarations,
|
|
174
|
-
...deployedCsrfFragment(opts),
|
|
175
|
-
``,
|
|
176
|
-
...deployedCorsFragment(opts.cors, "aws-lambda"),
|
|
180
|
+
...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, "aws-lambda"),
|
|
177
181
|
``,
|
|
178
182
|
`function eventV2ToRequest(event) {`,
|
|
179
183
|
` const method = event.requestContext?.http?.method ?? 'GET'`,
|
|
@@ -196,7 +200,11 @@ function renderAwsLambdaEntry(opts = {}) {
|
|
|
196
200
|
` })`,
|
|
197
201
|
`}`,
|
|
198
202
|
``,
|
|
199
|
-
...awsLambdaHandlerFragment(
|
|
203
|
+
...awsLambdaHandlerFragment(
|
|
204
|
+
runtimeConfig.executeRouteSpread,
|
|
205
|
+
agentsFragment.branch,
|
|
206
|
+
agentsFragment.hostBypass
|
|
207
|
+
)
|
|
200
208
|
].join("\n");
|
|
201
209
|
}
|
|
202
210
|
async function buildAwsLambda(config, cwd, deps = {}, ctx) {
|
|
@@ -213,6 +221,10 @@ async function buildAwsLambda(config, cwd, deps = {}, ctx) {
|
|
|
213
221
|
ensureDir(outputDir);
|
|
214
222
|
const entry = renderAwsLambdaEntry({
|
|
215
223
|
securityHeaders: config.security?.headers,
|
|
224
|
+
// B-235 — pillar (a): the option existed and no build passed it, so a project with a
|
|
225
|
+
// configured agents directory got the default `agents` on this target. Same defect
|
|
226
|
+
// B-185 fixed for bun and deno, one target over.
|
|
227
|
+
agentsDir: config.agentsDir,
|
|
216
228
|
csrf: config.security?.csrf,
|
|
217
229
|
disallowed: config.security?.disallowed,
|
|
218
230
|
cors: config.security?.cors,
|
|
@@ -259,4 +271,4 @@ export {
|
|
|
259
271
|
renderAwsLambdaEntry,
|
|
260
272
|
responseToLambdaResultV2
|
|
261
273
|
};
|
|
262
|
-
//# sourceMappingURL=aws-lambda-
|
|
274
|
+
//# sourceMappingURL=aws-lambda-OCJM5YGB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/aws-lambda.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * AWS Lambda adapter. Writes to `cwd/.theokit/lambda/`. Build-time tool.\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 {\n deployedAgentsFragment,\n scannedFromLoaderCache,\n JSON_NOT_FOUND_RESPONSE,\n} from './deployed-agents.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 AwsLambdaBuildDeps {\n runNodeBuild?: (config: TheoConfig, cwd: string, ctx?: AdapterBuildContext) => Promise<void>\n writeEntry?: (path: string, content: string) => void\n ensureDir?: (path: string) => void\n}\n\nexport interface RequestShape {\n method: string\n path: string\n headers: Record<string, string>\n body?: string\n}\n\nexport interface LambdaResultV2 {\n statusCode: number\n headers: Record<string, string>\n body: string\n isBase64Encoded: boolean\n}\n\nconst BINARY_CONTENT_TYPES = [\n 'application/octet-stream',\n 'application/pdf',\n 'application/zip',\n 'image/',\n 'audio/',\n 'video/',\n]\n\nfunction isBinaryContentType(contentType: string | undefined): boolean {\n if (!contentType) return false\n const ct = contentType.toLowerCase()\n return BINARY_CONTENT_TYPES.some((prefix) => ct.startsWith(prefix))\n}\n\ninterface APIGatewayProxyEventV2 {\n version: string\n requestContext: {\n http: { method: string; path: string }\n }\n headers?: Record<string, string | undefined>\n body?: string\n isBase64Encoded?: boolean\n}\n\nexport function eventV2ToRequestShape(event: APIGatewayProxyEventV2): RequestShape {\n const headers: Record<string, string> = {}\n for (const [k, v] of Object.entries(event.headers ?? {})) {\n if (v !== undefined) headers[k] = v\n }\n let body: string | undefined = event.body\n if (body !== undefined && event.isBase64Encoded) {\n body = Buffer.from(body, 'base64').toString('utf-8')\n }\n return {\n method: event.requestContext.http.method,\n path: event.requestContext.http.path,\n headers,\n body,\n }\n}\n\nexport function responseToLambdaResultV2(\n statusCode: number,\n headers: Record<string, string>,\n body: string,\n): LambdaResultV2 {\n const isBinary = isBinaryContentType(headers['content-type'])\n return {\n statusCode,\n headers,\n body: isBinary ? Buffer.from(body, 'binary').toString('base64') : body,\n isBase64Encoded: isBinary,\n }\n}\n\n// Generated-code fragments — extracted so the parent emitter stays under the\n// max-lines-per-function ceiling.\n/** The v2 result conversion, the handler, and the routing that feeds them. */\nfunction awsLambdaHandlerFragment(\n runtimeSpread: string,\n agentsBranch: readonly string[],\n agentsHostBypass: string,\n): string[] {\n return [\n `// #382 — this target is DELISTED for response streaming, by construction.`,\n `// The Lambda v2 result object below carries \\`body\\` as a string, so the`,\n `// response cannot exist until the run has finished, no matter how the`,\n `// framework's shim writes it. Streaming here would require`,\n `// \\`awslambda.streamifyResponse\\` plus a Function URL in RESPONSE_STREAM`,\n `// invoke mode — neither of which this adapter emits, and which would break`,\n `// every API Gateway deployment of it. Rather than degrade in silence, a`,\n `// response that is unambiguously a stream is named in the logs below.`,\n `async function responseToV2Result(response, routePath) {`,\n ` const headers = {}`,\n ` response.headers.forEach((v, k) => { headers[k] = v })`,\n ` const ct = headers['content-type'] ?? ''`,\n ` if (ct.includes('text/event-stream')) {`,\n ` console.warn(`,\n ` '[theo][aws-lambda] ' + routePath + ' returned a streaming response (' + ct + '), ' +`,\n ` 'but the aws-lambda target buffers it whole and delivers it when the run ends. ' +`,\n ` 'This target is delisted for streaming (theokit#382). Deploy streaming routes to ' +`,\n ` 'cloudflare, vercel, netlify, bun, deno-deploy or node.'`,\n ` )`,\n ` }`,\n ` const isBinary = /^application\\\\/(octet-stream|pdf|zip)|^(image|audio|video)\\\\//.test(ct)`,\n ` if (isBinary) {`,\n ` const buf = Buffer.from(await response.arrayBuffer())`,\n ` return {`,\n ` statusCode: response.status,`,\n ` headers,`,\n ` body: buf.toString('base64'),`,\n ` isBase64Encoded: true,`,\n ` }`,\n ` }`,\n ` return {`,\n ` statusCode: response.status,`,\n ` headers,`,\n ` body: await response.text(),`,\n ` isBase64Encoded: false,`,\n ` }`,\n `}`,\n ``,\n `// Every outcome — including both 404s — is produced as a Web Response by`,\n `// routeRequest, so the security baseline is applied at ONE place and the`,\n `// v2 result object is built from headers that already carry it.`,\n `export const handler = async (event) => {`,\n ` const path = event.requestContext?.http?.path ?? '/'`,\n ` // #409 — the same event, read as a Web Request so the CORS matcher can see the method and`,\n ` // the \\`origin\\` header. \\`eventV2ToRequest\\` reads a body already present in the event, so`,\n ` // unlike the Node targets there is no stream to drain twice.`,\n ` const corsRequest = eventV2ToRequest(event)`,\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 ` const response = preflight !== null`,\n ` ? withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ` : withCors(corsRequest, withSecurityHeaders(await routeRequest(event, path), SECURITY_HEADERS))`,\n ` return responseToV2Result(response, path)`,\n `}`,\n ``,\n `async function routeRequest(event, path) {`,\n ` if (!path.startsWith('/api/')${agentsHostBypass}) {`,\n ` return new Response(`,\n ` 'Static assets must be served from CloudFront or a separate static host.',`,\n ` { status: 404, headers: { 'content-type': 'text/plain' } },`,\n ` )`,\n ` }`,\n ``,\n ` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,\n ` if (!loaderCache) loaderCache = createProductionLoader()`,\n ``,\n // B-235 — hoisted above the agents branch, which names `request` like every other host's.\n // It was declared below `matchRoute`, and an agent path never reaches a route match. Building\n // it here costs nothing new: the outer handler already built one for the CORS matcher, and\n // `eventV2ToRequest` reads a body the event already carries, so there is no stream to drain\n // twice.\n ` const request = eventV2ToRequest(event)`,\n ``,\n ...agentsBranch,\n ``,\n ` const match = matchRoute(path, 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 ` return toResponse(executeRoute({ route: match.route, method, params: match.params, req, res, loadModule: loaderCache, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread} }))`,\n `}`,\n ]\n}\n\nexport function renderAwsLambdaEntry(opts: DeployedEntryOptions = {}): string {\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n // B-235. The entry already builds a Web `Request` — `eventV2ToRequest(event)`, for the CORS\n // matcher — so the shape this branch needs was here all along. `path` rather than `url.pathname`\n // because that is the name this host reads the route from.\n const agentsFragment = deployedAgentsFragment(scannedFromLoaderCache(agentsDirLiteral(opts)), {\n pathname: 'path',\n notFound: JSON_NOT_FOUND_RESPONSE,\n })\n return [\n `// Generated by Theo — AWS Lambda Adapter`,\n `// Use with API Gateway HTTP API v2 (default).`,\n ``,\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, ${serverDirLiteral(opts)})`,\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. Non-API paths 404 here and the document is served`,\n `// from CloudFront or another static host, so this covers the API and not the`,\n `// page (usetheokit/theokit#412).`,\n ...deployedEntryPreamble(runtimeConfig, agentsFragment, opts, 'aws-lambda'),\n ``,\n `function eventV2ToRequest(event) {`,\n ` const method = event.requestContext?.http?.method ?? 'GET'`,\n ` const path = event.requestContext?.http?.path ?? '/'`,\n ` const host = event.headers?.host ?? 'lambda'`,\n ` const qs = event.rawQueryString ? '?' + event.rawQueryString : ''`,\n ` const url = 'https://' + host + path + qs`,\n ` const headers = new Headers()`,\n ` for (const [k, v] of Object.entries(event.headers ?? {})) {`,\n ` if (v !== undefined) headers.set(k, String(v))`,\n ` }`,\n ` let body = event.body`,\n ` if (body && event.isBase64Encoded) {`,\n ` body = Buffer.from(body, 'base64')`,\n ` }`,\n ` return new Request(url, {`,\n ` method,`,\n ` headers,`,\n ` body: method === 'GET' || method === 'HEAD' ? undefined : body,`,\n ` })`,\n `}`,\n ``,\n ...awsLambdaHandlerFragment(\n runtimeConfig.executeRouteSpread,\n agentsFragment.branch,\n agentsFragment.hostBypass,\n ),\n ].join('\\n')\n}\n\nexport async function buildAwsLambda(\n config: TheoConfig,\n cwd: string,\n deps: AwsLambdaBuildDeps = {},\n ctx?: AdapterBuildContext,\n): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('aws-lambda', readManifest(cwd))\n\n // #382 — refuse by name rather than build something that cannot do what was\n // asked. `ssrStreaming` is the config's declaration that responses stream,\n // and this target is delisted for that (see `awsLambdaAdapter.streamsResponses`).\n if (config.ssrStreaming) {\n throw new Error(\n '[adapter-aws-lambda] ssrStreaming is on, but the aws-lambda target does not stream ' +\n 'responses: the Lambda v2 result object carries the body as a string, so nothing can ' +\n 'leave the function before the run ends. Response streaming would need ' +\n 'awslambda.streamifyResponse plus a Function URL in RESPONSE_STREAM invoke mode, which ' +\n 'this adapter does not emit. Build a streaming target instead (cloudflare, vercel, ' +\n 'netlify, bun, deno-deploy, node), or set ssrStreaming: false in theo.config.ts.',\n )\n }\n\n const runNodeBuild = deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter)\n await runNodeBuild(config, cwd, ctx)\n\n const outputDir = resolve(cwd, '.theokit/aws')\n const ensureDir = deps.ensureDir ?? ((p: string) => mkdirSync(p, { recursive: true }))\n ensureDir(outputDir)\n\n const entry = renderAwsLambdaEntry({\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 const write =\n deps.writeEntry ??\n ((p, c) => {\n writeFileSync(p, c)\n })\n write(resolve(outputDir, 'handler.mjs'), entry)\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ AWS Lambda output → .theokit/aws/handler.mjs')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'aws-lambda',\n securityHeaders: config.security?.headers,\n mintsNonce: false,\n documentHeaders: 'platform-unmanaged',\n })}\\n`,\n )\n}\n\nexport const awsLambdaAdapter: DeployAdapter = {\n name: 'aws-lambda',\n // #382 — delisted for streaming, deliberately. See DeployAdapter.\n streamsResponses: false,\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 comes from CloudFront or another static host and does not pass\n // through it (usetheokit/theokit#412).\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization'],\n build(config, cwd, ctx) {\n return buildAwsLambda(config, cwd, {}, ctx)\n },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -50,7 +50,7 @@ import "./chunk-OSBGZYXZ.js";
|
|
|
50
50
|
|
|
51
51
|
// src/cli/commands/build.ts
|
|
52
52
|
import { existsSync as existsSync4 } from "fs";
|
|
53
|
-
import { dirname as dirname2, relative, resolve, sep as sep2 } from "path";
|
|
53
|
+
import { dirname as dirname2, join, relative, resolve, sep as sep2 } from "path";
|
|
54
54
|
|
|
55
55
|
// src/adapters/types.ts
|
|
56
56
|
var VALID_TARGETS = [
|
|
@@ -554,7 +554,7 @@ async function buildCommand(options) {
|
|
|
554
554
|
`);
|
|
555
555
|
}
|
|
556
556
|
async function runAdapterBuild(target, config, cwd) {
|
|
557
|
-
const { theoPluginAsync } = await import("./vite-plugin-
|
|
557
|
+
const { theoPluginAsync } = await import("./vite-plugin-Z7AJG3M2.js");
|
|
558
558
|
const { default: react } = await import("@vitejs/plugin-react");
|
|
559
559
|
const ctx = {
|
|
560
560
|
// `react()` may return Plugin or Plugin[] depending on version; spread the
|
|
@@ -599,11 +599,16 @@ async function runAdapterBuild(target, config, cwd) {
|
|
|
599
599
|
filePath: toProjectRelative(agent.filePath),
|
|
600
600
|
agentPath: agent.agentPath,
|
|
601
601
|
name: agent.name
|
|
602
|
-
}))
|
|
602
|
+
})),
|
|
603
|
+
// B-185 — the identity module, decided here for the same reason the agents are: this
|
|
604
|
+
// provider is handed `serverDir`, and a Worker has no filesystem to look for it on. An app
|
|
605
|
+
// with no `server/context.ts` yields `undefined`, and the generator then emits no import —
|
|
606
|
+
// importing a file that is not there would fail the BUILD rather than one request.
|
|
607
|
+
contextModule: existsSync4(join(abs, "context.ts")) ? toProjectRelative(join(abs, "context.ts")) : void 0
|
|
603
608
|
};
|
|
604
609
|
}
|
|
605
610
|
};
|
|
606
|
-
const { resolveAdapter } = await import("./registry-
|
|
611
|
+
const { resolveAdapter } = await import("./registry-DDBXDHJ2.js");
|
|
607
612
|
const adapter = await resolveAdapter(target);
|
|
608
613
|
const { warnUnappliedConfig, assertRateLimitEnforceable } = await import("./config-support-O4REYSK5.js");
|
|
609
614
|
assertRateLimitEnforceable(config, adapter, target);
|
|
@@ -676,4 +681,4 @@ function relativize3(absPath, root) {
|
|
|
676
681
|
export {
|
|
677
682
|
buildCommand
|
|
678
683
|
};
|
|
679
|
-
//# sourceMappingURL=build-
|
|
684
|
+
//# sourceMappingURL=build-CGFKWZ73.js.map
|