@kaito-http/core 4.0.0-beta.3 → 4.0.0-beta.31
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-DRJX3OJG.js +1003 -0
- package/dist/chunk-HJ5HIYGW.js +92 -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 +1218 -106
- package/dist/index.d.cts +137 -107
- package/dist/index.d.ts +137 -107
- package/dist/index.js +218 -105
- package/dist/schema/schema.cjs +1046 -0
- package/dist/schema/schema.d.cts +391 -0
- package/dist/schema/schema.d.ts +391 -0
- package/dist/schema/schema.js +44 -0
- package/dist/stream/stream.cjs +11 -23
- package/dist/stream/stream.d.cts +14 -11
- package/dist/stream/stream.d.ts +14 -11
- package/dist/stream/stream.js +7 -96
- package/package.json +6 -9
package/dist/index.cjs
CHANGED
|
@@ -20,18 +20,38 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
BaseSchema: () => BaseSchema,
|
|
24
|
+
KArray: () => KArray,
|
|
25
|
+
KBoolean: () => KBoolean,
|
|
26
|
+
KLazy: () => KLazy,
|
|
27
|
+
KLiteral: () => KLiteral,
|
|
28
|
+
KNativeEnum: () => KNativeEnum,
|
|
29
|
+
KNull: () => KNull,
|
|
30
|
+
KNumber: () => KNumber,
|
|
31
|
+
KObject: () => KObject,
|
|
32
|
+
KObjectFromURLSearchParams: () => KObjectFromURLSearchParams,
|
|
33
|
+
KRecord: () => KRecord,
|
|
34
|
+
KRef: () => KRef,
|
|
35
|
+
KScalar: () => KScalar,
|
|
36
|
+
KString: () => KString,
|
|
37
|
+
KUnion: () => KUnion,
|
|
23
38
|
KaitoError: () => KaitoError,
|
|
39
|
+
KaitoHead: () => KaitoHead,
|
|
24
40
|
KaitoRequest: () => KaitoRequest,
|
|
41
|
+
ParseContext: () => ParseContext,
|
|
25
42
|
Router: () => Router,
|
|
43
|
+
STRING_FORMAT_REGEXES: () => STRING_FORMAT_REGEXES,
|
|
44
|
+
SchemaError: () => SchemaError,
|
|
26
45
|
WrappedError: () => WrappedError,
|
|
27
46
|
create: () => create,
|
|
28
|
-
isNodeLikeDev: () => isNodeLikeDev
|
|
47
|
+
isNodeLikeDev: () => isNodeLikeDev,
|
|
48
|
+
isPrimitiveJSONValue: () => isPrimitiveJSONValue,
|
|
49
|
+
k: () => k
|
|
29
50
|
});
|
|
30
51
|
module.exports = __toCommonJS(index_exports);
|
|
31
52
|
|
|
32
53
|
// src/router/router.ts
|
|
33
|
-
var
|
|
34
|
-
var import_zod_openapi = require("zod-openapi");
|
|
54
|
+
var OpenAPI = require("openapi3-ts/oas31");
|
|
35
55
|
|
|
36
56
|
// src/error.ts
|
|
37
57
|
var WrappedError = class _WrappedError extends Error {
|
|
@@ -84,14 +104,14 @@ var KaitoHead = class {
|
|
|
84
104
|
* @param body The Kaito JSON format to be sent as the response body
|
|
85
105
|
* @returns A Response instance, ready to be sent
|
|
86
106
|
*/
|
|
87
|
-
toResponse(
|
|
107
|
+
toResponse(data) {
|
|
88
108
|
const init = {
|
|
89
109
|
status: this.#status
|
|
90
110
|
};
|
|
91
111
|
if (this.#headers) {
|
|
92
112
|
init.headers = this.#headers;
|
|
93
113
|
}
|
|
94
|
-
return Response.json(
|
|
114
|
+
return Response.json(data, init);
|
|
95
115
|
}
|
|
96
116
|
/**
|
|
97
117
|
* Whether this KaitoHead instance has been touched/modified
|
|
@@ -139,43 +159,1048 @@ var KaitoRequest = class {
|
|
|
139
159
|
}
|
|
140
160
|
};
|
|
141
161
|
|
|
162
|
+
// src/schema/schema.ts
|
|
163
|
+
function isPrimitiveJSONValue(value) {
|
|
164
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null;
|
|
165
|
+
}
|
|
166
|
+
var SchemaError = class extends Error {
|
|
167
|
+
constructor(issues) {
|
|
168
|
+
const first = issues.values().next().value;
|
|
169
|
+
if (first === void 0) {
|
|
170
|
+
throw new Error("SchemaError expects at least one issue to be provided");
|
|
171
|
+
}
|
|
172
|
+
super(first.message);
|
|
173
|
+
this.issues = issues;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
var ParseContext = class _ParseContext {
|
|
177
|
+
static ISSUE = Symbol("ISSUE");
|
|
178
|
+
ISSUE = _ParseContext.ISSUE;
|
|
179
|
+
#issues = /* @__PURE__ */ new Set();
|
|
180
|
+
addIssue(message, path) {
|
|
181
|
+
this.#issues.add({ message, path });
|
|
182
|
+
return _ParseContext.ISSUE;
|
|
183
|
+
}
|
|
184
|
+
addIssues(issues, path) {
|
|
185
|
+
for (const issue of issues) {
|
|
186
|
+
this.#issues.add({ ...issue, path: [...path, ...issue.path] });
|
|
187
|
+
}
|
|
188
|
+
return _ParseContext.ISSUE;
|
|
189
|
+
}
|
|
190
|
+
get issues() {
|
|
191
|
+
return this.#issues;
|
|
192
|
+
}
|
|
193
|
+
static result(fn) {
|
|
194
|
+
const result = _ParseContext.with(fn);
|
|
195
|
+
if (result.type === "FATAL" || result.issues.size > 0) {
|
|
196
|
+
return {
|
|
197
|
+
success: false,
|
|
198
|
+
issues: result.issues
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
success: true,
|
|
203
|
+
result: result.data
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
static with(fn) {
|
|
207
|
+
const ctx = new _ParseContext();
|
|
208
|
+
const data = fn(ctx);
|
|
209
|
+
if (data === _ParseContext.ISSUE) {
|
|
210
|
+
return {
|
|
211
|
+
type: "FATAL",
|
|
212
|
+
issues: ctx.issues
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
return {
|
|
216
|
+
type: "PARSED",
|
|
217
|
+
issues: ctx.issues,
|
|
218
|
+
data
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
var BaseSchema = class {
|
|
223
|
+
/** @internal */
|
|
224
|
+
_input;
|
|
225
|
+
/** @internal */
|
|
226
|
+
_output;
|
|
227
|
+
def;
|
|
228
|
+
getSchemaObject() {
|
|
229
|
+
const schema = {};
|
|
230
|
+
if (this.def.description !== void 0) {
|
|
231
|
+
schema.description = this.def.description;
|
|
232
|
+
}
|
|
233
|
+
if (this.def.example !== void 0) {
|
|
234
|
+
schema.example = this.def.example;
|
|
235
|
+
}
|
|
236
|
+
return schema;
|
|
237
|
+
}
|
|
238
|
+
clone(def) {
|
|
239
|
+
return new this.constructor({
|
|
240
|
+
...this.def,
|
|
241
|
+
...def
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
constructor(def) {
|
|
245
|
+
this.def = def;
|
|
246
|
+
}
|
|
247
|
+
or(other) {
|
|
248
|
+
return k.union([this, other]);
|
|
249
|
+
}
|
|
250
|
+
example(example) {
|
|
251
|
+
if (example === void 0) {
|
|
252
|
+
return this.def.example;
|
|
253
|
+
}
|
|
254
|
+
return this.clone({ example });
|
|
255
|
+
}
|
|
256
|
+
description(description) {
|
|
257
|
+
if (description === void 0) {
|
|
258
|
+
return this.def.description;
|
|
259
|
+
}
|
|
260
|
+
return this.clone({ description });
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
var STRING_FORMAT_REGEXES = {
|
|
264
|
+
uuid: /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i,
|
|
265
|
+
email: /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i,
|
|
266
|
+
ipv4: /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,
|
|
267
|
+
ipv6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/,
|
|
268
|
+
date: /^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/,
|
|
269
|
+
uri: /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/.+|^[a-zA-Z][a-zA-Z0-9+.-]*:[^\/].+/,
|
|
270
|
+
hostname: /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/
|
|
271
|
+
};
|
|
272
|
+
var KString = class _KString extends BaseSchema {
|
|
273
|
+
static create = () => new _KString({});
|
|
274
|
+
serialize(value) {
|
|
275
|
+
return value;
|
|
276
|
+
}
|
|
277
|
+
setCheck(check) {
|
|
278
|
+
return this.clone({ [check.type]: check });
|
|
279
|
+
}
|
|
280
|
+
toOpenAPI() {
|
|
281
|
+
const baseSchema = this.getSchemaObject();
|
|
282
|
+
const schema = {
|
|
283
|
+
...baseSchema,
|
|
284
|
+
type: "string"
|
|
285
|
+
};
|
|
286
|
+
if (this.def.regex) {
|
|
287
|
+
schema.pattern = this.def.regex.regex.source;
|
|
288
|
+
}
|
|
289
|
+
if (this.def.format) {
|
|
290
|
+
schema.format = this.def.format.format;
|
|
291
|
+
}
|
|
292
|
+
if (this.def.min !== void 0) {
|
|
293
|
+
schema.minLength = this.def.min.val;
|
|
294
|
+
}
|
|
295
|
+
if (this.def.max !== void 0) {
|
|
296
|
+
schema.maxLength = this.def.max.val;
|
|
297
|
+
}
|
|
298
|
+
return schema;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Sets the minimum length of the string
|
|
302
|
+
*
|
|
303
|
+
* @param min The minimum length of the string
|
|
304
|
+
* @returns A clone of the schema with the minimum length set
|
|
305
|
+
*/
|
|
306
|
+
min(min, message) {
|
|
307
|
+
return this.setCheck({ type: "min", val: min, message });
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Sets the maximum length of the string
|
|
311
|
+
*
|
|
312
|
+
* @param max The maximum length of the string
|
|
313
|
+
* @returns A clone of the schema with the maximum length set
|
|
314
|
+
*/
|
|
315
|
+
max(max, message) {
|
|
316
|
+
return this.setCheck({ type: "max", val: max, message });
|
|
317
|
+
}
|
|
318
|
+
regex(regex, message) {
|
|
319
|
+
return this.setCheck({ type: "regex", regex, message });
|
|
320
|
+
}
|
|
321
|
+
startsWith(prefix, message) {
|
|
322
|
+
return this.setCheck({ type: "startsWith", prefix, message });
|
|
323
|
+
}
|
|
324
|
+
endsWith(suffix, message) {
|
|
325
|
+
return this.setCheck({ type: "endsWith", suffix, message });
|
|
326
|
+
}
|
|
327
|
+
format(format, message) {
|
|
328
|
+
return this.setCheck({ type: "format", format, message });
|
|
329
|
+
}
|
|
330
|
+
uri(message) {
|
|
331
|
+
return this.format("uri", message);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Deprecated because OpenAPI uses the term "uri"
|
|
335
|
+
* but this method exists for making migration from
|
|
336
|
+
* Zod easier.
|
|
337
|
+
*
|
|
338
|
+
* @deprecated Use {@link uri} instead
|
|
339
|
+
*/
|
|
340
|
+
url(message) {
|
|
341
|
+
return this.uri(message);
|
|
342
|
+
}
|
|
343
|
+
email(message) {
|
|
344
|
+
return this.format("email", message);
|
|
345
|
+
}
|
|
346
|
+
uuid(message) {
|
|
347
|
+
return this.format("uuid", message);
|
|
348
|
+
}
|
|
349
|
+
ipv4(message) {
|
|
350
|
+
return this.format("ipv4", message);
|
|
351
|
+
}
|
|
352
|
+
ipv6(message) {
|
|
353
|
+
return this.format("ipv6", message);
|
|
354
|
+
}
|
|
355
|
+
date(message) {
|
|
356
|
+
return this.format("date", message);
|
|
357
|
+
}
|
|
358
|
+
dateTime(message) {
|
|
359
|
+
return this.format("date-time", message);
|
|
360
|
+
}
|
|
361
|
+
password(message) {
|
|
362
|
+
return this.format("password", message);
|
|
363
|
+
}
|
|
364
|
+
byte(message) {
|
|
365
|
+
return this.format("byte", message);
|
|
366
|
+
}
|
|
367
|
+
binary(message) {
|
|
368
|
+
return this.format("binary", message);
|
|
369
|
+
}
|
|
370
|
+
hostname(message) {
|
|
371
|
+
return this.format("hostname", message);
|
|
372
|
+
}
|
|
373
|
+
parseSafe(json) {
|
|
374
|
+
return ParseContext.result((ctx) => {
|
|
375
|
+
if (typeof json !== "string") {
|
|
376
|
+
return ctx.addIssue("Expected string", []);
|
|
377
|
+
}
|
|
378
|
+
if (this.def.min !== void 0 && json.length < this.def.min.val) {
|
|
379
|
+
ctx.addIssue(this.def.min.message ?? `String must be at least ${this.def.min.val} characters`, []);
|
|
380
|
+
}
|
|
381
|
+
if (this.def.max !== void 0 && json.length > this.def.max.val) {
|
|
382
|
+
ctx.addIssue(this.def.max.message ?? `String must be at most ${this.def.max.val} characters`, []);
|
|
383
|
+
}
|
|
384
|
+
if (this.def.regex !== void 0 && !this.def.regex.regex.test(json)) {
|
|
385
|
+
ctx.addIssue(this.def.regex.message ?? `String must match ${this.def.regex.regex.source}`, []);
|
|
386
|
+
}
|
|
387
|
+
if (this.def.startsWith !== void 0 && !json.startsWith(this.def.startsWith.prefix)) {
|
|
388
|
+
ctx.addIssue(this.def.startsWith.message ?? `String must start with "${this.def.startsWith.prefix}"`, []);
|
|
389
|
+
}
|
|
390
|
+
if (this.def.endsWith !== void 0 && !json.endsWith(this.def.endsWith.suffix)) {
|
|
391
|
+
ctx.addIssue(this.def.endsWith.message ?? `String must end with "${this.def.endsWith.suffix}"`, []);
|
|
392
|
+
}
|
|
393
|
+
if (this.def.format !== void 0) {
|
|
394
|
+
switch (this.def.format.format) {
|
|
395
|
+
case "uuid":
|
|
396
|
+
if (!STRING_FORMAT_REGEXES.uuid.test(json)) {
|
|
397
|
+
ctx.addIssue(this.def.format.message ?? "Invalid UUID format", []);
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
400
|
+
case "email":
|
|
401
|
+
if (!STRING_FORMAT_REGEXES.email.test(json)) {
|
|
402
|
+
ctx.addIssue(this.def.format.message ?? "Invalid email format", []);
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
case "ipv4":
|
|
406
|
+
if (!STRING_FORMAT_REGEXES.ipv4.test(json)) {
|
|
407
|
+
ctx.addIssue(this.def.format.message ?? "Invalid IPv4 address", []);
|
|
408
|
+
}
|
|
409
|
+
break;
|
|
410
|
+
case "ipv6":
|
|
411
|
+
if (!STRING_FORMAT_REGEXES.ipv6.test(json)) {
|
|
412
|
+
ctx.addIssue(this.def.format.message ?? "Invalid IPv6 address", []);
|
|
413
|
+
}
|
|
414
|
+
break;
|
|
415
|
+
case "date":
|
|
416
|
+
if (!STRING_FORMAT_REGEXES.date.test(json)) {
|
|
417
|
+
ctx.addIssue(this.def.format.message ?? "Invalid date format", []);
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
case "date-time":
|
|
421
|
+
if (Number.isNaN(new Date(json).getTime())) {
|
|
422
|
+
ctx.addIssue(this.def.format.message ?? "Invalid date-time format", []);
|
|
423
|
+
}
|
|
424
|
+
break;
|
|
425
|
+
case "byte":
|
|
426
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(json) || json.length % 4 !== 0) {
|
|
427
|
+
ctx.addIssue(this.def.format.message ?? "Invalid base64 format", []);
|
|
428
|
+
}
|
|
429
|
+
break;
|
|
430
|
+
case "uri":
|
|
431
|
+
if (!STRING_FORMAT_REGEXES.uri.test(json)) {
|
|
432
|
+
ctx.addIssue(this.def.format.message ?? "Invalid URI format", []);
|
|
433
|
+
}
|
|
434
|
+
break;
|
|
435
|
+
case "hostname":
|
|
436
|
+
if (!STRING_FORMAT_REGEXES.hostname.test(json)) {
|
|
437
|
+
ctx.addIssue(this.def.format.message ?? "Invalid hostname format", []);
|
|
438
|
+
}
|
|
439
|
+
break;
|
|
440
|
+
case "binary":
|
|
441
|
+
break;
|
|
442
|
+
case "password":
|
|
443
|
+
break;
|
|
444
|
+
default:
|
|
445
|
+
this.def.format.format;
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return json;
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
parse(json) {
|
|
453
|
+
const result = this.parseSafe(json);
|
|
454
|
+
if (!result.success) {
|
|
455
|
+
throw new SchemaError(result.issues);
|
|
456
|
+
}
|
|
457
|
+
return result.result;
|
|
458
|
+
}
|
|
459
|
+
visit() {
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
var KNumber = class _KNumber extends BaseSchema {
|
|
463
|
+
static create = () => new _KNumber({});
|
|
464
|
+
serialize(value) {
|
|
465
|
+
return value;
|
|
466
|
+
}
|
|
467
|
+
setCheck(check) {
|
|
468
|
+
return this.clone({ [check.type]: check });
|
|
469
|
+
}
|
|
470
|
+
toOpenAPI() {
|
|
471
|
+
const baseSchema = this.getSchemaObject();
|
|
472
|
+
const schema = {
|
|
473
|
+
...baseSchema,
|
|
474
|
+
type: "number"
|
|
475
|
+
};
|
|
476
|
+
if (this.def.min !== void 0) {
|
|
477
|
+
schema.minimum = this.def.min.val;
|
|
478
|
+
}
|
|
479
|
+
if (this.def.max !== void 0) {
|
|
480
|
+
schema.maximum = this.def.max.val;
|
|
481
|
+
}
|
|
482
|
+
if (this.def.multipleOf !== void 0) {
|
|
483
|
+
schema.multipleOf = this.def.multipleOf.val;
|
|
484
|
+
}
|
|
485
|
+
if (this.def.integer) {
|
|
486
|
+
schema.type = "integer";
|
|
487
|
+
}
|
|
488
|
+
if (this.def.format) {
|
|
489
|
+
switch (this.def.format.format) {
|
|
490
|
+
case "float":
|
|
491
|
+
schema.format = "float";
|
|
492
|
+
schema.type = "number";
|
|
493
|
+
break;
|
|
494
|
+
case "double":
|
|
495
|
+
schema.format = "double";
|
|
496
|
+
schema.type = "number";
|
|
497
|
+
break;
|
|
498
|
+
case "int32":
|
|
499
|
+
schema.format = "int32";
|
|
500
|
+
schema.type = "integer";
|
|
501
|
+
break;
|
|
502
|
+
case "int64":
|
|
503
|
+
schema.format = "int64";
|
|
504
|
+
schema.type = "integer";
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (this.def.format) {
|
|
509
|
+
schema.format = this.def.format.format;
|
|
510
|
+
}
|
|
511
|
+
return schema;
|
|
512
|
+
}
|
|
513
|
+
min(min) {
|
|
514
|
+
return this.setCheck({ type: "min", val: min });
|
|
515
|
+
}
|
|
516
|
+
max(max) {
|
|
517
|
+
return this.setCheck({ type: "max", val: max });
|
|
518
|
+
}
|
|
519
|
+
integer() {
|
|
520
|
+
return this.setCheck({ type: "integer" });
|
|
521
|
+
}
|
|
522
|
+
multipleOf(multipleOf) {
|
|
523
|
+
if (multipleOf <= 0) {
|
|
524
|
+
throw new Error("multipleOf must be a positive number");
|
|
525
|
+
}
|
|
526
|
+
return this.setCheck({ type: "multipleOf", val: multipleOf });
|
|
527
|
+
}
|
|
528
|
+
float() {
|
|
529
|
+
return this.setCheck({ type: "format", format: "float" });
|
|
530
|
+
}
|
|
531
|
+
double() {
|
|
532
|
+
return this.setCheck({ type: "format", format: "double" });
|
|
533
|
+
}
|
|
534
|
+
int32() {
|
|
535
|
+
return this.setCheck({ type: "format", format: "int32" }).integer();
|
|
536
|
+
}
|
|
537
|
+
int64() {
|
|
538
|
+
return this.setCheck({ type: "format", format: "int64" }).integer();
|
|
539
|
+
}
|
|
540
|
+
parseSafe(json) {
|
|
541
|
+
return ParseContext.result((ctx) => {
|
|
542
|
+
if (typeof json !== "number") {
|
|
543
|
+
return ctx.addIssue("Expected number", []);
|
|
544
|
+
}
|
|
545
|
+
if (this.def.integer && !Number.isInteger(json)) {
|
|
546
|
+
ctx.addIssue(this.def.integer.message ?? "Expected integer", []);
|
|
547
|
+
}
|
|
548
|
+
if (this.def.min !== void 0 && json < this.def.min.val) {
|
|
549
|
+
ctx.addIssue(this.def.min.message ?? `Number must be greater than or equal to ${this.def.min.val}`, []);
|
|
550
|
+
}
|
|
551
|
+
if (this.def.max !== void 0 && json > this.def.max.val) {
|
|
552
|
+
ctx.addIssue(this.def.max.message ?? `Number must be less than or equal to ${this.def.max.val}`, []);
|
|
553
|
+
}
|
|
554
|
+
if (this.def.multipleOf !== void 0 && json % this.def.multipleOf.val !== 0) {
|
|
555
|
+
ctx.addIssue(this.def.multipleOf.message ?? `Number must be multiple of ${this.def.multipleOf.val}`, []);
|
|
556
|
+
}
|
|
557
|
+
return json;
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
parse(json) {
|
|
561
|
+
const result = this.parseSafe(json);
|
|
562
|
+
if (!result.success) {
|
|
563
|
+
throw new SchemaError(result.issues);
|
|
564
|
+
}
|
|
565
|
+
return result.result;
|
|
566
|
+
}
|
|
567
|
+
visit() {
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
var KBoolean = class _KBoolean extends BaseSchema {
|
|
571
|
+
static create = () => new _KBoolean({});
|
|
572
|
+
serialize(value) {
|
|
573
|
+
return value;
|
|
574
|
+
}
|
|
575
|
+
toOpenAPI() {
|
|
576
|
+
const baseSchema = this.getSchemaObject();
|
|
577
|
+
return {
|
|
578
|
+
...baseSchema,
|
|
579
|
+
type: "boolean"
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
parseSafe(json) {
|
|
583
|
+
return ParseContext.result((ctx) => {
|
|
584
|
+
if (typeof json !== "boolean") {
|
|
585
|
+
return ctx.addIssue("Expected boolean", []);
|
|
586
|
+
}
|
|
587
|
+
return json;
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
parse(json) {
|
|
591
|
+
const result = this.parseSafe(json);
|
|
592
|
+
if (!result.success) {
|
|
593
|
+
throw new SchemaError(result.issues);
|
|
594
|
+
}
|
|
595
|
+
return result.result;
|
|
596
|
+
}
|
|
597
|
+
visit() {
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
var KArray = class _KArray extends BaseSchema {
|
|
601
|
+
static create = (items) => new _KArray({ items });
|
|
602
|
+
serialize(value) {
|
|
603
|
+
return value.map((item) => this.def.items.serialize(item));
|
|
604
|
+
}
|
|
605
|
+
setCheck(check) {
|
|
606
|
+
return this.clone({ [check.type]: check });
|
|
607
|
+
}
|
|
608
|
+
toOpenAPI() {
|
|
609
|
+
const baseSchema = this.getSchemaObject();
|
|
610
|
+
return {
|
|
611
|
+
...baseSchema,
|
|
612
|
+
type: "array",
|
|
613
|
+
items: this.def.items.toOpenAPI(),
|
|
614
|
+
...this.def.minItems !== void 0 ? { minItems: this.def.minItems.val } : {},
|
|
615
|
+
...this.def.maxItems !== void 0 ? { maxItems: this.def.maxItems.val } : {},
|
|
616
|
+
...this.def.uniqueItems !== void 0 ? { uniqueItems: this.def.uniqueItems.val } : {}
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
min(minItems) {
|
|
620
|
+
return this.setCheck({ type: "minItems", val: minItems });
|
|
621
|
+
}
|
|
622
|
+
max(maxItems) {
|
|
623
|
+
return this.setCheck({ type: "maxItems", val: maxItems });
|
|
624
|
+
}
|
|
625
|
+
unique() {
|
|
626
|
+
return this.setCheck({ type: "uniqueItems", val: true });
|
|
627
|
+
}
|
|
628
|
+
notUnique() {
|
|
629
|
+
return this.setCheck({ type: "uniqueItems", val: false });
|
|
630
|
+
}
|
|
631
|
+
parseSafe(json) {
|
|
632
|
+
return ParseContext.result((ctx) => {
|
|
633
|
+
if (!Array.isArray(json)) {
|
|
634
|
+
return ctx.addIssue("Expected array", []);
|
|
635
|
+
}
|
|
636
|
+
if (this.def.minItems !== void 0 && json.length < this.def.minItems.val) {
|
|
637
|
+
ctx.addIssue(this.def.minItems.message ?? `Array must have at least ${this.def.minItems.val} items`, []);
|
|
638
|
+
}
|
|
639
|
+
if (this.def.maxItems !== void 0 && json.length > this.def.maxItems.val) {
|
|
640
|
+
ctx.addIssue(this.def.maxItems.message ?? `Array must have at most ${this.def.maxItems.val} items`, []);
|
|
641
|
+
}
|
|
642
|
+
if (this.def.uniqueItems?.val === true && new Set(json).size !== json.length) {
|
|
643
|
+
ctx.addIssue(this.def.uniqueItems.message ?? "Array items must be unique", []);
|
|
644
|
+
}
|
|
645
|
+
const items = [];
|
|
646
|
+
for (let i = 0; i < json.length; i++) {
|
|
647
|
+
const item = json[i];
|
|
648
|
+
const result = this.def.items.parseSafe(item);
|
|
649
|
+
if (!result.success) {
|
|
650
|
+
ctx.addIssues(result.issues, [i.toString()]);
|
|
651
|
+
} else {
|
|
652
|
+
items.push(result.result);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
return items;
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
parse(json) {
|
|
659
|
+
const result = this.parseSafe(json);
|
|
660
|
+
if (!result.success) {
|
|
661
|
+
throw new SchemaError(result.issues);
|
|
662
|
+
}
|
|
663
|
+
return result.result;
|
|
664
|
+
}
|
|
665
|
+
visit(visitor) {
|
|
666
|
+
const child = this.def.items;
|
|
667
|
+
visitor(child);
|
|
668
|
+
child.visit(visitor);
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
var KNull = class _KNull extends BaseSchema {
|
|
672
|
+
static create = () => new _KNull({});
|
|
673
|
+
serialize(value) {
|
|
674
|
+
return value;
|
|
675
|
+
}
|
|
676
|
+
toOpenAPI() {
|
|
677
|
+
const baseSchema = this.getSchemaObject();
|
|
678
|
+
return {
|
|
679
|
+
...baseSchema,
|
|
680
|
+
type: "null"
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
parseSafe(json) {
|
|
684
|
+
return ParseContext.result((ctx) => {
|
|
685
|
+
if (json !== null) {
|
|
686
|
+
return ctx.addIssue("Expected null", []);
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
parse(json) {
|
|
692
|
+
const result = this.parseSafe(json);
|
|
693
|
+
if (!result.success) {
|
|
694
|
+
throw new SchemaError(result.issues);
|
|
695
|
+
}
|
|
696
|
+
return result.result;
|
|
697
|
+
}
|
|
698
|
+
visit() {
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
var KObject = class _KObject extends BaseSchema {
|
|
702
|
+
static create = (shape) => new _KObject({ shape });
|
|
703
|
+
serialize(value) {
|
|
704
|
+
const result = {};
|
|
705
|
+
for (const key in this.def.shape) {
|
|
706
|
+
if (Object.prototype.hasOwnProperty.call(this.def.shape, key)) {
|
|
707
|
+
const fieldValue = value[key];
|
|
708
|
+
if (fieldValue === void 0) {
|
|
709
|
+
throw new Error(`Missing required property: ${key}`);
|
|
710
|
+
}
|
|
711
|
+
result[key] = this.def.shape[key].serialize(fieldValue);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return result;
|
|
715
|
+
}
|
|
716
|
+
toOpenAPI() {
|
|
717
|
+
const baseSchema = this.getSchemaObject();
|
|
718
|
+
return {
|
|
719
|
+
...baseSchema,
|
|
720
|
+
type: "object",
|
|
721
|
+
properties: Object.fromEntries(
|
|
722
|
+
Object.entries(this.def.shape).map((entry) => {
|
|
723
|
+
const [key, value] = entry;
|
|
724
|
+
return [key, value.toOpenAPI()];
|
|
725
|
+
})
|
|
726
|
+
),
|
|
727
|
+
required: Object.keys(this.def.shape)
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
parseSafe(json) {
|
|
731
|
+
return ParseContext.result((ctx) => {
|
|
732
|
+
if (typeof json !== "object" || json === null || Array.isArray(json)) {
|
|
733
|
+
return ctx.addIssue(`Expected object, got ${typeof json}`, []);
|
|
734
|
+
}
|
|
735
|
+
const result = {};
|
|
736
|
+
for (const key in this.def.shape) {
|
|
737
|
+
if (Object.prototype.hasOwnProperty.call(this.def.shape, key)) {
|
|
738
|
+
const value = json[key];
|
|
739
|
+
if (value === void 0) {
|
|
740
|
+
return ctx.addIssue(`Missing required property: ${key}`, [key]);
|
|
741
|
+
}
|
|
742
|
+
const parseResult = this.def.shape[key].parseSafe(value);
|
|
743
|
+
if (!parseResult.success) {
|
|
744
|
+
return ctx.addIssues(parseResult.issues, [key]);
|
|
745
|
+
}
|
|
746
|
+
result[key] = parseResult.result;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return result;
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
parse(json) {
|
|
753
|
+
const result = this.parseSafe(json);
|
|
754
|
+
if (!result.success) {
|
|
755
|
+
throw new SchemaError(result.issues);
|
|
756
|
+
}
|
|
757
|
+
return result.result;
|
|
758
|
+
}
|
|
759
|
+
get shape() {
|
|
760
|
+
return this.def.shape;
|
|
761
|
+
}
|
|
762
|
+
visit(visitor) {
|
|
763
|
+
for (const child of Object.values(this.def.shape)) {
|
|
764
|
+
visitor(child);
|
|
765
|
+
child.visit(visitor);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
};
|
|
769
|
+
var KObjectFromURLSearchParams = class _KObjectFromURLSearchParams extends KObject {
|
|
770
|
+
static create = (shape) => new _KObjectFromURLSearchParams({ shape });
|
|
771
|
+
serialize(value) {
|
|
772
|
+
return super.serialize(value);
|
|
773
|
+
}
|
|
774
|
+
toOpenAPI() {
|
|
775
|
+
return super.toOpenAPI();
|
|
776
|
+
}
|
|
777
|
+
parseSafe(json) {
|
|
778
|
+
return ParseContext.result((ctx) => {
|
|
779
|
+
if (!(json instanceof URLSearchParams)) {
|
|
780
|
+
return ctx.addIssue(`Expected URLSearchParams, got ${typeof json}`, []);
|
|
781
|
+
}
|
|
782
|
+
const result = {};
|
|
783
|
+
for (const key in this.def.shape) {
|
|
784
|
+
if (Object.prototype.hasOwnProperty.call(this.def.shape, key)) {
|
|
785
|
+
const value = json.get(key);
|
|
786
|
+
if (value === null) {
|
|
787
|
+
return ctx.addIssue(`Missing required property: ${key}`, [key]);
|
|
788
|
+
}
|
|
789
|
+
const parseResult = this.def.shape[key].parseSafe(value);
|
|
790
|
+
if (!parseResult.success) {
|
|
791
|
+
return ctx.addIssues(parseResult.issues, [key]);
|
|
792
|
+
}
|
|
793
|
+
result[key] = parseResult.result;
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return result;
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
var KRef = class _KRef extends BaseSchema {
|
|
801
|
+
static create = (name, shape) => new _KRef({ name, shape });
|
|
802
|
+
serialize(value) {
|
|
803
|
+
const result = {};
|
|
804
|
+
for (const key in this.def.shape) {
|
|
805
|
+
if (Object.prototype.hasOwnProperty.call(this.def.shape, key)) {
|
|
806
|
+
const fieldValue = value[key];
|
|
807
|
+
if (fieldValue === void 0) {
|
|
808
|
+
throw new Error(`Missing required property: ${key}`);
|
|
809
|
+
}
|
|
810
|
+
result[key] = this.def.shape[key].serialize(fieldValue);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
visit(visitor) {
|
|
816
|
+
for (const child of Object.values(this.def.shape)) {
|
|
817
|
+
visitor(child);
|
|
818
|
+
child.visit(visitor);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
example() {
|
|
822
|
+
throw new Error("Cannot set an example on a KRef");
|
|
823
|
+
}
|
|
824
|
+
toOpenAPI() {
|
|
825
|
+
return {
|
|
826
|
+
$ref: `#/components/schemas/${this.def.name}`,
|
|
827
|
+
...this.def.description ? { description: this.def.description } : {},
|
|
828
|
+
...this.def.summary ? { summary: this.def.summary } : {}
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
parseSafe(json) {
|
|
832
|
+
return ParseContext.result((ctx) => {
|
|
833
|
+
if (typeof json !== "object" || json === null || Array.isArray(json)) {
|
|
834
|
+
return ctx.addIssue(`Expected object, got ${typeof json}`, []);
|
|
835
|
+
}
|
|
836
|
+
const result = {};
|
|
837
|
+
for (const key in this.def.shape) {
|
|
838
|
+
if (Object.prototype.hasOwnProperty.call(this.def.shape, key)) {
|
|
839
|
+
const value = json[key];
|
|
840
|
+
if (value === void 0) {
|
|
841
|
+
return ctx.addIssue(`Missing required property: ${key}`, [key]);
|
|
842
|
+
}
|
|
843
|
+
const parseResult = this.def.shape[key].parseSafe(value);
|
|
844
|
+
if (!parseResult.success) {
|
|
845
|
+
return ctx.addIssues(parseResult.issues, [key]);
|
|
846
|
+
}
|
|
847
|
+
result[key] = parseResult.result;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
return result;
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
parse(json) {
|
|
854
|
+
const result = this.parseSafe(json);
|
|
855
|
+
if (!result.success) {
|
|
856
|
+
throw new SchemaError(result.issues);
|
|
857
|
+
}
|
|
858
|
+
return result.result;
|
|
859
|
+
}
|
|
860
|
+
summary(summary) {
|
|
861
|
+
if (summary === void 0) {
|
|
862
|
+
return this.def.summary;
|
|
863
|
+
}
|
|
864
|
+
return this.clone({ summary });
|
|
865
|
+
}
|
|
866
|
+
get shape() {
|
|
867
|
+
return this.def.shape;
|
|
868
|
+
}
|
|
869
|
+
get name() {
|
|
870
|
+
return this.def.name;
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
var KScalar = class _KScalar extends BaseSchema {
|
|
874
|
+
static create = (options) => new _KScalar(options);
|
|
875
|
+
constructor(def) {
|
|
876
|
+
super({
|
|
877
|
+
...def,
|
|
878
|
+
example: def.schema.example(),
|
|
879
|
+
description: def.schema.description()
|
|
880
|
+
});
|
|
881
|
+
}
|
|
882
|
+
serialize(value) {
|
|
883
|
+
return this.def.toClient(value);
|
|
884
|
+
}
|
|
885
|
+
toOpenAPI() {
|
|
886
|
+
return {
|
|
887
|
+
...this.def.schema.toOpenAPI(),
|
|
888
|
+
...this.def.description ? { description: this.def.description } : {},
|
|
889
|
+
...this.def.example ? { example: this.def.example } : {}
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
parseSafe(json) {
|
|
893
|
+
return ParseContext.result((ctx) => {
|
|
894
|
+
const jsonValue = this.def.schema.parseSafe(json);
|
|
895
|
+
if (!jsonValue.success) {
|
|
896
|
+
return ctx.addIssues(jsonValue.issues, []);
|
|
897
|
+
}
|
|
898
|
+
try {
|
|
899
|
+
return this.def.toServer(jsonValue.result);
|
|
900
|
+
} catch (error) {
|
|
901
|
+
return ctx.addIssue(error instanceof Error ? error.message : "Conversion failed", []);
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
parse(json) {
|
|
906
|
+
const result = this.parseSafe(json);
|
|
907
|
+
if (!result.success) {
|
|
908
|
+
throw new SchemaError(result.issues);
|
|
909
|
+
}
|
|
910
|
+
return result.result;
|
|
911
|
+
}
|
|
912
|
+
visit(visitor) {
|
|
913
|
+
const child = this.def.schema;
|
|
914
|
+
visitor(child);
|
|
915
|
+
child.visit(visitor);
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
var KUnion = class _KUnion extends BaseSchema {
|
|
919
|
+
static create = (items) => new _KUnion({ items });
|
|
920
|
+
static enum = (values) => k.union(values.map((v) => k.literal(v)));
|
|
921
|
+
serialize(value) {
|
|
922
|
+
for (const option of this.def.items) {
|
|
923
|
+
try {
|
|
924
|
+
return option.serialize(value);
|
|
925
|
+
} catch {
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
throw new Error("Value does not match any union option for serialization");
|
|
929
|
+
}
|
|
930
|
+
toOpenAPI() {
|
|
931
|
+
const baseSchema = this.getSchemaObject();
|
|
932
|
+
return {
|
|
933
|
+
...baseSchema,
|
|
934
|
+
oneOf: this.def.items.map((option) => option.toOpenAPI())
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
parseSafe(json) {
|
|
938
|
+
let lastIssues;
|
|
939
|
+
for (const option of this.def.items) {
|
|
940
|
+
const result = option.parseSafe(json);
|
|
941
|
+
if (result.success) {
|
|
942
|
+
return { success: true, result: result.result };
|
|
943
|
+
} else {
|
|
944
|
+
lastIssues = result.issues;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
return { success: false, issues: lastIssues ?? /* @__PURE__ */ new Set([{ message: "No union option matched", path: [] }]) };
|
|
948
|
+
}
|
|
949
|
+
parse(json) {
|
|
950
|
+
const result = this.parseSafe(json);
|
|
951
|
+
if (!result.success) {
|
|
952
|
+
throw new SchemaError(result.issues);
|
|
953
|
+
}
|
|
954
|
+
return result.result;
|
|
955
|
+
}
|
|
956
|
+
visit(visitor) {
|
|
957
|
+
for (const child of this.def.items) {
|
|
958
|
+
visitor(child);
|
|
959
|
+
child.visit(visitor);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
var KLiteral = class _KLiteral extends BaseSchema {
|
|
964
|
+
parse(json) {
|
|
965
|
+
const result = this.parseSafe(json);
|
|
966
|
+
if (!result.success) {
|
|
967
|
+
throw new SchemaError(result.issues);
|
|
968
|
+
}
|
|
969
|
+
return result.result;
|
|
970
|
+
}
|
|
971
|
+
static create = (value) => new _KLiteral({ value });
|
|
972
|
+
serialize(value) {
|
|
973
|
+
return value;
|
|
974
|
+
}
|
|
975
|
+
toOpenAPI() {
|
|
976
|
+
const baseSchema = this.getSchemaObject();
|
|
977
|
+
const type = typeof this.def.value;
|
|
978
|
+
return {
|
|
979
|
+
...baseSchema,
|
|
980
|
+
type,
|
|
981
|
+
enum: [this.def.value]
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
parseSafe(json) {
|
|
985
|
+
return ParseContext.result((ctx) => {
|
|
986
|
+
if (json !== this.def.value) {
|
|
987
|
+
return ctx.addIssue(`Expected ${this.def.value}`, []);
|
|
988
|
+
}
|
|
989
|
+
return this.def.value;
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
visit() {
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
var KNativeEnum = class _KNativeEnum extends BaseSchema {
|
|
996
|
+
static create = (enumObject) => new _KNativeEnum({ enum: enumObject });
|
|
997
|
+
serialize(value) {
|
|
998
|
+
return value;
|
|
999
|
+
}
|
|
1000
|
+
toOpenAPI() {
|
|
1001
|
+
const baseSchema = this.getSchemaObject();
|
|
1002
|
+
const actualValues = Object.keys(this.def.enum).filter((key) => Number.isNaN(Number(key))).map((key) => this.def.enum[key]);
|
|
1003
|
+
const uniqueValues = [...new Set(actualValues)];
|
|
1004
|
+
const type = typeof uniqueValues[0] === "number" ? "number" : "string";
|
|
1005
|
+
return {
|
|
1006
|
+
...baseSchema,
|
|
1007
|
+
type,
|
|
1008
|
+
enum: uniqueValues
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
parseSafe(json) {
|
|
1012
|
+
return ParseContext.result((ctx) => {
|
|
1013
|
+
const actualValues = Object.keys(this.def.enum).filter((key) => Number.isNaN(Number(key))).map((key) => this.def.enum[key]);
|
|
1014
|
+
if (!actualValues.includes(json)) {
|
|
1015
|
+
return ctx.addIssue(`Expected one of: ${actualValues.join(", ")}`, []);
|
|
1016
|
+
}
|
|
1017
|
+
return json;
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
parse(json) {
|
|
1021
|
+
const result = this.parseSafe(json);
|
|
1022
|
+
if (!result.success) {
|
|
1023
|
+
throw new SchemaError(result.issues);
|
|
1024
|
+
}
|
|
1025
|
+
return result.result;
|
|
1026
|
+
}
|
|
1027
|
+
visit() {
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
var KRecord = class _KRecord extends BaseSchema {
|
|
1031
|
+
static create = (keys, values) => new _KRecord({ keys, values });
|
|
1032
|
+
serialize(value) {
|
|
1033
|
+
const result = {};
|
|
1034
|
+
for (const key in value) {
|
|
1035
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
1036
|
+
const keySerialize = this.def.keys.serialize(key);
|
|
1037
|
+
const valueSerialize = this.def.values.serialize(value[key]);
|
|
1038
|
+
result[keySerialize] = valueSerialize;
|
|
1039
|
+
}
|
|
1040
|
+
return result;
|
|
1041
|
+
}
|
|
1042
|
+
toOpenAPI() {
|
|
1043
|
+
const baseSchema = this.getSchemaObject();
|
|
1044
|
+
return {
|
|
1045
|
+
...baseSchema,
|
|
1046
|
+
type: "object",
|
|
1047
|
+
propertyNames: this.def.keys.toOpenAPI(),
|
|
1048
|
+
additionalProperties: this.def.values.toOpenAPI()
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
parseSafe(json) {
|
|
1052
|
+
return ParseContext.result((ctx) => {
|
|
1053
|
+
if (typeof json !== "object" || json === null || Array.isArray(json)) {
|
|
1054
|
+
return ctx.addIssue("Expected object", []);
|
|
1055
|
+
}
|
|
1056
|
+
const result = {};
|
|
1057
|
+
for (const key in json) {
|
|
1058
|
+
if (!Object.prototype.hasOwnProperty.call(json, key)) continue;
|
|
1059
|
+
const keyParse = this.def.keys.parseSafe(key);
|
|
1060
|
+
if (!keyParse.success) {
|
|
1061
|
+
return ctx.addIssues(keyParse.issues, [key]);
|
|
1062
|
+
}
|
|
1063
|
+
const value = json[keyParse.result];
|
|
1064
|
+
const valueParse = this.def.values.parseSafe(value);
|
|
1065
|
+
if (!valueParse.success) {
|
|
1066
|
+
return ctx.addIssues(valueParse.issues, [key]);
|
|
1067
|
+
}
|
|
1068
|
+
result[keyParse.result] = valueParse.result;
|
|
1069
|
+
}
|
|
1070
|
+
return result;
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
parse(json) {
|
|
1074
|
+
const result = this.parseSafe(json);
|
|
1075
|
+
if (!result.success) {
|
|
1076
|
+
throw new SchemaError(result.issues);
|
|
1077
|
+
}
|
|
1078
|
+
return result.result;
|
|
1079
|
+
}
|
|
1080
|
+
visit(visitor) {
|
|
1081
|
+
visitor(this.def.keys);
|
|
1082
|
+
visitor(this.def.values);
|
|
1083
|
+
}
|
|
1084
|
+
};
|
|
1085
|
+
var KLazy = class _KLazy extends BaseSchema {
|
|
1086
|
+
schema;
|
|
1087
|
+
static create = (getter) => new _KLazy({ getter });
|
|
1088
|
+
getSchema() {
|
|
1089
|
+
if (!this.schema) {
|
|
1090
|
+
this.schema = this.def.getter();
|
|
1091
|
+
}
|
|
1092
|
+
return this.schema;
|
|
1093
|
+
}
|
|
1094
|
+
serialize(value) {
|
|
1095
|
+
return this.getSchema().serialize(value);
|
|
1096
|
+
}
|
|
1097
|
+
toOpenAPI() {
|
|
1098
|
+
return this.getSchema().toOpenAPI();
|
|
1099
|
+
}
|
|
1100
|
+
parseSafe(json) {
|
|
1101
|
+
return this.getSchema().parseSafe(json);
|
|
1102
|
+
}
|
|
1103
|
+
parse(json) {
|
|
1104
|
+
return this.getSchema().parse(json);
|
|
1105
|
+
}
|
|
1106
|
+
visit(visitor) {
|
|
1107
|
+
const schema = this.getSchema();
|
|
1108
|
+
visitor(schema);
|
|
1109
|
+
schema.visit(visitor);
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
var k = {
|
|
1113
|
+
string: KString.create,
|
|
1114
|
+
number: KNumber.create,
|
|
1115
|
+
boolean: KBoolean.create,
|
|
1116
|
+
array: KArray.create,
|
|
1117
|
+
null: KNull.create,
|
|
1118
|
+
ref: KRef.create,
|
|
1119
|
+
record: KRecord.create,
|
|
1120
|
+
object: KObject.create,
|
|
1121
|
+
scalar: KScalar.create,
|
|
1122
|
+
literal: KLiteral.create,
|
|
1123
|
+
enum: KUnion.enum,
|
|
1124
|
+
nativeEnum: KNativeEnum.create,
|
|
1125
|
+
union: KUnion.create,
|
|
1126
|
+
lazy: KLazy.create,
|
|
1127
|
+
/**
|
|
1128
|
+
* Schema for any valid JSON value
|
|
1129
|
+
*/
|
|
1130
|
+
json: () => {
|
|
1131
|
+
const jsonSchema = k.lazy(
|
|
1132
|
+
() => k.union([k.string(), k.number(), k.boolean(), k.null(), k.array(jsonSchema), k.record(k.string(), jsonSchema)])
|
|
1133
|
+
);
|
|
1134
|
+
return jsonSchema;
|
|
1135
|
+
},
|
|
1136
|
+
/**
|
|
1137
|
+
* @internal
|
|
1138
|
+
* @experimental
|
|
1139
|
+
*/
|
|
1140
|
+
objectFromURLSearchParams: KObjectFromURLSearchParams.create
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
// src/stream/stream.ts
|
|
1144
|
+
var KaitoSSEResponse = class {
|
|
1145
|
+
events;
|
|
1146
|
+
constructor(events) {
|
|
1147
|
+
this.events = events;
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
function sseEventToString(event) {
|
|
1151
|
+
const lines = [];
|
|
1152
|
+
if (event.event) {
|
|
1153
|
+
lines.push(`event:${event.event}`);
|
|
1154
|
+
}
|
|
1155
|
+
if (event.id) {
|
|
1156
|
+
lines.push(`id:${event.id}`);
|
|
1157
|
+
}
|
|
1158
|
+
if (event.retry) {
|
|
1159
|
+
lines.push(`retry:${event.retry}`);
|
|
1160
|
+
}
|
|
1161
|
+
if (event.data !== void 0) {
|
|
1162
|
+
lines.push(`data:${JSON.stringify(event.data)}`);
|
|
1163
|
+
}
|
|
1164
|
+
return lines.join("\n");
|
|
1165
|
+
}
|
|
1166
|
+
|
|
142
1167
|
// src/util.ts
|
|
143
1168
|
var isNodeLikeDev = typeof process !== "undefined" && typeof process.env !== "undefined" && process.env.NODE_ENV === "development";
|
|
144
1169
|
|
|
145
1170
|
// src/router/router.ts
|
|
146
1171
|
var Router = class _Router {
|
|
147
|
-
state;
|
|
148
|
-
static create = (config) => new _Router({
|
|
149
|
-
through: async (context) => context,
|
|
150
|
-
routes: /* @__PURE__ */ new Set(),
|
|
151
|
-
config
|
|
152
|
-
});
|
|
1172
|
+
#state;
|
|
1173
|
+
static create = (config = {}) => new _Router({ through: (context) => context, routes: /* @__PURE__ */ new Set(), config });
|
|
153
1174
|
constructor(state) {
|
|
154
|
-
this
|
|
1175
|
+
this.#state = state;
|
|
155
1176
|
}
|
|
156
1177
|
get routes() {
|
|
157
|
-
return this
|
|
1178
|
+
return this.#state.routes;
|
|
158
1179
|
}
|
|
159
1180
|
add = (method, path, route) => {
|
|
160
1181
|
const merged = {
|
|
161
1182
|
...typeof route === "object" ? route : { run: route },
|
|
162
1183
|
method,
|
|
163
1184
|
path,
|
|
164
|
-
|
|
1185
|
+
router: this
|
|
165
1186
|
};
|
|
166
1187
|
return new _Router({
|
|
167
|
-
...this
|
|
168
|
-
routes: /* @__PURE__ */ new Set([...this
|
|
1188
|
+
...this.#state,
|
|
1189
|
+
routes: /* @__PURE__ */ new Set([...this.#state.routes, merged])
|
|
169
1190
|
});
|
|
170
1191
|
};
|
|
1192
|
+
params = () => this;
|
|
171
1193
|
merge = (pathPrefix, other) => {
|
|
172
|
-
const newRoutes = [...other
|
|
1194
|
+
const newRoutes = [...other.#state.routes].map((route) => ({
|
|
173
1195
|
...route,
|
|
174
|
-
|
|
1196
|
+
// handle pathPrefix = / & route.path = / case causing //
|
|
1197
|
+
// we intentionally are replacing on the joining path and not the pathPrefix, in case of
|
|
1198
|
+
// /named -> merged to -> / causing /named/ not /named
|
|
1199
|
+
path: `${pathPrefix}${route.path === "/" ? "" : route.path}`
|
|
175
1200
|
}));
|
|
176
1201
|
return new _Router({
|
|
177
|
-
...this
|
|
178
|
-
routes: /* @__PURE__ */ new Set([...this
|
|
1202
|
+
...this.#state,
|
|
1203
|
+
routes: /* @__PURE__ */ new Set([...this.#state.routes, ...newRoutes])
|
|
179
1204
|
});
|
|
180
1205
|
};
|
|
181
1206
|
static getFindRoute = (routes) => (method, path) => {
|
|
@@ -203,52 +1228,60 @@ var Router = class _Router {
|
|
|
203
1228
|
}
|
|
204
1229
|
return {};
|
|
205
1230
|
};
|
|
206
|
-
static buildQuerySchema = (schema) => {
|
|
207
|
-
const keys = Object.keys(schema);
|
|
208
|
-
return import_zod.z.instanceof(URLSearchParams).transform((params) => {
|
|
209
|
-
const result = {};
|
|
210
|
-
for (const key of keys) {
|
|
211
|
-
result[key] = params.get(key);
|
|
212
|
-
}
|
|
213
|
-
return result;
|
|
214
|
-
}).pipe(import_zod.z.object(schema));
|
|
215
|
-
};
|
|
216
1231
|
serve = () => {
|
|
217
1232
|
const methodToRoutesMap = /* @__PURE__ */ new Map();
|
|
218
|
-
for (const route of this
|
|
1233
|
+
for (const route of this.#state.routes) {
|
|
219
1234
|
if (!methodToRoutesMap.has(route.method)) {
|
|
220
1235
|
methodToRoutesMap.set(route.method, /* @__PURE__ */ new Map());
|
|
221
1236
|
}
|
|
222
1237
|
methodToRoutesMap.get(route.method).set(route.path, {
|
|
223
1238
|
...route,
|
|
224
|
-
fastQuerySchema: route.query ?
|
|
1239
|
+
fastQuerySchema: route.query ? k.objectFromURLSearchParams(route.query) : void 0
|
|
225
1240
|
});
|
|
226
1241
|
}
|
|
227
1242
|
const findRoute = _Router.getFindRoute(methodToRoutesMap);
|
|
228
|
-
const handle = async (req) => {
|
|
1243
|
+
const handle = async (req, ...args) => {
|
|
229
1244
|
const url = new URL(req.url);
|
|
230
1245
|
const method = req.method;
|
|
231
|
-
const { route, params } = findRoute(method, url.pathname);
|
|
1246
|
+
const { route, params: rawParams } = findRoute(method, url.pathname);
|
|
232
1247
|
if (!route) {
|
|
233
|
-
|
|
234
|
-
success: false,
|
|
235
|
-
data: null,
|
|
236
|
-
message: `Cannot ${method} ${url.pathname}`
|
|
237
|
-
};
|
|
238
|
-
return Response.json(body, { status: 404 });
|
|
1248
|
+
return Response.json({ message: `Cannot ${method} ${url.pathname}` }, { status: 404 });
|
|
239
1249
|
}
|
|
240
1250
|
const request = new KaitoRequest(url, req);
|
|
241
1251
|
const head = new KaitoHead();
|
|
242
1252
|
try {
|
|
243
|
-
const body = route.body ? await route.body.
|
|
244
|
-
const query = route.fastQuerySchema ?
|
|
245
|
-
const ctx = await route.
|
|
1253
|
+
const body = route.body ? await route.body.parse(await req.json()) : void 0;
|
|
1254
|
+
const query = route.fastQuerySchema ? route.fastQuerySchema.parse(url.searchParams) : {};
|
|
1255
|
+
const ctx = await route.router.#state.through(
|
|
1256
|
+
await this.#state.config.getContext?.(request, head, ...args) ?? null,
|
|
1257
|
+
rawParams
|
|
1258
|
+
);
|
|
246
1259
|
const result = await route.run({
|
|
247
1260
|
ctx,
|
|
248
1261
|
body,
|
|
249
1262
|
query,
|
|
250
|
-
params
|
|
1263
|
+
params: rawParams
|
|
251
1264
|
});
|
|
1265
|
+
if (result instanceof KaitoSSEResponse) {
|
|
1266
|
+
const body2 = route.openapi?.body;
|
|
1267
|
+
const schema = body2 && "schema" in body2 ? body2.schema : void 0;
|
|
1268
|
+
const stringStream = result.events.pipeThrough(
|
|
1269
|
+
new TransformStream({
|
|
1270
|
+
transform(event, controller) {
|
|
1271
|
+
const serialized = schema ? { ...event, data: event.data !== void 0 ? schema.serialize(event.data) : void 0 } : event;
|
|
1272
|
+
controller.enqueue(sseEventToString(serialized) + "\n\n");
|
|
1273
|
+
}
|
|
1274
|
+
})
|
|
1275
|
+
);
|
|
1276
|
+
const sseHeaders = new Headers(head.touched ? head.headers : void 0);
|
|
1277
|
+
sseHeaders.set("Content-Type", "text/event-stream");
|
|
1278
|
+
sseHeaders.set("Cache-Control", "no-cache");
|
|
1279
|
+
sseHeaders.set("Connection", "keep-alive");
|
|
1280
|
+
return new Response(stringStream, {
|
|
1281
|
+
status: head.status(),
|
|
1282
|
+
headers: sseHeaders
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
252
1285
|
if (result instanceof Response) {
|
|
253
1286
|
if (isNodeLikeDev) {
|
|
254
1287
|
if (head.touched) {
|
|
@@ -263,50 +1296,46 @@ var Router = class _Router {
|
|
|
263
1296
|
}
|
|
264
1297
|
return result;
|
|
265
1298
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
1299
|
+
if (route.openapi && "schema" in route.openapi.body && route.openapi.body.schema) {
|
|
1300
|
+
const parsed = route.openapi.body.schema.serialize(result);
|
|
1301
|
+
return head.toResponse(parsed);
|
|
1302
|
+
}
|
|
1303
|
+
if (result === void 0) {
|
|
1304
|
+
return head.toResponse(null);
|
|
1305
|
+
}
|
|
1306
|
+
return head.toResponse(result);
|
|
270
1307
|
} catch (e) {
|
|
271
1308
|
const error = WrappedError.maybe(e);
|
|
272
1309
|
if (error instanceof KaitoError) {
|
|
273
1310
|
return head.status(error.status).toResponse({
|
|
274
|
-
success: false,
|
|
275
|
-
data: null,
|
|
276
1311
|
message: error.message
|
|
277
1312
|
});
|
|
278
1313
|
}
|
|
279
|
-
if (!this
|
|
1314
|
+
if (!this.#state.config.onError) {
|
|
280
1315
|
return head.status(500).toResponse({
|
|
281
|
-
success: false,
|
|
282
|
-
data: null,
|
|
283
1316
|
message: "Internal Server Error"
|
|
284
1317
|
});
|
|
285
1318
|
}
|
|
286
1319
|
try {
|
|
287
|
-
const { status, message } = await this
|
|
1320
|
+
const { status, message } = await this.#state.config.onError(error, request);
|
|
288
1321
|
return head.status(status).toResponse({
|
|
289
|
-
success: false,
|
|
290
|
-
data: null,
|
|
291
1322
|
message
|
|
292
1323
|
});
|
|
293
1324
|
} catch (e2) {
|
|
294
|
-
console.error("
|
|
1325
|
+
console.error("[Kaito] Failed to handle error inside `.onError()`, returning 500 and Internal Server Error");
|
|
295
1326
|
console.error(e2);
|
|
296
1327
|
return head.status(500).toResponse({
|
|
297
|
-
success: false,
|
|
298
|
-
data: null,
|
|
299
1328
|
message: "Internal Server Error"
|
|
300
1329
|
});
|
|
301
1330
|
}
|
|
302
1331
|
}
|
|
303
1332
|
};
|
|
304
|
-
return async (request) => {
|
|
305
|
-
if (this
|
|
306
|
-
const result = await this
|
|
1333
|
+
return async (request, ...args) => {
|
|
1334
|
+
if (this.#state.config.before) {
|
|
1335
|
+
const result = await this.#state.config.before(request);
|
|
307
1336
|
if (result instanceof Response) {
|
|
308
|
-
if (this
|
|
309
|
-
const transformed = await this
|
|
1337
|
+
if (this.#state.config.transform) {
|
|
1338
|
+
const transformed = await this.#state.config.transform(request, result);
|
|
310
1339
|
if (transformed instanceof Response) {
|
|
311
1340
|
return result;
|
|
312
1341
|
}
|
|
@@ -314,9 +1343,9 @@ var Router = class _Router {
|
|
|
314
1343
|
return result;
|
|
315
1344
|
}
|
|
316
1345
|
}
|
|
317
|
-
const response = await handle(request);
|
|
318
|
-
if (this
|
|
319
|
-
const transformed = await this
|
|
1346
|
+
const response = await handle(request, ...args);
|
|
1347
|
+
if (this.#state.config.transform) {
|
|
1348
|
+
const transformed = await this.#state.config.transform(request, response);
|
|
320
1349
|
if (transformed instanceof Response) {
|
|
321
1350
|
return transformed;
|
|
322
1351
|
}
|
|
@@ -324,66 +1353,124 @@ var Router = class _Router {
|
|
|
324
1353
|
return response;
|
|
325
1354
|
};
|
|
326
1355
|
};
|
|
327
|
-
|
|
328
|
-
|
|
1356
|
+
/**
|
|
1357
|
+
* Create a `/openapi.json` route on this router.
|
|
1358
|
+
*
|
|
1359
|
+
* Any routes defined AFTER this method call will NOT be included in the
|
|
1360
|
+
* file. This is because all methods in Kaito are immutable, so there's no
|
|
1361
|
+
* way for the router to know about routes that were created in the future
|
|
1362
|
+
* on another router.
|
|
1363
|
+
*
|
|
1364
|
+
* @example
|
|
1365
|
+
* ```ts
|
|
1366
|
+
* router.get("/", () => "hey").openapi({
|
|
1367
|
+
* info: {
|
|
1368
|
+
* title: "My API",
|
|
1369
|
+
* version: "1.0.0",
|
|
1370
|
+
* },
|
|
1371
|
+
* });
|
|
1372
|
+
* ```
|
|
1373
|
+
*
|
|
1374
|
+
* @param options Options object
|
|
1375
|
+
* @returns
|
|
1376
|
+
*/
|
|
1377
|
+
openapi = ({
|
|
1378
|
+
info,
|
|
1379
|
+
servers
|
|
1380
|
+
}) => {
|
|
1381
|
+
const OPENAPI_VERSION = "3.1.0";
|
|
1382
|
+
const componentsSchemas = {};
|
|
1383
|
+
const addSchemaForRef = (ref) => {
|
|
1384
|
+
const name = ref.name;
|
|
1385
|
+
const properties = Object.fromEntries(Object.entries(ref.shape).map(([key, value]) => [key, value.toOpenAPI()]));
|
|
1386
|
+
const desc = ref.description();
|
|
1387
|
+
const schemaObject = {
|
|
1388
|
+
type: "object",
|
|
1389
|
+
properties,
|
|
1390
|
+
required: Object.keys(ref.shape),
|
|
1391
|
+
...desc ? { description: desc } : {}
|
|
1392
|
+
};
|
|
1393
|
+
const existing = componentsSchemas[name];
|
|
1394
|
+
if (existing) {
|
|
1395
|
+
if (JSON.stringify(existing) !== JSON.stringify(schemaObject)) {
|
|
1396
|
+
throw new Error(
|
|
1397
|
+
`Conflicting KRef definitions detected for "${name}". OpenAPI components require a single schema per name.`
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
componentsSchemas[name] = schemaObject;
|
|
1403
|
+
};
|
|
1404
|
+
function visit(schema, seen = /* @__PURE__ */ new Set()) {
|
|
1405
|
+
if (seen.has(schema)) return;
|
|
1406
|
+
seen.add(schema);
|
|
1407
|
+
if (schema instanceof KRef) addSchemaForRef(schema);
|
|
1408
|
+
schema.visit((child) => visit(child, seen));
|
|
1409
|
+
}
|
|
329
1410
|
const paths = {};
|
|
330
|
-
for (const route of this
|
|
331
|
-
|
|
332
|
-
|
|
1411
|
+
for (const route of this.#state.routes) {
|
|
1412
|
+
if (!route.openapi) {
|
|
1413
|
+
continue;
|
|
1414
|
+
}
|
|
1415
|
+
const pathWithColonParamsReplaceWithCurlyBraces = route.path.replace(/:(\w+)/g, "{$1}");
|
|
333
1416
|
if (!paths[pathWithColonParamsReplaceWithCurlyBraces]) {
|
|
334
1417
|
paths[pathWithColonParamsReplaceWithCurlyBraces] = {};
|
|
335
1418
|
}
|
|
1419
|
+
let contentType;
|
|
1420
|
+
const type = route.openapi.body.type;
|
|
1421
|
+
switch (type) {
|
|
1422
|
+
case "json":
|
|
1423
|
+
contentType = "application/json";
|
|
1424
|
+
break;
|
|
1425
|
+
case "sse":
|
|
1426
|
+
contentType = "text/event-stream";
|
|
1427
|
+
break;
|
|
1428
|
+
case "response":
|
|
1429
|
+
contentType = "application/octet-stream";
|
|
1430
|
+
break;
|
|
1431
|
+
default:
|
|
1432
|
+
throw new Error(`Unknown output type in route ${route.method} ${route.path}: ${type}`);
|
|
1433
|
+
}
|
|
1434
|
+
if ("schema" in route.openapi.body && route.openapi.body.schema) visit(route.openapi.body.schema);
|
|
1435
|
+
if (route.body) visit(route.body);
|
|
1436
|
+
const responseSchema = "schema" in route.openapi.body && route.openapi.body.schema ? route.openapi.body.schema.toOpenAPI() : { type: "string" };
|
|
336
1437
|
const item = {
|
|
1438
|
+
...route.openapi.summary ? { summary: route.openapi.summary } : {},
|
|
337
1439
|
description: route.openapi?.description ?? "Successful response",
|
|
338
1440
|
responses: {
|
|
339
1441
|
200: {
|
|
340
|
-
description: route.openapi
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
json: "application/json",
|
|
345
|
-
sse: "text/event-stream"
|
|
346
|
-
}[route.openapi.body.type]]: { schema: route.openapi?.body.schema }
|
|
1442
|
+
description: route.openapi.body.description ?? "Successful response",
|
|
1443
|
+
content: {
|
|
1444
|
+
[contentType]: {
|
|
1445
|
+
schema: responseSchema
|
|
347
1446
|
}
|
|
348
|
-
}
|
|
1447
|
+
}
|
|
349
1448
|
}
|
|
350
1449
|
}
|
|
351
1450
|
};
|
|
352
1451
|
if (route.body) {
|
|
353
1452
|
item.requestBody = {
|
|
354
1453
|
content: {
|
|
355
|
-
"application/json": { schema: route.body }
|
|
1454
|
+
"application/json": { schema: route.body.toOpenAPI() }
|
|
356
1455
|
}
|
|
357
1456
|
};
|
|
358
1457
|
}
|
|
359
|
-
const params = {};
|
|
360
|
-
if (route.query) {
|
|
361
|
-
params.query = import_zod.z.object(route.query);
|
|
362
|
-
}
|
|
363
|
-
const urlParams = path.match(/:(\w+)/g);
|
|
364
|
-
if (urlParams) {
|
|
365
|
-
const pathParams = {};
|
|
366
|
-
for (const param of urlParams) {
|
|
367
|
-
pathParams[param.slice(1)] = import_zod.z.string();
|
|
368
|
-
}
|
|
369
|
-
params.path = import_zod.z.object(pathParams);
|
|
370
|
-
}
|
|
371
|
-
item.requestParams = params;
|
|
372
1458
|
paths[pathWithColonParamsReplaceWithCurlyBraces][route.method.toLowerCase()] = item;
|
|
373
1459
|
}
|
|
374
|
-
const doc =
|
|
1460
|
+
const doc = {
|
|
375
1461
|
openapi: OPENAPI_VERSION,
|
|
1462
|
+
info,
|
|
376
1463
|
paths,
|
|
377
|
-
...
|
|
378
|
-
servers: Object.entries(
|
|
1464
|
+
...Object.keys(componentsSchemas).length > 0 ? { components: { schemas: componentsSchemas } } : {},
|
|
1465
|
+
servers: Object.entries(servers ?? {}).map((entry) => {
|
|
379
1466
|
const [url, description] = entry;
|
|
380
1467
|
return {
|
|
381
1468
|
url,
|
|
382
1469
|
description
|
|
383
1470
|
};
|
|
384
1471
|
})
|
|
385
|
-
}
|
|
386
|
-
return this.
|
|
1472
|
+
};
|
|
1473
|
+
return this.get("/openapi.json", () => Response.json(doc));
|
|
387
1474
|
};
|
|
388
1475
|
method = (method) => {
|
|
389
1476
|
return (path, route) => this.add(method, path, route);
|
|
@@ -397,22 +1484,47 @@ var Router = class _Router {
|
|
|
397
1484
|
options = this.method("OPTIONS");
|
|
398
1485
|
through = (through) => {
|
|
399
1486
|
return new _Router({
|
|
400
|
-
...this
|
|
401
|
-
through:
|
|
1487
|
+
...this.#state,
|
|
1488
|
+
through: (context, params) => {
|
|
1489
|
+
const next = this.#state.through(context, params);
|
|
1490
|
+
if (next instanceof Promise) {
|
|
1491
|
+
return next.then((next2) => through(next2, params));
|
|
1492
|
+
}
|
|
1493
|
+
return through(next, params);
|
|
1494
|
+
}
|
|
402
1495
|
});
|
|
403
1496
|
};
|
|
404
1497
|
};
|
|
405
1498
|
|
|
406
|
-
// src/
|
|
407
|
-
|
|
408
|
-
return () => Router.create(config);
|
|
409
|
-
}
|
|
1499
|
+
// src/index.ts
|
|
1500
|
+
var create = Router.create;
|
|
410
1501
|
// Annotate the CommonJS export names for ESM import in node:
|
|
411
1502
|
0 && (module.exports = {
|
|
1503
|
+
BaseSchema,
|
|
1504
|
+
KArray,
|
|
1505
|
+
KBoolean,
|
|
1506
|
+
KLazy,
|
|
1507
|
+
KLiteral,
|
|
1508
|
+
KNativeEnum,
|
|
1509
|
+
KNull,
|
|
1510
|
+
KNumber,
|
|
1511
|
+
KObject,
|
|
1512
|
+
KObjectFromURLSearchParams,
|
|
1513
|
+
KRecord,
|
|
1514
|
+
KRef,
|
|
1515
|
+
KScalar,
|
|
1516
|
+
KString,
|
|
1517
|
+
KUnion,
|
|
412
1518
|
KaitoError,
|
|
1519
|
+
KaitoHead,
|
|
413
1520
|
KaitoRequest,
|
|
1521
|
+
ParseContext,
|
|
414
1522
|
Router,
|
|
1523
|
+
STRING_FORMAT_REGEXES,
|
|
1524
|
+
SchemaError,
|
|
415
1525
|
WrappedError,
|
|
416
1526
|
create,
|
|
417
|
-
isNodeLikeDev
|
|
1527
|
+
isNodeLikeDev,
|
|
1528
|
+
isPrimitiveJSONValue,
|
|
1529
|
+
k
|
|
418
1530
|
});
|