stitchkit 0.2.0 → 0.4.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 +11 -10
- package/dist/browser/client.d.ts.map +1 -1
- package/dist/browser/http.d.ts +5 -0
- package/dist/browser/http.d.ts.map +1 -1
- package/dist/browser/socket-io.d.ts +17 -0
- package/dist/browser/socket-io.d.ts.map +1 -1
- package/dist/cli.d.ts +23 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +21 -0
- package/dist/contract/define.d.ts +35 -2
- package/dist/contract/define.d.ts.map +1 -1
- package/dist/contract/index.d.ts +1 -1
- package/dist/contract/index.d.ts.map +1 -1
- package/dist/contract/index.js +2 -1
- package/dist/index-0ed3bx43.js +33 -0
- package/dist/index-0ma1eqv4.js +1007 -0
- package/dist/index-1cf8jkhf.js +219 -0
- package/dist/index-37x76zdn.js +4 -0
- package/dist/{index-v2z2v3mq.js → index-3qmtdfpa.js} +304 -62
- package/dist/index-48ffdxgk.js +6 -0
- package/dist/{index-5sxnvwb1.js → index-78q1qm7v.js} +6 -3
- package/dist/{index-kckky6zw.js → index-afzt3nmx.js} +1 -1
- package/dist/{index-n7bmdwmz.js → index-d4rwrjbc.js} +8 -4
- package/dist/index-kzfs85xp.js +9 -0
- package/dist/index-mwmpw6j1.js +60 -0
- package/dist/{index-a35v22fh.js → index-vhdvv00d.js} +13 -5
- package/dist/index-x3fcszf8.js +8 -0
- package/dist/index.js +17 -4
- package/dist/internal/errors.d.ts +13 -1
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/http-input.d.ts +13 -0
- package/dist/internal/http-input.d.ts.map +1 -0
- package/dist/internal/safe-json.d.ts +19 -0
- package/dist/internal/safe-json.d.ts.map +1 -0
- package/dist/internal/secure-fetch.d.ts +27 -0
- package/dist/internal/secure-fetch.d.ts.map +1 -0
- package/dist/internal/within-dir.d.ts +7 -0
- package/dist/internal/within-dir.d.ts.map +1 -0
- package/dist/node.d.ts +10 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +41 -7
- package/dist/observability/audit.d.ts.map +1 -1
- package/dist/observability/context.d.ts +9 -1
- package/dist/observability/context.d.ts.map +1 -1
- package/dist/observability/event.d.ts +4 -0
- package/dist/observability/event.d.ts.map +1 -1
- package/dist/observability/index.js +38 -15
- package/dist/observability/sanitize.d.ts.map +1 -1
- package/dist/react.js +2 -0
- package/dist/server/context.d.ts +3 -2
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/event-bus.d.ts +10 -1
- package/dist/server/event-bus.d.ts.map +1 -1
- package/dist/server/implement.d.ts.map +1 -1
- package/dist/server/index.d.ts +6 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +203 -193
- package/dist/server/logger.d.ts +5 -4
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware/auth.d.ts +41 -1
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/cookies.d.ts.map +1 -1
- package/dist/server/middleware/cors.d.ts +7 -0
- package/dist/server/middleware/cors.d.ts.map +1 -1
- package/dist/server/middleware/pkce.d.ts +17 -0
- package/dist/server/middleware/pkce.d.ts.map +1 -0
- package/dist/server/multipart.d.ts +2 -1
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/node.d.ts +9 -0
- package/dist/server/node.d.ts.map +1 -1
- package/dist/server/openapi.d.ts +52 -0
- package/dist/server/openapi.d.ts.map +1 -0
- package/dist/server/rate-limit.d.ts +7 -2
- package/dist/server/rate-limit.d.ts.map +1 -1
- package/dist/server/request.d.ts +27 -4
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/router.d.ts +4 -2
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/socket-io.d.ts +60 -15
- package/dist/server/socket-io.d.ts.map +1 -1
- package/dist/server/stream.d.ts +3 -1
- package/dist/server/stream.d.ts.map +1 -1
- package/dist/server/types.d.ts +17 -1
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/websocket.d.ts +73 -0
- package/dist/server/websocket.d.ts.map +1 -0
- package/dist/tools/cli-args.d.ts +68 -0
- package/dist/tools/cli-args.d.ts.map +1 -0
- package/dist/tools/cli-format.d.ts +39 -0
- package/dist/tools/cli-format.d.ts.map +1 -0
- package/dist/tools/cli-wait.d.ts +45 -0
- package/dist/tools/cli-wait.d.ts.map +1 -0
- package/dist/tools/cli.d.ts +77 -0
- package/dist/tools/cli.d.ts.map +1 -0
- package/dist/tools/coerce.d.ts +8 -4
- package/dist/tools/coerce.d.ts.map +1 -1
- package/dist/tools/execute.d.ts +1 -1
- package/dist/tools/execute.d.ts.map +1 -1
- package/dist/tools/json-schema.d.ts +29 -4
- package/dist/tools/json-schema.d.ts.map +1 -1
- package/dist/tools/manifest.d.ts +4 -0
- package/dist/tools/manifest.d.ts.map +1 -1
- package/dist/tools/mcp-app.d.ts +59 -0
- package/dist/tools/mcp-app.d.ts.map +1 -0
- package/dist/tools/mcp-handler.d.ts +18 -0
- package/dist/tools/mcp-handler.d.ts.map +1 -1
- package/dist/tools/mcp.d.ts +9 -0
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mount-download.d.ts +30 -0
- package/dist/tools/mount-download.d.ts.map +1 -0
- package/dist/tools/mount-upload.d.ts +19 -0
- package/dist/tools/mount-upload.d.ts.map +1 -0
- package/dist/tools/mount-wait.d.ts +36 -0
- package/dist/tools/mount-wait.d.ts.map +1 -0
- package/dist/tools/mount.d.ts +8 -4
- package/dist/tools/mount.d.ts.map +1 -1
- package/dist/tools/native-result.d.ts +17 -0
- package/dist/tools/native-result.d.ts.map +1 -0
- package/dist/tools/oauth-metadata.d.ts +28 -0
- package/dist/tools/oauth-metadata.d.ts.map +1 -0
- package/dist/tools/oauth-provider.d.ts +85 -0
- package/dist/tools/oauth-provider.d.ts.map +1 -0
- package/dist/tools/remote.d.ts +2 -2
- package/dist/tools/remote.d.ts.map +1 -1
- package/dist/tools/toolkit.d.ts +51 -0
- package/dist/tools/toolkit.d.ts.map +1 -0
- package/dist/tools/view-file.d.ts +12 -0
- package/dist/tools/view-file.d.ts.map +1 -1
- package/dist/tools/wait-core.d.ts +33 -0
- package/dist/tools/wait-core.d.ts.map +1 -0
- package/dist/tools.d.ts +13 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +637 -424
- package/package.json +22 -9
- package/dist/index-ke4mx4ea.js +0 -38
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EACL,SAAS,EACT,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,oBAAoB,EACzB,cAAc,EACd,oBAAoB,EACpB,YAAY,EACZ,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,OAAO,EACP,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,KAAK,UAAU,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,YAAY,GACb,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EACL,KAAK,eAAe,EACpB,SAAS,EACT,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EACV,SAAS,EACT,eAAe,EACf,aAAa,EACb,QAAQ,EACR,cAAc,EACd,SAAS,EACT,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,UAAU,EACV,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,KAAK,YAAY,EACjB,wBAAwB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,aAAa,GACd,MAAM,aAAa,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseSSE,
|
|
3
3
|
streamSSE
|
|
4
|
-
} from "../index-
|
|
4
|
+
} from "../index-d4rwrjbc.js";
|
|
5
5
|
import {
|
|
6
|
+
createAuthHook,
|
|
7
|
+
createBearerResolver,
|
|
8
|
+
defineCookie,
|
|
9
|
+
deriveCodeChallenge,
|
|
10
|
+
extractToken,
|
|
11
|
+
parseCookies,
|
|
12
|
+
serializeCookie,
|
|
13
|
+
signJwt,
|
|
14
|
+
verifyJwt,
|
|
15
|
+
verifyPkce
|
|
16
|
+
} from "../index-1cf8jkhf.js";
|
|
17
|
+
import {
|
|
18
|
+
inputIsQuery
|
|
19
|
+
} from "../index-48ffdxgk.js";
|
|
20
|
+
import {
|
|
21
|
+
jsonSchemaFields,
|
|
22
|
+
toJsonSchema
|
|
23
|
+
} from "../index-0ed3bx43.js";
|
|
24
|
+
import {
|
|
25
|
+
composeWebSocketHandlers,
|
|
6
26
|
corsHeaders,
|
|
7
27
|
corsPreflightResponse,
|
|
8
28
|
createHandler,
|
|
29
|
+
createImplement,
|
|
9
30
|
createServer,
|
|
31
|
+
createSocketIOServer,
|
|
32
|
+
implement,
|
|
10
33
|
parseMultipart,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
34
|
+
socketIoLane,
|
|
35
|
+
staticRoute,
|
|
36
|
+
webSocketLane
|
|
37
|
+
} from "../index-3qmtdfpa.js";
|
|
38
|
+
import"../index-x3fcszf8.js";
|
|
39
|
+
import"../index-vhdvv00d.js";
|
|
14
40
|
import {
|
|
15
41
|
AppError,
|
|
16
42
|
appError,
|
|
@@ -20,13 +46,19 @@ import {
|
|
|
20
46
|
notFound,
|
|
21
47
|
rateLimited,
|
|
22
48
|
unauthorized
|
|
23
|
-
} from "../index-
|
|
49
|
+
} from "../index-afzt3nmx.js";
|
|
24
50
|
import {
|
|
25
51
|
extractIp,
|
|
26
52
|
generateTraceId,
|
|
27
53
|
getClientInfo,
|
|
54
|
+
resolveSocketIp,
|
|
28
55
|
resolveTraceId
|
|
29
|
-
} from "../index-
|
|
56
|
+
} from "../index-mwmpw6j1.js";
|
|
57
|
+
import"../index-kzfs85xp.js";
|
|
58
|
+
import {
|
|
59
|
+
isRecord
|
|
60
|
+
} from "../index-809wc1tt.js";
|
|
61
|
+
import"../index-37x76zdn.js";
|
|
30
62
|
// src/server/swept-map.ts
|
|
31
63
|
function createSweptMap(options) {
|
|
32
64
|
const store = new Map;
|
|
@@ -85,7 +117,7 @@ function cacheHeaders(maxAge, scope = "public") {
|
|
|
85
117
|
};
|
|
86
118
|
}
|
|
87
119
|
// src/server/event-bus.ts
|
|
88
|
-
function createEventBus() {
|
|
120
|
+
function createEventBus(options = {}) {
|
|
89
121
|
const subscriptions = new Map;
|
|
90
122
|
function add(event, fn, once) {
|
|
91
123
|
let set = subscriptions.get(event);
|
|
@@ -109,11 +141,12 @@ function createEventBus() {
|
|
|
109
141
|
set.delete(sub);
|
|
110
142
|
try {
|
|
111
143
|
const result = sub.fn(data);
|
|
112
|
-
if (result instanceof Promise)
|
|
113
|
-
result.catch(() =>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
144
|
+
if (result instanceof Promise) {
|
|
145
|
+
result.catch((err) => options.onListenerError?.(err, event));
|
|
146
|
+
}
|
|
147
|
+
} catch (err) {
|
|
148
|
+
options.onListenerError?.(err, event);
|
|
149
|
+
}
|
|
117
150
|
}
|
|
118
151
|
},
|
|
119
152
|
on(event, handler) {
|
|
@@ -136,163 +169,150 @@ function createEventBus() {
|
|
|
136
169
|
}
|
|
137
170
|
};
|
|
138
171
|
}
|
|
139
|
-
// src/server/
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
return {
|
|
160
|
-
name: contract.meta.prefix,
|
|
161
|
-
prefix: contract.meta.prefix,
|
|
162
|
-
scope: groupScope,
|
|
163
|
-
methods
|
|
164
|
-
};
|
|
172
|
+
// src/server/openapi.ts
|
|
173
|
+
var ERROR_ENVELOPE_SCHEMA = {
|
|
174
|
+
type: "object",
|
|
175
|
+
properties: {
|
|
176
|
+
error: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {
|
|
179
|
+
code: { type: "string" },
|
|
180
|
+
message: { type: "string" },
|
|
181
|
+
details: {},
|
|
182
|
+
hint: { type: "string" }
|
|
183
|
+
},
|
|
184
|
+
required: ["code"]
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
required: ["error"]
|
|
188
|
+
};
|
|
189
|
+
function joinPath(...parts) {
|
|
190
|
+
const joined = parts.filter((p) => Boolean(p)).map((part) => part.replace(/^\/+|\/+$/g, "")).filter(Boolean).join("/");
|
|
191
|
+
return `/${joined}`;
|
|
165
192
|
}
|
|
166
|
-
function
|
|
167
|
-
return (
|
|
193
|
+
function toOpenApiPath(path) {
|
|
194
|
+
return path.replace(/:([^/]+)/g, "{$1}");
|
|
168
195
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
196
|
+
function safeJson(schema, io) {
|
|
197
|
+
if (!schema)
|
|
198
|
+
return {};
|
|
199
|
+
try {
|
|
200
|
+
return toJsonSchema(schema, io, "any");
|
|
201
|
+
} catch {
|
|
172
202
|
return {};
|
|
173
|
-
const cookies = {};
|
|
174
|
-
for (const pair of header.split(";")) {
|
|
175
|
-
const [key, ...rest] = pair.split("=");
|
|
176
|
-
if (!key)
|
|
177
|
-
continue;
|
|
178
|
-
const raw = rest.join("=").trim();
|
|
179
|
-
try {
|
|
180
|
-
cookies[key.trim()] = decodeURIComponent(raw);
|
|
181
|
-
} catch {
|
|
182
|
-
cookies[key.trim()] = raw;
|
|
183
|
-
}
|
|
184
203
|
}
|
|
185
|
-
return cookies;
|
|
186
204
|
}
|
|
187
|
-
function
|
|
188
|
-
let cookie = `${name}=${encodeURIComponent(value)}`;
|
|
189
|
-
if (opts.maxAge !== undefined)
|
|
190
|
-
cookie += `; Max-Age=${opts.maxAge}`;
|
|
191
|
-
if (opts.path)
|
|
192
|
-
cookie += `; Path=${opts.path}`;
|
|
193
|
-
if (opts.domain)
|
|
194
|
-
cookie += `; Domain=${opts.domain}`;
|
|
195
|
-
if (opts.secure)
|
|
196
|
-
cookie += "; Secure";
|
|
197
|
-
if (opts.httpOnly)
|
|
198
|
-
cookie += "; HttpOnly";
|
|
199
|
-
if (opts.sameSite)
|
|
200
|
-
cookie += `; SameSite=${opts.sameSite}`;
|
|
201
|
-
return cookie;
|
|
202
|
-
}
|
|
203
|
-
function defineCookie(config) {
|
|
204
|
-
const { name, ...options } = config;
|
|
205
|
+
function errorResponse(description) {
|
|
205
206
|
return {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
},
|
|
209
|
-
set(value) {
|
|
210
|
-
return serializeCookie(name, value, options);
|
|
211
|
-
},
|
|
212
|
-
clear() {
|
|
213
|
-
return serializeCookie(name, "", { ...options, maxAge: 0 });
|
|
214
|
-
}
|
|
207
|
+
description,
|
|
208
|
+
content: { "application/json": { schema: ERROR_ENVELOPE_SCHEMA } }
|
|
215
209
|
};
|
|
216
210
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
const [headerB64, payloadB64, signatureB64] = token.split(".");
|
|
226
|
-
if (!headerB64 || !payloadB64 || !signatureB64)
|
|
227
|
-
throw unauthorized("Invalid token format");
|
|
228
|
-
let header;
|
|
229
|
-
let payload;
|
|
230
|
-
let signature;
|
|
231
|
-
try {
|
|
232
|
-
const decoder = new TextDecoder;
|
|
233
|
-
header = JSON.parse(decoder.decode(decodeBase64Url(headerB64)));
|
|
234
|
-
payload = JSON.parse(decoder.decode(decodeBase64Url(payloadB64)));
|
|
235
|
-
signature = decodeBase64Url(signatureB64);
|
|
236
|
-
} catch {
|
|
237
|
-
throw unauthorized("Malformed token");
|
|
238
|
-
}
|
|
239
|
-
if (header.alg !== "HS256")
|
|
240
|
-
throw unauthorized("Unsupported token algorithm");
|
|
241
|
-
const encoder = new TextEncoder;
|
|
242
|
-
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"]);
|
|
243
|
-
const data = encoder.encode(`${headerB64}.${payloadB64}`);
|
|
244
|
-
const valid = await crypto.subtle.verify("HMAC", key, signature, data);
|
|
245
|
-
if (!valid)
|
|
246
|
-
throw unauthorized("Invalid token signature");
|
|
247
|
-
const now = Date.now() / 1000;
|
|
248
|
-
if (typeof payload.exp === "number" && payload.exp < now) {
|
|
249
|
-
throw unauthorized("Token expired");
|
|
250
|
-
}
|
|
251
|
-
if (typeof payload.nbf === "number" && payload.nbf > now) {
|
|
252
|
-
throw unauthorized("Token not yet valid");
|
|
253
|
-
}
|
|
254
|
-
return payload;
|
|
255
|
-
}
|
|
256
|
-
function extractToken(req, cookieName) {
|
|
257
|
-
const authHeader = req.headers.get("authorization");
|
|
258
|
-
if (authHeader?.startsWith("Bearer "))
|
|
259
|
-
return authHeader.slice(7);
|
|
260
|
-
if (cookieName) {
|
|
261
|
-
const cookies = parseCookies(req.headers.get("cookie"));
|
|
262
|
-
return cookies[cookieName] ?? null;
|
|
211
|
+
function errorResponses(scope) {
|
|
212
|
+
const responses = {
|
|
213
|
+
"400": errorResponse("Validation error"),
|
|
214
|
+
"500": errorResponse("Server error")
|
|
215
|
+
};
|
|
216
|
+
if (scope && scope !== "public") {
|
|
217
|
+
responses["401"] = errorResponse("Unauthorized");
|
|
218
|
+
responses["403"] = errorResponse("Forbidden");
|
|
263
219
|
}
|
|
264
|
-
return
|
|
220
|
+
return responses;
|
|
265
221
|
}
|
|
266
|
-
function
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
222
|
+
function generateOpenApiDocument(config) {
|
|
223
|
+
const groups = [
|
|
224
|
+
...(config.services ?? []).map((service) => ({ pathPrefix: undefined, service })),
|
|
225
|
+
...(config.groups ?? []).flatMap((group) => group.services.map((service) => ({ pathPrefix: group.pathPrefix, service })))
|
|
226
|
+
];
|
|
227
|
+
const paths = {};
|
|
228
|
+
for (const { pathPrefix, service } of groups) {
|
|
229
|
+
for (const [key, method] of Object.entries(service.methods)) {
|
|
230
|
+
if (method.expose && !method.expose.includes("HTTP"))
|
|
231
|
+
continue;
|
|
232
|
+
const servicePath = joinPath("/", service.prefix, method.path === "/" ? "" : method.path);
|
|
233
|
+
const fullPath = toOpenApiPath(pathPrefix ? joinPath(pathPrefix, servicePath) : servicePath);
|
|
234
|
+
const parameters = [];
|
|
235
|
+
for (const field of jsonSchemaFields(safeJson(method.paramsSchema, "input"))) {
|
|
236
|
+
parameters.push({
|
|
237
|
+
name: field.name,
|
|
238
|
+
in: "path",
|
|
239
|
+
required: true,
|
|
240
|
+
schema: field.schema,
|
|
241
|
+
...field.description && { description: field.description }
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const inputInQuery = inputIsQuery(method.method);
|
|
245
|
+
if (inputInQuery && method.inputSchema) {
|
|
246
|
+
for (const field of jsonSchemaFields(safeJson(method.inputSchema, "input"))) {
|
|
247
|
+
parameters.push({
|
|
248
|
+
name: field.name,
|
|
249
|
+
in: "query",
|
|
250
|
+
required: field.required,
|
|
251
|
+
schema: field.schema,
|
|
252
|
+
...field.description && { description: field.description }
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const responses = { ...errorResponses(method.scope) };
|
|
257
|
+
if (method.outputSchema) {
|
|
258
|
+
responses["200"] = {
|
|
259
|
+
description: "Success",
|
|
260
|
+
content: { "application/json": { schema: safeJson(method.outputSchema, "output") } }
|
|
261
|
+
};
|
|
262
|
+
} else {
|
|
263
|
+
responses["204"] = { description: "No content" };
|
|
264
|
+
}
|
|
265
|
+
const operation = {
|
|
266
|
+
summary: method.desc,
|
|
267
|
+
operationId: `${service.name}_${key}`,
|
|
268
|
+
...parameters.length > 0 && { parameters },
|
|
269
|
+
responses
|
|
270
|
+
};
|
|
271
|
+
if (!inputInQuery && (method.inputSchema || method.multipart)) {
|
|
272
|
+
if (method.multipart) {
|
|
273
|
+
const inputJson = safeJson(method.inputSchema, "input");
|
|
274
|
+
const baseProps = isRecord(inputJson.properties) ? inputJson.properties : {};
|
|
275
|
+
const baseRequired = Array.isArray(inputJson.required) ? inputJson.required : [];
|
|
276
|
+
operation.requestBody = {
|
|
277
|
+
required: true,
|
|
278
|
+
content: {
|
|
279
|
+
"multipart/form-data": {
|
|
280
|
+
schema: {
|
|
281
|
+
type: "object",
|
|
282
|
+
properties: {
|
|
283
|
+
...baseProps,
|
|
284
|
+
[method.multipart]: { type: "string", format: "binary" }
|
|
285
|
+
},
|
|
286
|
+
required: [...baseRequired, method.multipart]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
} else if (method.inputSchema) {
|
|
292
|
+
const required = jsonSchemaFields(safeJson(method.inputSchema, "input")).some((f) => f.required);
|
|
293
|
+
operation.requestBody = {
|
|
294
|
+
required,
|
|
295
|
+
content: { "application/json": { schema: safeJson(method.inputSchema, "input") } }
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
const pathItem = paths[fullPath] ?? {};
|
|
300
|
+
pathItem[method.method.toLowerCase()] = operation;
|
|
301
|
+
paths[fullPath] = pathItem;
|
|
283
302
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
openapi: "3.1.0",
|
|
306
|
+
info: config.info,
|
|
307
|
+
...config.servers && { servers: config.servers },
|
|
308
|
+
paths
|
|
288
309
|
};
|
|
289
310
|
}
|
|
290
|
-
function
|
|
291
|
-
return
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
return config.lookup(token, req);
|
|
311
|
+
function openApiRoute(path, document) {
|
|
312
|
+
return {
|
|
313
|
+
method: "GET",
|
|
314
|
+
path,
|
|
315
|
+
handler: () => Response.json(document)
|
|
296
316
|
};
|
|
297
317
|
}
|
|
298
318
|
// src/server/rate-limit.ts
|
|
@@ -301,6 +321,7 @@ function refillBucket(entry, config, now) {
|
|
|
301
321
|
entry.tokens = Math.min(config.max, entry.tokens + elapsed / config.window * config.max);
|
|
302
322
|
entry.lastRefill = now;
|
|
303
323
|
}
|
|
324
|
+
var MAX_BUCKETS = 1e5;
|
|
304
325
|
function createRateLimiter() {
|
|
305
326
|
const { store: buckets, destroy } = createSweptMap({
|
|
306
327
|
intervalMs: 60000,
|
|
@@ -310,15 +331,26 @@ function createRateLimiter() {
|
|
|
310
331
|
destroy,
|
|
311
332
|
check(key, config) {
|
|
312
333
|
const now = Date.now();
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
|
|
334
|
+
const entry = buckets.get(key);
|
|
335
|
+
if (entry) {
|
|
336
|
+
buckets.delete(key);
|
|
316
337
|
buckets.set(key, entry);
|
|
338
|
+
refillBucket(entry, config, now);
|
|
339
|
+
if (entry.tokens < 1)
|
|
340
|
+
return false;
|
|
341
|
+
entry.tokens -= 1;
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
if (buckets.size >= MAX_BUCKETS) {
|
|
345
|
+
const lru = buckets.keys().next().value;
|
|
346
|
+
if (lru !== undefined)
|
|
347
|
+
buckets.delete(lru);
|
|
317
348
|
}
|
|
318
|
-
|
|
319
|
-
|
|
349
|
+
const fresh = { tokens: config.max, lastRefill: now };
|
|
350
|
+
buckets.set(key, fresh);
|
|
351
|
+
if (fresh.tokens < 1)
|
|
320
352
|
return false;
|
|
321
|
-
|
|
353
|
+
fresh.tokens -= 1;
|
|
322
354
|
return true;
|
|
323
355
|
},
|
|
324
356
|
remaining(key, config) {
|
|
@@ -330,55 +362,32 @@ function createRateLimiter() {
|
|
|
330
362
|
}
|
|
331
363
|
};
|
|
332
364
|
}
|
|
333
|
-
// src/server/socket-io.ts
|
|
334
|
-
import { Server as BunEngine } from "@socket.io/bun-engine";
|
|
335
|
-
import { Server as SocketIOServer } from "socket.io";
|
|
336
|
-
function createSocketIOServer(config) {
|
|
337
|
-
const path = config.path ?? "/socket.io/";
|
|
338
|
-
const io = new SocketIOServer({
|
|
339
|
-
path,
|
|
340
|
-
cors: {
|
|
341
|
-
origin: config.cors.origin,
|
|
342
|
-
credentials: config.cors.credentials ?? true,
|
|
343
|
-
methods: ["GET", "POST"]
|
|
344
|
-
},
|
|
345
|
-
transports: config.transports ?? ["websocket", "polling"],
|
|
346
|
-
pingTimeout: config.pingTimeout ?? 20000,
|
|
347
|
-
pingInterval: config.pingInterval ?? 1e4
|
|
348
|
-
});
|
|
349
|
-
const engine = new BunEngine({ path });
|
|
350
|
-
io.bind(engine);
|
|
351
|
-
const { websocket } = engine.handler();
|
|
352
|
-
const route = {
|
|
353
|
-
method: "ALL",
|
|
354
|
-
path: `${path.replace(/\/+$/, "")}/*`,
|
|
355
|
-
handler: (req, ctx) => {
|
|
356
|
-
if (!ctx.server) {
|
|
357
|
-
throw new Error("[stitchkit] createSocketIOServer route needs a running Bun server — mount it via createServer.");
|
|
358
|
-
}
|
|
359
|
-
return engine.handleRequest(req, ctx.server);
|
|
360
|
-
}
|
|
361
|
-
};
|
|
362
|
-
return { io, websocket, route };
|
|
363
|
-
}
|
|
364
365
|
export {
|
|
366
|
+
webSocketLane,
|
|
367
|
+
verifyPkce,
|
|
365
368
|
verifyJwt,
|
|
366
369
|
unauthorized,
|
|
367
370
|
streamSSE,
|
|
368
371
|
staticRoute,
|
|
372
|
+
socketIoLane,
|
|
373
|
+
signJwt,
|
|
369
374
|
serializeCookie,
|
|
370
375
|
resolveTraceId,
|
|
376
|
+
resolveSocketIp,
|
|
371
377
|
rateLimited,
|
|
372
378
|
parseSSE,
|
|
373
379
|
parseMultipart,
|
|
374
380
|
parseCookies,
|
|
381
|
+
openApiRoute,
|
|
375
382
|
notFound,
|
|
376
383
|
implement,
|
|
377
384
|
getClientInfo,
|
|
378
385
|
generateTraceId,
|
|
386
|
+
generateOpenApiDocument,
|
|
379
387
|
forbidden,
|
|
380
388
|
extractToken,
|
|
381
389
|
extractIp,
|
|
390
|
+
deriveCodeChallenge,
|
|
382
391
|
defineCookie,
|
|
383
392
|
createSocketIOServer,
|
|
384
393
|
createServer,
|
|
@@ -392,6 +401,7 @@ export {
|
|
|
392
401
|
corsPreflightResponse,
|
|
393
402
|
corsHeaders,
|
|
394
403
|
conflict,
|
|
404
|
+
composeWebSocketHandlers,
|
|
395
405
|
cacheHeaders,
|
|
396
406
|
badRequest,
|
|
397
407
|
appError,
|
package/dist/server/logger.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/** Elapsed milliseconds since a `performance.now()` mark. */
|
|
2
|
+
export declare function elapsedMs(startTime: number): number;
|
|
2
3
|
/** Map an HTTP status to a log level. */
|
|
3
4
|
export declare function levelForStatus(status: number): 'error' | 'warn' | 'info';
|
|
4
5
|
/** The structured fields shared by every completed-request log line. */
|
|
@@ -11,11 +12,11 @@ export declare function buildLogFields(method: string, path: string, status: num
|
|
|
11
12
|
};
|
|
12
13
|
export interface RequestLog {
|
|
13
14
|
traceId: string;
|
|
14
|
-
startTime:
|
|
15
|
+
startTime: number;
|
|
15
16
|
}
|
|
16
17
|
export declare function shouldLog(pathname: string, method: string): boolean;
|
|
17
18
|
/** Open the timing window for a request. Development prints a `→` line. */
|
|
18
|
-
export declare function logIncoming(req: Request, pathname: string, traceId: string): RequestLog;
|
|
19
|
+
export declare function logIncoming(req: Request, pathname: string, traceId: string, ipAddress?: string): RequestLog;
|
|
19
20
|
/** Close a request. Development: `←` line. Production: one structured JSON line. */
|
|
20
|
-
export declare function logOutgoing(req: Request, pathname: string, status: number, log: RequestLog): void;
|
|
21
|
+
export declare function logOutgoing(req: Request, pathname: string, status: number, log: RequestLog, ipAddress?: string): void;
|
|
21
22
|
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/server/logger.ts"],"names":[],"mappings":"AAwCA,6DAA6D;AAC7D,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEnD;AAQD,yCAAyC;AACzC,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAIxE;AAED,wEAAwE;AACxE,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAEvF;AA0BD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAID,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,UAAU,CASZ;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CACzB,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,UAAU,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI,CAoBN"}
|
|
@@ -3,7 +3,33 @@ import type { MethodDef } from '../types';
|
|
|
3
3
|
export interface JwtPayload {
|
|
4
4
|
[key: string]: unknown;
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
/** Tuning for `verifyJwt`. */
|
|
7
|
+
export interface VerifyJwtOptions {
|
|
8
|
+
/** Clock-skew tolerance for `exp` / `nbf`, in seconds. Default `60`. */
|
|
9
|
+
leewaySeconds?: number;
|
|
10
|
+
/** Required `iss` claim — the token is rejected on mismatch. */
|
|
11
|
+
issuer?: string;
|
|
12
|
+
/** Required `aud` claim — the token is rejected if it does not carry it. */
|
|
13
|
+
audience?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function verifyJwt(token: string, secret: string, options?: VerifyJwtOptions): Promise<JwtPayload>;
|
|
16
|
+
/** Tuning for `signJwt`. */
|
|
17
|
+
export interface SignJwtOptions {
|
|
18
|
+
/** Lifetime in seconds — sets `exp` to now + this. Omit for no expiry. */
|
|
19
|
+
expiresInSec?: number;
|
|
20
|
+
/** `iss` claim. */
|
|
21
|
+
issuer?: string;
|
|
22
|
+
/** `aud` claim. */
|
|
23
|
+
audience?: string;
|
|
24
|
+
/** `sub` claim. */
|
|
25
|
+
subject?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sign a payload as an HS256 JWT — the issuing counterpart of `verifyJwt`.
|
|
29
|
+
* Used to mint OAuth access tokens whose audience binds them to one resource.
|
|
30
|
+
* `iat` is always set; `exp` / `iss` / `aud` / `sub` follow `options`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function signJwt(payload: JwtPayload, secret: string, options?: SignJwtOptions): Promise<string>;
|
|
7
33
|
export declare function extractToken(req: Request, cookieName?: string): string | null;
|
|
8
34
|
/**
|
|
9
35
|
* Per-scope access predicate. `endpoint.scope` selects which rule applies:
|
|
@@ -17,6 +43,14 @@ export type AuthRule<TIdentity> = 'public' | 'authenticated' | ((identity: Await
|
|
|
17
43
|
export interface AuthHookConfig<TIdentity> {
|
|
18
44
|
/** Resolve the request identity — cookie / bearer + DB lookup. */
|
|
19
45
|
resolve: (ctx: RuntimeContext) => Promise<TIdentity | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Resolve identity on a non-HTTP context (a tool call) where there is no
|
|
48
|
+
* `req`. The transport (MCP / agent) has already authenticated the caller;
|
|
49
|
+
* this locates the identity it injected into `ctx` (via `buildMcpServer`'s
|
|
50
|
+
* `context`). Without it, a scoped tool call with no `req` **fails closed**
|
|
51
|
+
* — the scope rule sees no identity and `onAnonymous` rejects the call.
|
|
52
|
+
*/
|
|
53
|
+
resolveFromContext?: (ctx: RuntimeContext) => TIdentity | null | Promise<TIdentity | null>;
|
|
20
54
|
/** Access rule per scope; `endpoint.scope` is the key. */
|
|
21
55
|
rules: Record<string, AuthRule<TIdentity>>;
|
|
22
56
|
/** Scope applied when an endpoint declares none. */
|
|
@@ -35,6 +69,12 @@ export type AuthHook = (ctx: RuntimeContext, endpoint: MethodDef) => Promise<voi
|
|
|
35
69
|
* Identity resolution and the scope vocabulary stay in the project; the
|
|
36
70
|
* project annotates its `rules` object with `satisfies Record<MyScope, …>` to
|
|
37
71
|
* keep scope coverage exhaustive.
|
|
72
|
+
*
|
|
73
|
+
* The hook runs on both surfaces: as `createServer`'s `beforeHandle` (HTTP) and
|
|
74
|
+
* as a tool mount's `lifecycle.beforeHandle` (MCP / agent). On HTTP it resolves
|
|
75
|
+
* identity from `ctx.req` via `resolve`; on a tool call — where there is no
|
|
76
|
+
* `req` — it uses `resolveFromContext`. If `resolveFromContext` is omitted, a
|
|
77
|
+
* scoped tool call has no identity and **fails closed** (never silently passes).
|
|
38
78
|
*/
|
|
39
79
|
export declare function createAuthHook<TIdentity>(config: AuthHookConfig<TIdentity>): AuthHook;
|
|
40
80
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cookies.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cookies.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkB1E;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CACtC;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,aAAkB,GACvB,MAAM,CASR;AAED,4EAA4E;AAC5E,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;IACtC,+EAA+E;IAC/E,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,gEAAgE;IAChE,KAAK,IAAI,MAAM,CAAC;CACjB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAahF"}
|
|
@@ -4,6 +4,13 @@ export interface CorsConfig {
|
|
|
4
4
|
methods?: string;
|
|
5
5
|
headers?: string;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Reject an unsafe CORS config at construction. `credentials: true` with a
|
|
9
|
+
* wildcard origin would reflect *any* caller's `Origin` with
|
|
10
|
+
* `Allow-Credentials: true` — every site could make authenticated cross-origin
|
|
11
|
+
* requests. Credentials require an explicit origin allow-list.
|
|
12
|
+
*/
|
|
13
|
+
export declare function assertCorsConfig(config: CorsConfig): void;
|
|
7
14
|
export declare function corsHeaders(config: CorsConfig, requestOrigin?: string | null): Record<string, string>;
|
|
8
15
|
export declare function corsPreflightResponse(config: CorsConfig, req: Request): Response;
|
|
9
16
|
//# sourceMappingURL=cors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/cors.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAOzD;AAoBD,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAsBxB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,GAAG,QAAQ,CAKhF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (RFC 7636) verification for the OAuth authorization-code flow. The client
|
|
3
|
+
* sends a `code_challenge` at `/authorize` and the matching `code_verifier` at
|
|
4
|
+
* `/token`; the server confirms they correspond so an intercepted code is
|
|
5
|
+
* useless without the verifier.
|
|
6
|
+
*/
|
|
7
|
+
/** The only PKCE method OAuth 2.1 permits for public clients. */
|
|
8
|
+
export type PkceMethod = 'S256';
|
|
9
|
+
/** Derive the S256 `code_challenge` from a `code_verifier`. */
|
|
10
|
+
export declare function deriveCodeChallenge(verifier: string): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Verify a `code_verifier` against the stored S256 `code_challenge`. S256 is the
|
|
13
|
+
* only method OAuth 2.1 permits for public clients — `plain` is intentionally
|
|
14
|
+
* not supported (it offers no protection against a leaked challenge).
|
|
15
|
+
*/
|
|
16
|
+
export declare function verifyPkce(verifier: string, challenge: string): Promise<boolean>;
|
|
17
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/pkce.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAQhC,+DAA+D;AAC/D,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG3E;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAItF"}
|