theokit 0.68.0 → 0.70.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-ICWX5PZ2.js} +8 -8
- package/dist/{actions-virtual-module-3OPYLD76.js → actions-virtual-module-LY6VGJZ2.js} +5 -5
- package/dist/adapters/agent-mount.d.ts +191 -3
- package/dist/adapters/agent-mount.js +19 -4
- 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-7DQ3TKJY.js} +4 -4
- package/dist/agent-scan-BLXaFL6R.d.ts +12 -0
- package/dist/{app-typed-client-BE3PV3JY.js → app-typed-client-2S76VTMB.js} +5 -5
- package/dist/{app-typed-client-RAFEBA7S.js → app-typed-client-6YQREFRS.js} +8 -8
- 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-NIHGHPYS.js} +12 -7
- package/dist/build-NIHGHPYS.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-3NAKOWTX.js +573 -0
- package/dist/chunk-3NAKOWTX.js.map +1 -0
- package/dist/chunk-4D4YVXHR.js +816 -0
- package/dist/chunk-4D4YVXHR.js.map +1 -0
- package/dist/{chunk-G2NWAVGG.js → chunk-5XXXJ6DT.js} +65 -6
- package/dist/chunk-5XXXJ6DT.js.map +1 -0
- package/dist/{chunk-CO7Q75IS.js → chunk-6SK4MX2N.js} +10 -10
- 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-GP6OJBXP.js → chunk-CPXIYCAY.js} +2 -2
- package/dist/chunk-FFGP2LGQ.js +465 -0
- package/dist/chunk-FFGP2LGQ.js.map +1 -0
- package/dist/{chunk-KDP2HURW.js → chunk-FHQP23Z5.js} +10 -2
- package/dist/{chunk-KDP2HURW.js.map → chunk-FHQP23Z5.js.map} +1 -1
- package/dist/{chunk-BCFA6LHL.js → chunk-GVJFVBCJ.js} +2 -2
- package/dist/{chunk-LADTWXOB.js → chunk-H5KSRGRS.js} +43 -554
- package/dist/chunk-H5KSRGRS.js.map +1 -0
- package/dist/{chunk-ENRT6DAU.js → chunk-IDWN2OSG.js} +15 -2
- package/dist/chunk-IDWN2OSG.js.map +1 -0
- package/dist/{chunk-GDF2XQOO.js → chunk-JMN4COMK.js} +5 -3
- package/dist/chunk-JMN4COMK.js.map +1 -0
- package/dist/{chunk-Q7T3UQ4L.js → chunk-KOG5K26V.js} +16 -738
- package/dist/chunk-KOG5K26V.js.map +1 -0
- package/dist/{chunk-FYYKMPST.js → chunk-MLF25NC4.js} +4 -4
- package/dist/{chunk-7THO4PRL.js → chunk-PGDBSK2L.js} +33 -11
- package/dist/chunk-PGDBSK2L.js.map +1 -0
- package/dist/{chunk-5NNFO7R7.js → chunk-R7G2B2WH.js} +10 -2
- package/dist/chunk-R7G2B2WH.js.map +1 -0
- package/dist/{chunk-GAJOZJWD.js → chunk-SX7ZAHNE.js} +15 -2
- package/dist/chunk-SX7ZAHNE.js.map +1 -0
- 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/{chunk-QGNSZ2ZK.js → chunk-YWWMYEAC.js} +3 -3
- package/dist/cli/index.js +7 -7
- 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-KKO3JIN7.js} +7 -7
- package/dist/{dev-emit-ZLB2J5ME.js → dev-emit-23AA3V64.js} +3 -3
- package/dist/{dev-emit-7RT624PM.js → dev-emit-UJJXY3ET.js} +3 -3
- package/dist/{index-B9iVBHJI.d.ts → index-inRdhi59.d.ts} +39 -4
- package/dist/index.js +9 -8
- package/dist/index.js.map +1 -1
- package/dist/{internal-api-OOTVIOH2.js → internal-api-HUIBRF2X.js} +5 -5
- package/dist/{internal-api-VAKXXW6F.js → internal-api-S72T2XKD.js} +10 -9
- package/dist/match-DaKsL73w.d.ts +28 -0
- package/dist/{mcp-7UOQM4FW.js → mcp-I6MCW6KX.js} +4 -4
- 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/{openapi-SKKXWFX4.js → openapi-24PTE7P6.js} +3 -3
- package/dist/{preview-GPMF43QX.js → preview-EOL3LMK7.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 +13 -8
- package/dist/server/index.d.ts +6 -5
- package/dist/server/index.js +17 -12
- package/dist/server/index.js.map +1 -1
- package/dist/server/scan/index.d.ts +4 -3
- package/dist/server/scan/index.js +2 -2
- package/dist/{server-boundary-A3HW27C7.js → server-boundary-ERBSHRHT.js} +5 -5
- package/dist/{server-boundary-V6PCM22J.js → server-boundary-I5XWYINJ.js} +8 -8
- package/dist/{start-6WEPXA3X.js → start-OD4DG4C6.js} +6 -6
- package/dist/{vercel-YUZADKGV.js → vercel-LZTDSDJF.js} +42 -28
- package/dist/vercel-LZTDSDJF.js.map +1 -0
- package/dist/vite-plugin/index.js +9 -8
- package/dist/{vite-plugin-WBF5NXGW.js → vite-plugin-SH3VGQEE.js} +7 -7
- package/package.json +4 -4
- package/dist/agent-scan-BZa-pagG.d.ts +0 -16
- 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-5NNFO7R7.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-7THO4PRL.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-ICWX5PZ2.js.map} +0 -0
- /package/dist/{actions-virtual-module-3OPYLD76.js.map → actions-virtual-module-LY6VGJZ2.js.map} +0 -0
- /package/dist/{agent-UBDDP2L5.js.map → agent-7DQ3TKJY.js.map} +0 -0
- /package/dist/{app-typed-client-BE3PV3JY.js.map → app-typed-client-2S76VTMB.js.map} +0 -0
- /package/dist/{app-typed-client-RAFEBA7S.js.map → app-typed-client-6YQREFRS.js.map} +0 -0
- /package/dist/{chunk-CO7Q75IS.js.map → chunk-6SK4MX2N.js.map} +0 -0
- /package/dist/{chunk-AROOYXI5.js.map → chunk-BTDTHXUI.js.map} +0 -0
- /package/dist/{chunk-GP6OJBXP.js.map → chunk-CPXIYCAY.js.map} +0 -0
- /package/dist/{chunk-BCFA6LHL.js.map → chunk-GVJFVBCJ.js.map} +0 -0
- /package/dist/{chunk-FYYKMPST.js.map → chunk-MLF25NC4.js.map} +0 -0
- /package/dist/{chunk-QGNSZ2ZK.js.map → chunk-YWWMYEAC.js.map} +0 -0
- /package/dist/{dev-E3USPAWQ.js.map → dev-KKO3JIN7.js.map} +0 -0
- /package/dist/{dev-emit-ZLB2J5ME.js.map → dev-emit-23AA3V64.js.map} +0 -0
- /package/dist/{dev-emit-7RT624PM.js.map → dev-emit-UJJXY3ET.js.map} +0 -0
- /package/dist/{internal-api-OOTVIOH2.js.map → internal-api-HUIBRF2X.js.map} +0 -0
- /package/dist/{internal-api-VAKXXW6F.js.map → internal-api-S72T2XKD.js.map} +0 -0
- /package/dist/{mcp-7UOQM4FW.js.map → mcp-I6MCW6KX.js.map} +0 -0
- /package/dist/{openapi-SKKXWFX4.js.map → openapi-24PTE7P6.js.map} +0 -0
- /package/dist/{preview-GPMF43QX.js.map → preview-EOL3LMK7.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-ERBSHRHT.js.map} +0 -0
- /package/dist/{server-boundary-V6PCM22J.js.map → server-boundary-I5XWYINJ.js.map} +0 -0
- /package/dist/{start-6WEPXA3X.js.map → start-OD4DG4C6.js.map} +0 -0
- /package/dist/{vite-plugin-WBF5NXGW.js.map → vite-plugin-SH3VGQEE.js.map} +0 -0
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
incomingMessageToHandlerRequest,
|
|
3
|
+
isZodLike,
|
|
4
|
+
parseQueryAndBody,
|
|
5
|
+
runMiddlewareAndContext,
|
|
6
|
+
runZodValidation,
|
|
7
|
+
sendError,
|
|
8
|
+
sendJson
|
|
9
|
+
} from "./chunk-4D4YVXHR.js";
|
|
10
|
+
import {
|
|
11
|
+
enforceCsrf
|
|
4
12
|
} from "./chunk-P6OS7652.js";
|
|
5
13
|
import {
|
|
6
14
|
ActionError,
|
|
7
15
|
ActionInputError
|
|
8
16
|
} from "./chunk-ZDUO4IYN.js";
|
|
9
|
-
import {
|
|
10
|
-
WEB_SHAPED_MIDDLEWARE
|
|
11
|
-
} from "./chunk-7L7LQ2GU.js";
|
|
12
17
|
import {
|
|
13
18
|
evaluateRoutePolicy,
|
|
14
19
|
subjectFromContext
|
|
15
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-IDWN2OSG.js";
|
|
16
21
|
import {
|
|
17
22
|
DuplicateContextKeyError,
|
|
18
23
|
createOutbox,
|
|
@@ -20,13 +25,9 @@ import {
|
|
|
20
25
|
createQueueClient
|
|
21
26
|
} from "./chunk-47FFT43U.js";
|
|
22
27
|
import {
|
|
23
|
-
RequestBodyConsumedError,
|
|
24
28
|
parseRequestBody,
|
|
25
29
|
warnOnce
|
|
26
30
|
} from "./chunk-ZDCCILMP.js";
|
|
27
|
-
import {
|
|
28
|
-
scanMiddlewares
|
|
29
|
-
} from "./chunk-V6Y2SMRG.js";
|
|
30
31
|
import {
|
|
31
32
|
envelopeCodeToStatus
|
|
32
33
|
} from "./chunk-ACKBVBUI.js";
|
|
@@ -35,718 +36,6 @@ import {
|
|
|
35
36
|
serverErrorToEnvelope
|
|
36
37
|
} from "./chunk-IZ3TIL6K.js";
|
|
37
38
|
|
|
38
|
-
// src/core/contracts/client-safe-error.ts
|
|
39
|
-
var INTERNAL_CODES = /* @__PURE__ */ new Set(["INTERNAL_ERROR", "INTERNAL_SERVER_ERROR"]);
|
|
40
|
-
var GENERIC_INTERNAL_MESSAGE = "Internal server error";
|
|
41
|
-
function redacts(code) {
|
|
42
|
-
return INTERNAL_CODES.has(code) && process.env.NODE_ENV === "production";
|
|
43
|
-
}
|
|
44
|
-
function clientSafeErrorMessage(code, message) {
|
|
45
|
-
return redacts(code) ? GENERIC_INTERNAL_MESSAGE : message;
|
|
46
|
-
}
|
|
47
|
-
function clientSafeErrorEnvelope(envelope) {
|
|
48
|
-
if (!redacts(envelope.code)) return envelope;
|
|
49
|
-
return { code: envelope.code, message: GENERIC_INTERNAL_MESSAGE };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// src/server/http/send-response.ts
|
|
53
|
-
function sendJson(res, data, status = 200, transformer) {
|
|
54
|
-
const body = transformer ? transformer.serialize(data) : JSON.stringify(data);
|
|
55
|
-
res.writeHead(status, {
|
|
56
|
-
"Content-Type": "application/json",
|
|
57
|
-
"Content-Length": Buffer.byteLength(body)
|
|
58
|
-
});
|
|
59
|
-
res.end(body);
|
|
60
|
-
}
|
|
61
|
-
function oneLine(value) {
|
|
62
|
-
return value.replace(/[\r\n]/g, "\\n");
|
|
63
|
-
}
|
|
64
|
-
function sendError(res, codeOrInput, message, status, issues, requestId, options) {
|
|
65
|
-
let code;
|
|
66
|
-
if (typeof codeOrInput === "string") {
|
|
67
|
-
code = codeOrInput;
|
|
68
|
-
message = message ?? "";
|
|
69
|
-
status = status ?? 500;
|
|
70
|
-
} else {
|
|
71
|
-
code = codeOrInput.code;
|
|
72
|
-
message = codeOrInput.message;
|
|
73
|
-
status = codeOrInput.status;
|
|
74
|
-
issues = codeOrInput.issues;
|
|
75
|
-
requestId = codeOrInput.requestId;
|
|
76
|
-
options = codeOrInput.options;
|
|
77
|
-
}
|
|
78
|
-
const errorMessage = clientSafeErrorMessage(code, message);
|
|
79
|
-
if (code === "INTERNAL_ERROR") {
|
|
80
|
-
console.error(`[${oneLine(requestId ?? "no-id")}] ${oneLine(message)}`);
|
|
81
|
-
}
|
|
82
|
-
if (status === 404 && options?.custom404Html) {
|
|
83
|
-
const body = options.custom404Html;
|
|
84
|
-
res.writeHead(404, {
|
|
85
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
86
|
-
"Content-Length": Buffer.byteLength(body)
|
|
87
|
-
});
|
|
88
|
-
res.end(body);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
if (status === 500 && options?.custom500Html) {
|
|
92
|
-
const body = options.custom500Html;
|
|
93
|
-
res.writeHead(500, {
|
|
94
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
95
|
-
"Content-Length": Buffer.byteLength(body)
|
|
96
|
-
});
|
|
97
|
-
res.end(body);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
sendJson(
|
|
101
|
-
res,
|
|
102
|
-
{
|
|
103
|
-
error: {
|
|
104
|
-
code,
|
|
105
|
-
message: errorMessage,
|
|
106
|
-
...requestId ? { requestId } : {},
|
|
107
|
-
...issues ? { issues } : {}
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
status
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// src/server/http/node-request.ts
|
|
115
|
-
import { Readable } from "node:stream";
|
|
116
|
-
function pickHeaderString(value) {
|
|
117
|
-
if (typeof value === "string") return value;
|
|
118
|
-
if (Array.isArray(value)) {
|
|
119
|
-
for (const v of value) if (typeof v === "string" && v.length > 0) return v;
|
|
120
|
-
}
|
|
121
|
-
return void 0;
|
|
122
|
-
}
|
|
123
|
-
function synthesizeAbsoluteUrl(req) {
|
|
124
|
-
const host = pickHeaderString(req.headers.host) ?? "localhost";
|
|
125
|
-
return `http://${host}${req.url ?? "/"}`;
|
|
126
|
-
}
|
|
127
|
-
function nodeHeadersToWeb(req) {
|
|
128
|
-
const headers = new Headers();
|
|
129
|
-
for (const [key, value] of Object.entries(req.headers)) {
|
|
130
|
-
if (value === void 0) continue;
|
|
131
|
-
if (Array.isArray(value)) {
|
|
132
|
-
headers.set(key, value.join(", "));
|
|
133
|
-
} else {
|
|
134
|
-
headers.set(key, value);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return headers;
|
|
138
|
-
}
|
|
139
|
-
function incomingMessageToWebRequest(req) {
|
|
140
|
-
const url = synthesizeAbsoluteUrl(req);
|
|
141
|
-
const headers = nodeHeadersToWeb(req);
|
|
142
|
-
const method = (req.method ?? "GET").toUpperCase();
|
|
143
|
-
const hasBody = method !== "GET" && method !== "HEAD";
|
|
144
|
-
if (!hasBody) {
|
|
145
|
-
return new Request(url, { method, headers });
|
|
146
|
-
}
|
|
147
|
-
const webStream = Readable.toWeb(req);
|
|
148
|
-
return new Request(url, {
|
|
149
|
-
method,
|
|
150
|
-
headers,
|
|
151
|
-
body: webStream,
|
|
152
|
-
// EC-2: Node 18+ requires `duplex: 'half'` when body is a stream.
|
|
153
|
-
// The `RequestInit` type omits it (Web spec gap); cast accordingly.
|
|
154
|
-
...{ duplex: "half" }
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
function createWebRequestSource(req) {
|
|
158
|
-
let converted;
|
|
159
|
-
return {
|
|
160
|
-
method: (req.method ?? "GET").toUpperCase(),
|
|
161
|
-
toRequest: () => converted ??= incomingMessageToWebRequest(req)
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function incomingMessageToHandlerRequest(req) {
|
|
165
|
-
return new Request(synthesizeAbsoluteUrl(req), {
|
|
166
|
-
method: (req.method ?? "GET").toUpperCase(),
|
|
167
|
-
headers: nodeHeadersToWeb(req)
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// src/server/http/validate-route-input.ts
|
|
172
|
-
function validateRouteInput(config, raw) {
|
|
173
|
-
let query = raw.query;
|
|
174
|
-
if (config.query !== void 0) {
|
|
175
|
-
const parsed = config.query.safeParse(raw.query);
|
|
176
|
-
if (!parsed.success) return { ok: false, channel: "query", error: parsed.error };
|
|
177
|
-
query = parsed.data;
|
|
178
|
-
}
|
|
179
|
-
let body = raw.body;
|
|
180
|
-
if (config.body !== void 0) {
|
|
181
|
-
const parsed = config.body.safeParse(raw.body);
|
|
182
|
-
if (!parsed.success) return { ok: false, channel: "body", error: parsed.error };
|
|
183
|
-
body = parsed.data;
|
|
184
|
-
}
|
|
185
|
-
let params = raw.params;
|
|
186
|
-
if (config.params !== void 0) {
|
|
187
|
-
const parsed = config.params.safeParse(raw.params);
|
|
188
|
-
if (!parsed.success) return { ok: false, channel: "params", error: parsed.error };
|
|
189
|
-
params = parsed.data;
|
|
190
|
-
}
|
|
191
|
-
return { ok: true, query, body, params };
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// src/server/http/execute-stages.ts
|
|
195
|
-
async function parseQueryAndBody(req, res, requestId) {
|
|
196
|
-
const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
|
|
197
|
-
const query = Object.fromEntries(url.searchParams);
|
|
198
|
-
let body;
|
|
199
|
-
let raw;
|
|
200
|
-
try {
|
|
201
|
-
const parsed = await parseRequestBody(req);
|
|
202
|
-
raw = parsed.raw;
|
|
203
|
-
if (parsed.json !== void 0) {
|
|
204
|
-
body = parsed.json;
|
|
205
|
-
} else if (parsed.files.length > 0 || Object.keys(parsed.fields).length > 0) {
|
|
206
|
-
body = { ...parsed.fields, _files: parsed.files };
|
|
207
|
-
} else {
|
|
208
|
-
body = void 0;
|
|
209
|
-
}
|
|
210
|
-
} catch (err) {
|
|
211
|
-
if (err instanceof RequestBodyConsumedError) {
|
|
212
|
-
sendError(res, "INTERNAL_ERROR", err.message, err.status, void 0, requestId);
|
|
213
|
-
return { ok: false };
|
|
214
|
-
}
|
|
215
|
-
const message = err.message;
|
|
216
|
-
const status = message.includes("Unsupported Content-Type") ? 415 : 400;
|
|
217
|
-
sendError(res, "VALIDATION_ERROR", message, status, void 0, requestId);
|
|
218
|
-
return { ok: false };
|
|
219
|
-
}
|
|
220
|
-
return { ok: true, data: { query, body, raw } };
|
|
221
|
-
}
|
|
222
|
-
var isZodLike = (value) => typeof value === "object" && value !== null && typeof value.safeParse === "function";
|
|
223
|
-
function runZodValidation(routeConfig, res, requestId, input) {
|
|
224
|
-
const { query, params } = input;
|
|
225
|
-
let { body } = input;
|
|
226
|
-
if (isZodLike(routeConfig.query)) {
|
|
227
|
-
const result = routeConfig.query.safeParse(query);
|
|
228
|
-
if (!result.success) {
|
|
229
|
-
sendError(
|
|
230
|
-
res,
|
|
231
|
-
"VALIDATION_ERROR",
|
|
232
|
-
"Invalid query parameters",
|
|
233
|
-
400,
|
|
234
|
-
result.error?.issues,
|
|
235
|
-
requestId
|
|
236
|
-
);
|
|
237
|
-
return { ok: false };
|
|
238
|
-
}
|
|
239
|
-
Object.assign(query, result.data);
|
|
240
|
-
}
|
|
241
|
-
if (isZodLike(routeConfig.body)) {
|
|
242
|
-
const result = routeConfig.body.safeParse(body);
|
|
243
|
-
if (!result.success) {
|
|
244
|
-
sendError(
|
|
245
|
-
res,
|
|
246
|
-
"VALIDATION_ERROR",
|
|
247
|
-
"Invalid request body",
|
|
248
|
-
400,
|
|
249
|
-
result.error?.issues,
|
|
250
|
-
requestId
|
|
251
|
-
);
|
|
252
|
-
return { ok: false };
|
|
253
|
-
}
|
|
254
|
-
body = result.data;
|
|
255
|
-
}
|
|
256
|
-
if (isZodLike(routeConfig.params)) {
|
|
257
|
-
const result = routeConfig.params.safeParse(params);
|
|
258
|
-
if (!result.success) {
|
|
259
|
-
sendError(
|
|
260
|
-
res,
|
|
261
|
-
"VALIDATION_ERROR",
|
|
262
|
-
"Invalid route parameters",
|
|
263
|
-
400,
|
|
264
|
-
result.error?.issues,
|
|
265
|
-
requestId
|
|
266
|
-
);
|
|
267
|
-
return { ok: false };
|
|
268
|
-
}
|
|
269
|
-
Object.assign(params, result.data);
|
|
270
|
-
}
|
|
271
|
-
return { ok: true, data: { query, body, params } };
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// src/server/http/web-middleware-runner.ts
|
|
275
|
-
async function runWebMiddleware(request, middleware, context, downstream) {
|
|
276
|
-
const runFrom = async (index) => {
|
|
277
|
-
if (index >= middleware.length) {
|
|
278
|
-
return downstream === void 0 ? void 0 : await downstream(request, context);
|
|
279
|
-
}
|
|
280
|
-
const invocations = [];
|
|
281
|
-
const rejections = /* @__PURE__ */ new Map();
|
|
282
|
-
let frameSettled = false;
|
|
283
|
-
let yieldedInvocation;
|
|
284
|
-
const next = () => {
|
|
285
|
-
const started = runFrom(index + 1);
|
|
286
|
-
invocations.push(started);
|
|
287
|
-
started.catch((reason) => {
|
|
288
|
-
if (frameSettled) {
|
|
289
|
-
reportOne(started, reason);
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
rejections.set(started, reason);
|
|
293
|
-
});
|
|
294
|
-
return started;
|
|
295
|
-
};
|
|
296
|
-
const reportOne = (invocation, reason) => {
|
|
297
|
-
if (invocation === yieldedInvocation) return;
|
|
298
|
-
const detail = reason instanceof Error ? reason.stack ?? reason.message : String(reason);
|
|
299
|
-
console.warn(
|
|
300
|
-
`[theokit] a middleware invoked next() and the downstream rejected, but the frame did not yield that result, so this failure reached no client: ${detail}`
|
|
301
|
-
);
|
|
302
|
-
};
|
|
303
|
-
const report = (yielded) => {
|
|
304
|
-
yieldedInvocation = yielded;
|
|
305
|
-
frameSettled = true;
|
|
306
|
-
for (const [invocation, reason] of rejections) reportOne(invocation, reason);
|
|
307
|
-
};
|
|
308
|
-
let own;
|
|
309
|
-
try {
|
|
310
|
-
own = await middleware[index](request, context, next);
|
|
311
|
-
} catch (error) {
|
|
312
|
-
let held;
|
|
313
|
-
for (const [invocation, reason] of rejections) {
|
|
314
|
-
if (reason === error) held = invocation;
|
|
315
|
-
}
|
|
316
|
-
report(held);
|
|
317
|
-
throw error;
|
|
318
|
-
}
|
|
319
|
-
if (own instanceof Response) {
|
|
320
|
-
report();
|
|
321
|
-
return own;
|
|
322
|
-
}
|
|
323
|
-
if (invocations.length > 0) {
|
|
324
|
-
const yielded = invocations[invocations.length - 1];
|
|
325
|
-
try {
|
|
326
|
-
return await yielded;
|
|
327
|
-
} finally {
|
|
328
|
-
report(yielded);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
report();
|
|
332
|
-
return await runFrom(index + 1);
|
|
333
|
-
};
|
|
334
|
-
return runFrom(0);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// src/server/web-handler.ts
|
|
338
|
-
function searchParamsToObject(params) {
|
|
339
|
-
const out = {};
|
|
340
|
-
for (const [key, value] of params.entries()) {
|
|
341
|
-
if (!Object.hasOwn(out, key)) {
|
|
342
|
-
out[key] = value;
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
const existing = out[key];
|
|
346
|
-
if (Array.isArray(existing)) {
|
|
347
|
-
existing.push(value);
|
|
348
|
-
} else {
|
|
349
|
-
out[key] = [existing, value];
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
return out;
|
|
353
|
-
}
|
|
354
|
-
async function parseBodyInline(request) {
|
|
355
|
-
if (request.method === "GET" || request.method === "HEAD") return void 0;
|
|
356
|
-
const contentType = request.headers.get("content-type") ?? "";
|
|
357
|
-
if (contentType.includes("application/json")) {
|
|
358
|
-
const text = await request.text();
|
|
359
|
-
if (text.length === 0) return void 0;
|
|
360
|
-
try {
|
|
361
|
-
return JSON.parse(text);
|
|
362
|
-
} catch {
|
|
363
|
-
return void 0;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
if (contentType.startsWith("text/")) {
|
|
367
|
-
const text = await request.text();
|
|
368
|
-
return text.length === 0 ? void 0 : text;
|
|
369
|
-
}
|
|
370
|
-
return void 0;
|
|
371
|
-
}
|
|
372
|
-
async function parseBodyFull(request) {
|
|
373
|
-
if (request.method === "GET" || request.method === "HEAD") return void 0;
|
|
374
|
-
const { parseWebRequestBody } = await import("./body-parser-web-ON5CUTEL.js");
|
|
375
|
-
try {
|
|
376
|
-
const parsed = await parseWebRequestBody(request);
|
|
377
|
-
if (parsed.json === void 0 && Object.keys(parsed.fields).length === 0 && parsed.files.length === 0) {
|
|
378
|
-
return void 0;
|
|
379
|
-
}
|
|
380
|
-
return parsed;
|
|
381
|
-
} catch {
|
|
382
|
-
return void 0;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
function validationErrorResponse(zodError, field) {
|
|
386
|
-
const envelope = {
|
|
387
|
-
code: "BAD_REQUEST",
|
|
388
|
-
message: `Validation failed: ${field}`,
|
|
389
|
-
ext: {
|
|
390
|
-
fields: zodError.issues.map((issue) => ({
|
|
391
|
-
path: issue.path.join("."),
|
|
392
|
-
message: issue.message
|
|
393
|
-
}))
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
return new Response(JSON.stringify(envelope), {
|
|
397
|
-
status: 400,
|
|
398
|
-
headers: { "content-type": "application/json" }
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
async function runHandler(config, request, bodyParser = "inline", paramsInput = {}, context = {}) {
|
|
402
|
-
const url = new URL(request.url);
|
|
403
|
-
const queryRaw = searchParamsToObject(url.searchParams);
|
|
404
|
-
const bodyRaw = bodyParser === "full" ? await parseBodyFull(request) : await parseBodyInline(request);
|
|
405
|
-
const paramsRaw = paramsInput;
|
|
406
|
-
const validated = validateRouteInput(config, {
|
|
407
|
-
query: queryRaw,
|
|
408
|
-
body: bodyRaw,
|
|
409
|
-
params: paramsRaw
|
|
410
|
-
});
|
|
411
|
-
if (!validated.ok) {
|
|
412
|
-
return { ok: false, response: validationErrorResponse(validated.error, validated.channel) };
|
|
413
|
-
}
|
|
414
|
-
const { query, body, params } = validated;
|
|
415
|
-
const decision = await evaluateRoutePolicy(config.policy, {
|
|
416
|
-
subject: subjectFromContext(context),
|
|
417
|
-
query,
|
|
418
|
-
body,
|
|
419
|
-
params
|
|
420
|
-
});
|
|
421
|
-
if (!decision.allowed) {
|
|
422
|
-
return { ok: false, response: accessDeniedResponse(decision.reason) };
|
|
423
|
-
}
|
|
424
|
-
const result = await config.handler({ query, body, params, request, context });
|
|
425
|
-
return validateResponseOutput(config.response, result) ?? { ok: true, result };
|
|
426
|
-
}
|
|
427
|
-
function validateResponseOutput(response, result) {
|
|
428
|
-
const validatable = result !== void 0 && result !== null && !(result instanceof Response);
|
|
429
|
-
if (!validatable || !isZodLike(response)) return void 0;
|
|
430
|
-
const parsed = response.safeParse(result);
|
|
431
|
-
if (parsed.success) return { ok: true, result: parsed.data };
|
|
432
|
-
const err = new TheoError({
|
|
433
|
-
code: "INTERNAL_SERVER_ERROR",
|
|
434
|
-
message: "response validation failed",
|
|
435
|
-
ext: { issues: parsed.error?.issues }
|
|
436
|
-
});
|
|
437
|
-
return { ok: false, response: handlerErrorResponse(err) };
|
|
438
|
-
}
|
|
439
|
-
function toResponse(result, status) {
|
|
440
|
-
if (result === void 0) {
|
|
441
|
-
return new Response(null, { status: 204 });
|
|
442
|
-
}
|
|
443
|
-
if (result instanceof Response) {
|
|
444
|
-
return result;
|
|
445
|
-
}
|
|
446
|
-
return new Response(JSON.stringify(result), {
|
|
447
|
-
status: status ?? 200,
|
|
448
|
-
headers: { "content-type": "application/json" }
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
function handlerErrorResponse(err) {
|
|
452
|
-
const envelope = clientSafeErrorEnvelope(serverErrorToEnvelope(err));
|
|
453
|
-
const status = envelopeCodeToStatus(envelope.code);
|
|
454
|
-
return new Response(JSON.stringify(envelope), {
|
|
455
|
-
status,
|
|
456
|
-
headers: { "content-type": "application/json" }
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
var CSRF_PROTECTED_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
460
|
-
function mergeHookHeaders(response, hookHeaders) {
|
|
461
|
-
if ([...hookHeaders].length === 0) return response;
|
|
462
|
-
const merged = new Headers(response.headers);
|
|
463
|
-
for (const [k, v] of hookHeaders.entries()) {
|
|
464
|
-
if (k.toLowerCase() === "set-cookie") continue;
|
|
465
|
-
if (!merged.has(k)) merged.set(k, v);
|
|
466
|
-
}
|
|
467
|
-
for (const sc of hookHeaders.getSetCookie()) {
|
|
468
|
-
merged.append("Set-Cookie", sc);
|
|
469
|
-
}
|
|
470
|
-
return new Response(response.body, {
|
|
471
|
-
status: response.status,
|
|
472
|
-
statusText: response.statusText,
|
|
473
|
-
headers: merged
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
function methodNotAllowedResponse(method) {
|
|
477
|
-
const envelope = {
|
|
478
|
-
code: "METHOD_NOT_ALLOWED",
|
|
479
|
-
message: `Method ${method} not allowed`
|
|
480
|
-
};
|
|
481
|
-
return new Response(JSON.stringify(envelope), {
|
|
482
|
-
status: 405,
|
|
483
|
-
headers: { "content-type": "application/json" }
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
function shouldEnforceCsrf(method, config, csrfMode) {
|
|
487
|
-
if ((csrfMode ?? "strict") === "off") return false;
|
|
488
|
-
if (!CSRF_PROTECTED_METHODS.has(method)) return false;
|
|
489
|
-
return config?.csrf !== false;
|
|
490
|
-
}
|
|
491
|
-
function accessDeniedResponse(reason) {
|
|
492
|
-
const envelope = {
|
|
493
|
-
code: "FORBIDDEN",
|
|
494
|
-
message: `Access denied: ${reason}`
|
|
495
|
-
};
|
|
496
|
-
return new Response(JSON.stringify({ error: envelope }), {
|
|
497
|
-
status: 403,
|
|
498
|
-
headers: { "Content-Type": "application/json" }
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
function csrfFailedResponse(reason) {
|
|
502
|
-
const envelope = {
|
|
503
|
-
code: "FORBIDDEN",
|
|
504
|
-
message: `CSRF check failed: ${reason}`
|
|
505
|
-
};
|
|
506
|
-
return new Response(JSON.stringify(envelope), {
|
|
507
|
-
status: 403,
|
|
508
|
-
headers: { "content-type": "application/json" }
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
async function executeWebRequest(request, routeModule, opts = {}) {
|
|
512
|
-
const method = request.method.toUpperCase();
|
|
513
|
-
const config = routeModule[method];
|
|
514
|
-
if (opts.hooks === void 0) {
|
|
515
|
-
if (config === void 0 || typeof config.handler !== "function") {
|
|
516
|
-
return methodNotAllowedResponse(method);
|
|
517
|
-
}
|
|
518
|
-
if (shouldEnforceCsrf(method, config, opts.csrfMode)) {
|
|
519
|
-
const csrfCheck = validateCsrfRequest(request);
|
|
520
|
-
if (!csrfCheck.valid) return csrfFailedResponse(csrfCheck.reason);
|
|
521
|
-
}
|
|
522
|
-
try {
|
|
523
|
-
const context = {};
|
|
524
|
-
const runRoute = async () => {
|
|
525
|
-
const outcome = await runHandler(
|
|
526
|
-
config,
|
|
527
|
-
request,
|
|
528
|
-
opts.bodyParser ?? "inline",
|
|
529
|
-
opts.params ?? {},
|
|
530
|
-
context
|
|
531
|
-
);
|
|
532
|
-
return outcome.ok ? toResponse(outcome.result, config.status) : outcome.response;
|
|
533
|
-
};
|
|
534
|
-
if (opts.middleware?.length) {
|
|
535
|
-
const response = await runWebMiddleware(request, opts.middleware, context, runRoute);
|
|
536
|
-
if (response !== void 0) return response;
|
|
537
|
-
}
|
|
538
|
-
return await runRoute();
|
|
539
|
-
} catch (err) {
|
|
540
|
-
return handlerErrorResponse(err);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
return runWithHooks(request, config, opts, opts.hooks);
|
|
544
|
-
}
|
|
545
|
-
async function runPreHandlerPipeline(hookCtx, request, config, opts, hooks) {
|
|
546
|
-
const method = request.method.toUpperCase();
|
|
547
|
-
const runList = async (list) => {
|
|
548
|
-
for (const hook of list) {
|
|
549
|
-
if (hookCtx.response !== void 0) return;
|
|
550
|
-
await hook(hookCtx);
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
if (hooks.onRequest) await runList(hooks.onRequest);
|
|
554
|
-
if (hookCtx.response === void 0 && shouldEnforceCsrf(method, config, opts.csrfMode)) {
|
|
555
|
-
const csrfCheck = validateCsrfRequest(request);
|
|
556
|
-
if (!csrfCheck.valid) hookCtx.response = csrfFailedResponse(csrfCheck.reason);
|
|
557
|
-
}
|
|
558
|
-
if (hookCtx.response === void 0 && hooks.preHandler) {
|
|
559
|
-
await runList(hooks.preHandler);
|
|
560
|
-
}
|
|
561
|
-
if (hookCtx.response === void 0) {
|
|
562
|
-
await runHandlerStage(hookCtx, request, config, opts, method);
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
async function runHandlerStage(hookCtx, request, config, opts, method) {
|
|
566
|
-
if (config === void 0 || typeof config.handler !== "function") {
|
|
567
|
-
hookCtx.response = methodNotAllowedResponse(method);
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
const runRoute = async () => {
|
|
571
|
-
const outcome = await runHandler(
|
|
572
|
-
config,
|
|
573
|
-
request,
|
|
574
|
-
opts.bodyParser ?? "inline",
|
|
575
|
-
opts.params ?? {},
|
|
576
|
-
hookCtx.ctx
|
|
577
|
-
);
|
|
578
|
-
return outcome.ok ? toResponse(outcome.result, config.status) : outcome.response;
|
|
579
|
-
};
|
|
580
|
-
if (opts.middleware?.length) {
|
|
581
|
-
const response = await runWebMiddleware(request, opts.middleware, hookCtx.ctx, runRoute);
|
|
582
|
-
if (response !== void 0) {
|
|
583
|
-
hookCtx.response = response;
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
hookCtx.response = await runRoute();
|
|
588
|
-
}
|
|
589
|
-
async function runWithHooks(request, config, opts, hooks) {
|
|
590
|
-
const hookCtx = {
|
|
591
|
-
request,
|
|
592
|
-
responseHeaders: new Headers(),
|
|
593
|
-
ctx: {},
|
|
594
|
-
requestId: opts.requestId ?? globalThis.crypto.randomUUID()
|
|
595
|
-
};
|
|
596
|
-
try {
|
|
597
|
-
await runPreHandlerPipeline(hookCtx, request, config, opts, hooks);
|
|
598
|
-
if (hooks.onResponse) {
|
|
599
|
-
for (const hook of hooks.onResponse) {
|
|
600
|
-
await hook(hookCtx);
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
const finalResponse = hookCtx.response ?? new Response(
|
|
604
|
-
JSON.stringify({ code: "INTERNAL_SERVER_ERROR", message: "No response built" }),
|
|
605
|
-
{
|
|
606
|
-
status: 500,
|
|
607
|
-
headers: { "content-type": "application/json" }
|
|
608
|
-
}
|
|
609
|
-
);
|
|
610
|
-
return mergeHookHeaders(finalResponse, hookCtx.responseHeaders);
|
|
611
|
-
} catch (err) {
|
|
612
|
-
return runErrorHooks(err, hookCtx, hooks.onError);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
async function runErrorHooks(err, hookCtx, onError) {
|
|
616
|
-
const errorResponse = handlerErrorResponse(err);
|
|
617
|
-
if (onError !== void 0) {
|
|
618
|
-
const errorCtx = {
|
|
619
|
-
...hookCtx,
|
|
620
|
-
response: errorResponse,
|
|
621
|
-
error: err
|
|
622
|
-
};
|
|
623
|
-
for (const hook of onError) {
|
|
624
|
-
try {
|
|
625
|
-
await hook(errorCtx);
|
|
626
|
-
} catch {
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
return mergeHookHeaders(errorResponse, hookCtx.responseHeaders);
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// src/server/http/middleware-runner.ts
|
|
634
|
-
import { existsSync } from "node:fs";
|
|
635
|
-
import { join } from "node:path";
|
|
636
|
-
|
|
637
|
-
// src/server/http/node-web-adapter.ts
|
|
638
|
-
async function writeWebResponseToServerResponse(response, res) {
|
|
639
|
-
const setCookies = response.headers.getSetCookie();
|
|
640
|
-
if (setCookies.length > 0) {
|
|
641
|
-
res.setHeader("Set-Cookie", setCookies);
|
|
642
|
-
}
|
|
643
|
-
const otherHeaders = {};
|
|
644
|
-
for (const [key, value] of response.headers.entries()) {
|
|
645
|
-
if (key.toLowerCase() === "set-cookie") continue;
|
|
646
|
-
otherHeaders[key] = value;
|
|
647
|
-
}
|
|
648
|
-
res.writeHead(response.status, response.statusText, otherHeaders);
|
|
649
|
-
if (response.body === null) {
|
|
650
|
-
res.end();
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
const reader = response.body.getReader();
|
|
654
|
-
try {
|
|
655
|
-
for (; ; ) {
|
|
656
|
-
const { done, value } = await reader.read();
|
|
657
|
-
if (done) break;
|
|
658
|
-
res.write(value);
|
|
659
|
-
}
|
|
660
|
-
res.end();
|
|
661
|
-
} finally {
|
|
662
|
-
reader.releaseLock();
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
// src/server/http/middleware-runner.ts
|
|
667
|
-
var middlewareCache = /* @__PURE__ */ new Map();
|
|
668
|
-
function _resetMiddlewareCacheForTests() {
|
|
669
|
-
middlewareCache.clear();
|
|
670
|
-
}
|
|
671
|
-
function getCachedScan(serverDir) {
|
|
672
|
-
let cached = middlewareCache.get(serverDir);
|
|
673
|
-
if (!cached) {
|
|
674
|
-
const singleFilePath = join(serverDir, "middleware.ts");
|
|
675
|
-
cached = {
|
|
676
|
-
singleFilePath,
|
|
677
|
-
singleFileExists: existsSync(singleFilePath),
|
|
678
|
-
dirMiddlewares: scanMiddlewares(serverDir)
|
|
679
|
-
};
|
|
680
|
-
middlewareCache.set(serverDir, cached);
|
|
681
|
-
}
|
|
682
|
-
return cached;
|
|
683
|
-
}
|
|
684
|
-
async function runWebShapedMiddleware(mw, req, res, context) {
|
|
685
|
-
const request = createWebRequestSource(req).toRequest();
|
|
686
|
-
const result = await mw(request, context);
|
|
687
|
-
if (!(result instanceof Response)) return { shortCircuited: false };
|
|
688
|
-
await writeWebResponseToServerResponse(result, res);
|
|
689
|
-
return { shortCircuited: true };
|
|
690
|
-
}
|
|
691
|
-
function isWebShaped(mw) {
|
|
692
|
-
return WEB_SHAPED_MIDDLEWARE in mw;
|
|
693
|
-
}
|
|
694
|
-
async function runScannedMiddleware(mw, req, res, context) {
|
|
695
|
-
if (isWebShaped(mw)) {
|
|
696
|
-
const { shortCircuited } = await runWebShapedMiddleware(mw, req, res, context);
|
|
697
|
-
return { aborted: shortCircuited };
|
|
698
|
-
}
|
|
699
|
-
const { nextCalled } = await runOneMiddleware(mw, req, res);
|
|
700
|
-
return { aborted: !nextCalled || res.writableEnded };
|
|
701
|
-
}
|
|
702
|
-
async function runOneMiddleware(mw, req, res) {
|
|
703
|
-
const state = { nextCalled: false };
|
|
704
|
-
await mw(req, res, () => {
|
|
705
|
-
state.nextCalled = true;
|
|
706
|
-
});
|
|
707
|
-
return state;
|
|
708
|
-
}
|
|
709
|
-
async function runMiddlewareAndContext(req, res, loadModule, serverDir) {
|
|
710
|
-
const { singleFilePath, singleFileExists, dirMiddlewares } = getCachedScan(serverDir);
|
|
711
|
-
const dirExists = dirMiddlewares.length > 0;
|
|
712
|
-
const middlewareCtx = {};
|
|
713
|
-
if (singleFileExists && dirExists) {
|
|
714
|
-
throw new Error(
|
|
715
|
-
"Ambiguous middleware configuration: found both server/middleware.ts and server/middleware/ directory. Use one or the other, not both."
|
|
716
|
-
);
|
|
717
|
-
}
|
|
718
|
-
if (dirExists) {
|
|
719
|
-
for (const mwPath of dirMiddlewares) {
|
|
720
|
-
const mod = await loadModule(mwPath);
|
|
721
|
-
const mw = mod.default;
|
|
722
|
-
if (typeof mw !== "function") continue;
|
|
723
|
-
const { aborted } = await runScannedMiddleware(mw, req, res, middlewareCtx);
|
|
724
|
-
if (aborted) return { ctx: middlewareCtx, aborted: true };
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
if (singleFileExists) {
|
|
728
|
-
const mod = await loadModule(singleFilePath);
|
|
729
|
-
const mw = mod.default;
|
|
730
|
-
if (typeof mw === "function") {
|
|
731
|
-
const { aborted } = await runScannedMiddleware(mw, req, res, middlewareCtx);
|
|
732
|
-
if (aborted) return { ctx: middlewareCtx, aborted: true };
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
const factoryCtx = await createServerContext(req, res, loadModule, serverDir);
|
|
736
|
-
if (factoryCtx === null || typeof factoryCtx !== "object") {
|
|
737
|
-
return { ctx: middlewareCtx, aborted: false };
|
|
738
|
-
}
|
|
739
|
-
return { ctx: { ...middlewareCtx, ...factoryCtx }, aborted: false };
|
|
740
|
-
}
|
|
741
|
-
async function createServerContext(req, res, loadModule, serverDir) {
|
|
742
|
-
const contextPath = join(serverDir, "context.ts");
|
|
743
|
-
if (!existsSync(contextPath)) return {};
|
|
744
|
-
const mod = await loadModule(contextPath);
|
|
745
|
-
const createContext = mod.createContext;
|
|
746
|
-
if (typeof createContext !== "function") return {};
|
|
747
|
-
return await createContext({ request: req, response: res });
|
|
748
|
-
}
|
|
749
|
-
|
|
750
39
|
// src/core/contracts/auth-error-guard.ts
|
|
751
40
|
function isAuthRequiredError(err) {
|
|
752
41
|
if (err == null || typeof err !== "object") return false;
|
|
@@ -761,7 +50,7 @@ function dispatchCsrfWarn(payload) {
|
|
|
761
50
|
}
|
|
762
51
|
|
|
763
52
|
// src/server/http/execute.ts
|
|
764
|
-
var
|
|
53
|
+
var CSRF_PROTECTED_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
765
54
|
async function waitForDrain(res) {
|
|
766
55
|
if (typeof res.once !== "function") return;
|
|
767
56
|
await new Promise((resolve) => {
|
|
@@ -892,7 +181,7 @@ async function executeRoute(ctx) {
|
|
|
892
181
|
return;
|
|
893
182
|
}
|
|
894
183
|
const routeOptOut = typeof routeConfig === "object" && routeConfig.csrf === false;
|
|
895
|
-
if (
|
|
184
|
+
if (CSRF_PROTECTED_METHODS.has(method) && !routeOptOut) {
|
|
896
185
|
const decision = enforceCsrf(
|
|
897
186
|
req,
|
|
898
187
|
csrfMode,
|
|
@@ -1338,7 +627,7 @@ function enforceCsrfForAction(req, res, ctx) {
|
|
|
1338
627
|
);
|
|
1339
628
|
return false;
|
|
1340
629
|
}
|
|
1341
|
-
async function
|
|
630
|
+
async function runPreHandlerPipeline(p) {
|
|
1342
631
|
if (p.serverDir) {
|
|
1343
632
|
const result = await runMiddlewareAndContext(p.req, p.res, p.loadModule, p.serverDir);
|
|
1344
633
|
if (result.aborted) return false;
|
|
@@ -1466,7 +755,7 @@ async function executeActionWithOptions(opts) {
|
|
|
1466
755
|
req,
|
|
1467
756
|
res
|
|
1468
757
|
};
|
|
1469
|
-
if (!await
|
|
758
|
+
if (!await runPreHandlerPipeline(pipeline)) return;
|
|
1470
759
|
ctx = pipeline.ctx;
|
|
1471
760
|
const bodyOutcome = await readActionBody(req, res, requestId, actionConfig);
|
|
1472
761
|
if (!bodyOutcome.ok) return;
|
|
@@ -1738,17 +1027,6 @@ function createCorsWebHandler(config) {
|
|
|
1738
1027
|
|
|
1739
1028
|
export {
|
|
1740
1029
|
dispatchCsrfWarn,
|
|
1741
|
-
sendJson,
|
|
1742
|
-
sendError,
|
|
1743
|
-
incomingMessageToWebRequest,
|
|
1744
|
-
createWebRequestSource,
|
|
1745
|
-
incomingMessageToHandlerRequest,
|
|
1746
|
-
validateRouteInput,
|
|
1747
|
-
executeWebRequest,
|
|
1748
|
-
writeWebResponseToServerResponse,
|
|
1749
|
-
_resetMiddlewareCacheForTests,
|
|
1750
|
-
runMiddlewareAndContext,
|
|
1751
|
-
createServerContext,
|
|
1752
1030
|
executeRoute,
|
|
1753
1031
|
handleRequestError,
|
|
1754
1032
|
handleWebRequestError,
|
|
@@ -1761,4 +1039,4 @@ export {
|
|
|
1761
1039
|
createCorsHandler,
|
|
1762
1040
|
createCorsWebHandler
|
|
1763
1041
|
};
|
|
1764
|
-
//# sourceMappingURL=chunk-
|
|
1042
|
+
//# sourceMappingURL=chunk-KOG5K26V.js.map
|