@kaito-http/core 4.0.0-beta.2 → 4.0.0-beta.21
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/dist/chunk-TL3E52YN.js +835 -0
- package/dist/cors/cors.cjs +85 -17
- package/dist/cors/cors.d.cts +122 -26
- package/dist/cors/cors.d.ts +122 -26
- package/dist/cors/cors.js +85 -17
- package/dist/index.cjs +955 -85
- package/dist/index.d.cts +97 -104
- package/dist/index.d.ts +97 -104
- package/dist/index.js +140 -84
- package/dist/schema/schema.cjs +875 -0
- package/dist/schema/schema.d.cts +333 -0
- package/dist/schema/schema.d.ts +333 -0
- package/dist/schema/schema.js +38 -0
- package/dist/stream/stream.cjs +6 -9
- package/dist/stream/stream.d.cts +11 -8
- package/dist/stream/stream.d.ts +11 -8
- package/dist/stream/stream.js +6 -9
- package/package.json +6 -9
package/dist/index.js
CHANGED
|
@@ -1,6 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseSchema,
|
|
3
|
+
KArray,
|
|
4
|
+
KBoolean,
|
|
5
|
+
KLiteral,
|
|
6
|
+
KNull,
|
|
7
|
+
KNumber,
|
|
8
|
+
KObject,
|
|
9
|
+
KObjectFromURLSearchParams,
|
|
10
|
+
KRef,
|
|
11
|
+
KScalar,
|
|
12
|
+
KString,
|
|
13
|
+
KUnion,
|
|
14
|
+
ParseContext,
|
|
15
|
+
STRING_FORMAT_REGEXES,
|
|
16
|
+
SchemaError,
|
|
17
|
+
isPrimitiveJSONValue,
|
|
18
|
+
k
|
|
19
|
+
} from "./chunk-TL3E52YN.js";
|
|
20
|
+
|
|
1
21
|
// src/router/router.ts
|
|
2
|
-
import
|
|
3
|
-
import { createDocument } from "zod-openapi";
|
|
22
|
+
import "openapi3-ts/oas31";
|
|
4
23
|
|
|
5
24
|
// src/error.ts
|
|
6
25
|
var WrappedError = class _WrappedError extends Error {
|
|
@@ -113,38 +132,44 @@ var isNodeLikeDev = typeof process !== "undefined" && typeof process.env !== "un
|
|
|
113
132
|
|
|
114
133
|
// src/router/router.ts
|
|
115
134
|
var Router = class _Router {
|
|
116
|
-
state;
|
|
117
|
-
static create = (config) =>
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
135
|
+
#state;
|
|
136
|
+
static create = (config = {}) => {
|
|
137
|
+
return new _Router({
|
|
138
|
+
through: (context) => context,
|
|
139
|
+
routes: /* @__PURE__ */ new Set(),
|
|
140
|
+
config
|
|
141
|
+
});
|
|
142
|
+
};
|
|
122
143
|
constructor(state) {
|
|
123
|
-
this
|
|
144
|
+
this.#state = state;
|
|
124
145
|
}
|
|
125
146
|
get routes() {
|
|
126
|
-
return this
|
|
147
|
+
return this.#state.routes;
|
|
127
148
|
}
|
|
128
149
|
add = (method, path, route) => {
|
|
129
150
|
const merged = {
|
|
130
151
|
...typeof route === "object" ? route : { run: route },
|
|
131
152
|
method,
|
|
132
153
|
path,
|
|
133
|
-
|
|
154
|
+
router: this
|
|
134
155
|
};
|
|
135
156
|
return new _Router({
|
|
136
|
-
...this
|
|
137
|
-
routes: /* @__PURE__ */ new Set([...this
|
|
157
|
+
...this.#state,
|
|
158
|
+
routes: /* @__PURE__ */ new Set([...this.#state.routes, merged])
|
|
138
159
|
});
|
|
139
160
|
};
|
|
161
|
+
params = () => this;
|
|
140
162
|
merge = (pathPrefix, other) => {
|
|
141
|
-
const newRoutes = [...other
|
|
163
|
+
const newRoutes = [...other.#state.routes].map((route) => ({
|
|
142
164
|
...route,
|
|
143
|
-
|
|
165
|
+
// handle pathPrefix = / & route.path = / case causing //
|
|
166
|
+
// we intentionally are replacing on the joining path and not the pathPrefix, in case of
|
|
167
|
+
// /named -> merged to -> / causing /named/ not /named
|
|
168
|
+
path: `${pathPrefix}${route.path === "/" ? "" : route.path}`
|
|
144
169
|
}));
|
|
145
170
|
return new _Router({
|
|
146
|
-
...this
|
|
147
|
-
routes: /* @__PURE__ */ new Set([...this
|
|
171
|
+
...this.#state,
|
|
172
|
+
routes: /* @__PURE__ */ new Set([...this.#state.routes, ...newRoutes])
|
|
148
173
|
});
|
|
149
174
|
};
|
|
150
175
|
static getFindRoute = (routes) => (method, path) => {
|
|
@@ -172,32 +197,22 @@ var Router = class _Router {
|
|
|
172
197
|
}
|
|
173
198
|
return {};
|
|
174
199
|
};
|
|
175
|
-
static buildQuerySchema = (schema) => {
|
|
176
|
-
const keys = Object.keys(schema);
|
|
177
|
-
return z.instanceof(URLSearchParams).transform((params) => {
|
|
178
|
-
const result = {};
|
|
179
|
-
for (const key of keys) {
|
|
180
|
-
result[key] = params.get(key);
|
|
181
|
-
}
|
|
182
|
-
return result;
|
|
183
|
-
}).pipe(z.object(schema));
|
|
184
|
-
};
|
|
185
200
|
serve = () => {
|
|
186
201
|
const methodToRoutesMap = /* @__PURE__ */ new Map();
|
|
187
|
-
for (const route of this
|
|
202
|
+
for (const route of this.#state.routes) {
|
|
188
203
|
if (!methodToRoutesMap.has(route.method)) {
|
|
189
204
|
methodToRoutesMap.set(route.method, /* @__PURE__ */ new Map());
|
|
190
205
|
}
|
|
191
206
|
methodToRoutesMap.get(route.method).set(route.path, {
|
|
192
207
|
...route,
|
|
193
|
-
fastQuerySchema: route.query ?
|
|
208
|
+
fastQuerySchema: route.query ? k.objectFromURLSearchParams(route.query) : void 0
|
|
194
209
|
});
|
|
195
210
|
}
|
|
196
211
|
const findRoute = _Router.getFindRoute(methodToRoutesMap);
|
|
197
|
-
const handle = async (req) => {
|
|
212
|
+
const handle = async (req, ...args) => {
|
|
198
213
|
const url = new URL(req.url);
|
|
199
214
|
const method = req.method;
|
|
200
|
-
const { route, params } = findRoute(method, url.pathname);
|
|
215
|
+
const { route, params: rawParams } = findRoute(method, url.pathname);
|
|
201
216
|
if (!route) {
|
|
202
217
|
const body = {
|
|
203
218
|
success: false,
|
|
@@ -209,14 +224,17 @@ var Router = class _Router {
|
|
|
209
224
|
const request = new KaitoRequest(url, req);
|
|
210
225
|
const head = new KaitoHead();
|
|
211
226
|
try {
|
|
212
|
-
const body = route.body ? await route.body.
|
|
213
|
-
const query = route.fastQuerySchema ?
|
|
214
|
-
const ctx = await route.
|
|
227
|
+
const body = route.body ? await route.body.parse(await req.json()) : void 0;
|
|
228
|
+
const query = route.fastQuerySchema ? route.fastQuerySchema.parse(url.searchParams) : {};
|
|
229
|
+
const ctx = await route.router.#state.through(
|
|
230
|
+
await this.#state.config.getContext?.(request, head, ...args) ?? null,
|
|
231
|
+
rawParams
|
|
232
|
+
);
|
|
215
233
|
const result = await route.run({
|
|
216
234
|
ctx,
|
|
217
235
|
body,
|
|
218
236
|
query,
|
|
219
|
-
params
|
|
237
|
+
params: rawParams
|
|
220
238
|
});
|
|
221
239
|
if (result instanceof Response) {
|
|
222
240
|
if (isNodeLikeDev) {
|
|
@@ -232,6 +250,18 @@ var Router = class _Router {
|
|
|
232
250
|
}
|
|
233
251
|
return result;
|
|
234
252
|
}
|
|
253
|
+
if (route.openapi?.schema) {
|
|
254
|
+
if (route.openapi.type !== "json") {
|
|
255
|
+
throw new Error(
|
|
256
|
+
`Cannot use openapi schema for ${route.method} ${route.path} because it is not a json output type`
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
const parsed = route.openapi.schema.serialize(result);
|
|
260
|
+
return head.toResponse({
|
|
261
|
+
success: true,
|
|
262
|
+
data: parsed
|
|
263
|
+
});
|
|
264
|
+
}
|
|
235
265
|
return head.toResponse({
|
|
236
266
|
success: true,
|
|
237
267
|
data: result
|
|
@@ -245,7 +275,7 @@ var Router = class _Router {
|
|
|
245
275
|
message: error.message
|
|
246
276
|
});
|
|
247
277
|
}
|
|
248
|
-
if (!this
|
|
278
|
+
if (!this.#state.config.onError) {
|
|
249
279
|
return head.status(500).toResponse({
|
|
250
280
|
success: false,
|
|
251
281
|
data: null,
|
|
@@ -253,14 +283,14 @@ var Router = class _Router {
|
|
|
253
283
|
});
|
|
254
284
|
}
|
|
255
285
|
try {
|
|
256
|
-
const { status, message } = await this
|
|
286
|
+
const { status, message } = await this.#state.config.onError(error, request);
|
|
257
287
|
return head.status(status).toResponse({
|
|
258
288
|
success: false,
|
|
259
289
|
data: null,
|
|
260
290
|
message
|
|
261
291
|
});
|
|
262
292
|
} catch (e2) {
|
|
263
|
-
console.error("
|
|
293
|
+
console.error("[Kaito] Failed to handle error inside `.onError()`, returning 500 and Internal Server Error");
|
|
264
294
|
console.error(e2);
|
|
265
295
|
return head.status(500).toResponse({
|
|
266
296
|
success: false,
|
|
@@ -270,12 +300,12 @@ var Router = class _Router {
|
|
|
270
300
|
}
|
|
271
301
|
}
|
|
272
302
|
};
|
|
273
|
-
return async (request) => {
|
|
274
|
-
if (this
|
|
275
|
-
const result = await this
|
|
303
|
+
return async (request, ...args) => {
|
|
304
|
+
if (this.#state.config.before) {
|
|
305
|
+
const result = await this.#state.config.before(request);
|
|
276
306
|
if (result instanceof Response) {
|
|
277
|
-
if (this
|
|
278
|
-
const transformed = await this
|
|
307
|
+
if (this.#state.config.transform) {
|
|
308
|
+
const transformed = await this.#state.config.transform(request, result);
|
|
279
309
|
if (transformed instanceof Response) {
|
|
280
310
|
return result;
|
|
281
311
|
}
|
|
@@ -283,9 +313,9 @@ var Router = class _Router {
|
|
|
283
313
|
return result;
|
|
284
314
|
}
|
|
285
315
|
}
|
|
286
|
-
const response = await handle(request);
|
|
287
|
-
if (this
|
|
288
|
-
const transformed = await this
|
|
316
|
+
const response = await handle(request, ...args);
|
|
317
|
+
if (this.#state.config.transform) {
|
|
318
|
+
const transformed = await this.#state.config.transform(request, response);
|
|
289
319
|
if (transformed instanceof Response) {
|
|
290
320
|
return transformed;
|
|
291
321
|
}
|
|
@@ -293,66 +323,70 @@ var Router = class _Router {
|
|
|
293
323
|
return response;
|
|
294
324
|
};
|
|
295
325
|
};
|
|
296
|
-
openapi = (
|
|
297
|
-
|
|
326
|
+
openapi = ({
|
|
327
|
+
info,
|
|
328
|
+
servers
|
|
329
|
+
}) => {
|
|
330
|
+
const OPENAPI_VERSION = "3.1.0";
|
|
298
331
|
const paths = {};
|
|
299
|
-
for (const route of this
|
|
300
|
-
|
|
301
|
-
|
|
332
|
+
for (const route of this.#state.routes) {
|
|
333
|
+
if (!route.openapi) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const pathWithColonParamsReplaceWithCurlyBraces = route.path.replace(/:(\w+)/g, "{$1}");
|
|
302
337
|
if (!paths[pathWithColonParamsReplaceWithCurlyBraces]) {
|
|
303
338
|
paths[pathWithColonParamsReplaceWithCurlyBraces] = {};
|
|
304
339
|
}
|
|
340
|
+
let contentType;
|
|
341
|
+
const type = route.openapi.type;
|
|
342
|
+
switch (type) {
|
|
343
|
+
case "json":
|
|
344
|
+
contentType = "application/json";
|
|
345
|
+
break;
|
|
346
|
+
case "sse":
|
|
347
|
+
contentType = "text/event-stream";
|
|
348
|
+
break;
|
|
349
|
+
default:
|
|
350
|
+
throw new Error(`Unknown output type in route ${route.method} ${route.path}: ${type}`);
|
|
351
|
+
}
|
|
305
352
|
const item = {
|
|
306
353
|
description: route.openapi?.description ?? "Successful response",
|
|
307
354
|
responses: {
|
|
308
355
|
200: {
|
|
309
356
|
description: route.openapi?.description ?? "Successful response",
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
357
|
+
content: {
|
|
358
|
+
[contentType]: {
|
|
359
|
+
schema: k.object({
|
|
360
|
+
success: k.literal(true),
|
|
361
|
+
data: route.openapi.schema
|
|
362
|
+
}).toOpenAPI()
|
|
316
363
|
}
|
|
317
|
-
}
|
|
364
|
+
}
|
|
318
365
|
}
|
|
319
366
|
}
|
|
320
367
|
};
|
|
321
368
|
if (route.body) {
|
|
322
369
|
item.requestBody = {
|
|
323
370
|
content: {
|
|
324
|
-
"application/json": { schema: route.body }
|
|
371
|
+
"application/json": { schema: route.body.toOpenAPI() }
|
|
325
372
|
}
|
|
326
373
|
};
|
|
327
374
|
}
|
|
328
|
-
const params = {};
|
|
329
|
-
if (route.query) {
|
|
330
|
-
params.query = z.object(route.query);
|
|
331
|
-
}
|
|
332
|
-
const urlParams = path.match(/:(\w+)/g);
|
|
333
|
-
if (urlParams) {
|
|
334
|
-
const pathParams = {};
|
|
335
|
-
for (const param of urlParams) {
|
|
336
|
-
pathParams[param.slice(1)] = z.string();
|
|
337
|
-
}
|
|
338
|
-
params.path = z.object(pathParams);
|
|
339
|
-
}
|
|
340
|
-
item.requestParams = params;
|
|
341
375
|
paths[pathWithColonParamsReplaceWithCurlyBraces][route.method.toLowerCase()] = item;
|
|
342
376
|
}
|
|
343
|
-
const doc =
|
|
377
|
+
const doc = {
|
|
344
378
|
openapi: OPENAPI_VERSION,
|
|
379
|
+
info,
|
|
345
380
|
paths,
|
|
346
|
-
|
|
347
|
-
servers: Object.entries(highLevelSpec.servers ?? {}).map((entry) => {
|
|
381
|
+
servers: Object.entries(servers ?? {}).map((entry) => {
|
|
348
382
|
const [url, description] = entry;
|
|
349
383
|
return {
|
|
350
384
|
url,
|
|
351
385
|
description
|
|
352
386
|
};
|
|
353
387
|
})
|
|
354
|
-
}
|
|
355
|
-
return this.
|
|
388
|
+
};
|
|
389
|
+
return this.get("/openapi.json", () => Response.json(doc));
|
|
356
390
|
};
|
|
357
391
|
method = (method) => {
|
|
358
392
|
return (path, route) => this.add(method, path, route);
|
|
@@ -366,21 +400,43 @@ var Router = class _Router {
|
|
|
366
400
|
options = this.method("OPTIONS");
|
|
367
401
|
through = (through) => {
|
|
368
402
|
return new _Router({
|
|
369
|
-
...this
|
|
370
|
-
through:
|
|
403
|
+
...this.#state,
|
|
404
|
+
through: (context, params) => {
|
|
405
|
+
const next = this.#state.through(context, params);
|
|
406
|
+
if (next instanceof Promise) {
|
|
407
|
+
return next.then((next2) => through(next2, params));
|
|
408
|
+
}
|
|
409
|
+
return through(next, params);
|
|
410
|
+
}
|
|
371
411
|
});
|
|
372
412
|
};
|
|
373
413
|
};
|
|
374
414
|
|
|
375
|
-
// src/
|
|
376
|
-
|
|
377
|
-
return () => Router.create(config);
|
|
378
|
-
}
|
|
415
|
+
// src/index.ts
|
|
416
|
+
var create = Router.create;
|
|
379
417
|
export {
|
|
418
|
+
BaseSchema,
|
|
419
|
+
KArray,
|
|
420
|
+
KBoolean,
|
|
421
|
+
KLiteral,
|
|
422
|
+
KNull,
|
|
423
|
+
KNumber,
|
|
424
|
+
KObject,
|
|
425
|
+
KObjectFromURLSearchParams,
|
|
426
|
+
KRef,
|
|
427
|
+
KScalar,
|
|
428
|
+
KString,
|
|
429
|
+
KUnion,
|
|
380
430
|
KaitoError,
|
|
431
|
+
KaitoHead,
|
|
381
432
|
KaitoRequest,
|
|
433
|
+
ParseContext,
|
|
382
434
|
Router,
|
|
435
|
+
STRING_FORMAT_REGEXES,
|
|
436
|
+
SchemaError,
|
|
383
437
|
WrappedError,
|
|
384
438
|
create,
|
|
385
|
-
isNodeLikeDev
|
|
439
|
+
isNodeLikeDev,
|
|
440
|
+
isPrimitiveJSONValue,
|
|
441
|
+
k
|
|
386
442
|
};
|