adorn-api 1.0.6 → 1.0.7
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 +12 -0
- package/dist/adapter/express/bootstrap.d.ts +1 -0
- package/dist/adapter/express/bootstrap.d.ts.map +1 -1
- package/dist/adapter/express/index.d.ts +11 -0
- package/dist/adapter/express/index.d.ts.map +1 -1
- package/dist/cli.cjs +16 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -1
- package/dist/express.cjs +231 -47
- package/dist/express.cjs.map +1 -1
- package/dist/express.js +231 -47
- package/dist/express.js.map +1 -1
- package/package.json +1 -1
package/dist/express.js
CHANGED
|
@@ -249,7 +249,8 @@ function bootstrap(options) {
|
|
|
249
249
|
swaggerPath = "/docs",
|
|
250
250
|
swaggerJsonPath = "/docs/openapi.json",
|
|
251
251
|
middleware,
|
|
252
|
-
auth
|
|
252
|
+
auth,
|
|
253
|
+
coerce
|
|
253
254
|
} = options;
|
|
254
255
|
if (controllers.length === 0) {
|
|
255
256
|
reject(new Error("At least one controller must be provided to bootstrap()."));
|
|
@@ -269,7 +270,8 @@ function bootstrap(options) {
|
|
|
269
270
|
controllers,
|
|
270
271
|
artifactsDir: absoluteArtifactsDir,
|
|
271
272
|
middleware,
|
|
272
|
-
auth
|
|
273
|
+
auth,
|
|
274
|
+
coerce
|
|
273
275
|
});
|
|
274
276
|
app.use(router);
|
|
275
277
|
if (enableSwagger) {
|
|
@@ -324,6 +326,17 @@ function bootstrap(options) {
|
|
|
324
326
|
}
|
|
325
327
|
|
|
326
328
|
// src/adapter/express/index.ts
|
|
329
|
+
function normalizeCoerceOptions(coerce) {
|
|
330
|
+
return {
|
|
331
|
+
body: coerce?.body ?? false,
|
|
332
|
+
query: coerce?.query ?? false,
|
|
333
|
+
path: coerce?.path ?? false,
|
|
334
|
+
header: coerce?.header ?? false,
|
|
335
|
+
cookie: coerce?.cookie ?? false,
|
|
336
|
+
dateTime: coerce?.dateTime ?? false,
|
|
337
|
+
date: coerce?.date ?? false
|
|
338
|
+
};
|
|
339
|
+
}
|
|
327
340
|
async function createExpressRouter(options) {
|
|
328
341
|
const { controllers, artifactsDir = ".adorn", middleware = {} } = options;
|
|
329
342
|
let manifest;
|
|
@@ -350,6 +363,7 @@ async function createExpressRouter(options) {
|
|
|
350
363
|
const validator = precompiledValidators ? null : createValidator();
|
|
351
364
|
const router = Router();
|
|
352
365
|
const instanceCache = /* @__PURE__ */ new Map();
|
|
366
|
+
const coerce = normalizeCoerceOptions(options.coerce);
|
|
353
367
|
function getInstance(Ctor) {
|
|
354
368
|
if (!instanceCache.has(Ctor)) {
|
|
355
369
|
instanceCache.set(Ctor, new Ctor());
|
|
@@ -412,6 +426,14 @@ async function createExpressRouter(options) {
|
|
|
412
426
|
}
|
|
413
427
|
for (const route of routes) {
|
|
414
428
|
const method = route.httpMethod.toLowerCase();
|
|
429
|
+
const openapiOperation = getOpenApiOperation(openapi, route);
|
|
430
|
+
const paramSchemaIndex = buildParamSchemaIndex(openapiOperation);
|
|
431
|
+
const bodySchema = getRequestBodySchema(openapiOperation, route.args.body?.contentType) ?? (route.args.body ? getSchemaByRef(route.args.body.schemaRef) : null);
|
|
432
|
+
const coerceBodyDates = getDateCoercionOptions(coerce, "body");
|
|
433
|
+
const coerceQueryDates = getDateCoercionOptions(coerce, "query");
|
|
434
|
+
const coercePathDates = getDateCoercionOptions(coerce, "path");
|
|
435
|
+
const coerceHeaderDates = getDateCoercionOptions(coerce, "header");
|
|
436
|
+
const coerceCookieDates = getDateCoercionOptions(coerce, "cookie");
|
|
415
437
|
const middlewareChain = [];
|
|
416
438
|
if (middleware.global) {
|
|
417
439
|
middlewareChain.push(...resolveMiddleware(middleware.global, middleware.named || {}));
|
|
@@ -439,10 +461,13 @@ async function createExpressRouter(options) {
|
|
|
439
461
|
}
|
|
440
462
|
const args = [];
|
|
441
463
|
if (route.args.body) {
|
|
442
|
-
|
|
464
|
+
const coercedBody = (coerceBodyDates.date || coerceBodyDates.dateTime) && bodySchema ? coerceDatesWithSchema(req.body, bodySchema, coerceBodyDates, openapi.components.schemas) : req.body;
|
|
465
|
+
args[route.args.body.index] = coercedBody;
|
|
443
466
|
}
|
|
444
467
|
for (const pathArg of route.args.path) {
|
|
445
|
-
const
|
|
468
|
+
const rawValue = req.params[pathArg.name];
|
|
469
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "path", pathArg.name) ?? (pathArg.schemaRef ? getSchemaByRef(pathArg.schemaRef) : null) ?? schemaFromType(pathArg.schemaType);
|
|
470
|
+
const coerced = coerceParamValue(rawValue, paramSchema, coercePathDates, openapi.components.schemas);
|
|
446
471
|
args[pathArg.index] = coerced;
|
|
447
472
|
}
|
|
448
473
|
if (route.args.query.length > 0) {
|
|
@@ -452,13 +477,15 @@ async function createExpressRouter(options) {
|
|
|
452
477
|
args[firstQueryIndex] = {};
|
|
453
478
|
for (const q of route.args.query) {
|
|
454
479
|
const parsed = parseQueryValue(req.query[q.name], q);
|
|
455
|
-
const
|
|
480
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name) ?? (q.schemaRef ? getSchemaByRef(q.schemaRef) : null) ?? schemaFromType(q.schemaType);
|
|
481
|
+
const coerced = coerceParamValue(parsed, paramSchema, coerceQueryDates, openapi.components.schemas);
|
|
456
482
|
args[firstQueryIndex][q.name] = coerced;
|
|
457
483
|
}
|
|
458
484
|
} else {
|
|
459
485
|
for (const q of route.args.query) {
|
|
460
486
|
const parsed = parseQueryValue(req.query[q.name], q);
|
|
461
|
-
const
|
|
487
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name) ?? (q.schemaRef ? getSchemaByRef(q.schemaRef) : null) ?? schemaFromType(q.schemaType);
|
|
488
|
+
const coerced = coerceParamValue(parsed, paramSchema, coerceQueryDates, openapi.components.schemas);
|
|
462
489
|
args[q.index] = coerced;
|
|
463
490
|
}
|
|
464
491
|
}
|
|
@@ -470,12 +497,16 @@ async function createExpressRouter(options) {
|
|
|
470
497
|
args[firstHeaderIndex] = {};
|
|
471
498
|
for (const h of route.args.headers) {
|
|
472
499
|
const headerValue = req.headers[h.name.toLowerCase()];
|
|
473
|
-
|
|
500
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "header", h.name) ?? (h.schemaRef ? getSchemaByRef(h.schemaRef) : null) ?? schemaFromType(h.schemaType);
|
|
501
|
+
const coerced = coerceParamValue(headerValue, paramSchema, coerceHeaderDates, openapi.components.schemas);
|
|
502
|
+
args[firstHeaderIndex][h.name] = coerced ?? void 0;
|
|
474
503
|
}
|
|
475
504
|
} else {
|
|
476
505
|
for (const h of route.args.headers) {
|
|
477
506
|
const headerValue = req.headers[h.name.toLowerCase()];
|
|
478
|
-
|
|
507
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "header", h.name) ?? (h.schemaRef ? getSchemaByRef(h.schemaRef) : null) ?? schemaFromType(h.schemaType);
|
|
508
|
+
const coerced = coerceParamValue(headerValue, paramSchema, coerceHeaderDates, openapi.components.schemas);
|
|
509
|
+
args[h.index] = coerced ?? void 0;
|
|
479
510
|
}
|
|
480
511
|
}
|
|
481
512
|
}
|
|
@@ -487,13 +518,15 @@ async function createExpressRouter(options) {
|
|
|
487
518
|
args[firstCookieIndex] = {};
|
|
488
519
|
for (const c of route.args.cookies) {
|
|
489
520
|
const cookieValue = cookies[c.name];
|
|
490
|
-
const
|
|
521
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "cookie", c.name) ?? (c.schemaRef ? getSchemaByRef(c.schemaRef) : null) ?? schemaFromType(c.schemaType);
|
|
522
|
+
const coerced = coerceParamValue(cookieValue, paramSchema, coerceCookieDates, openapi.components.schemas);
|
|
491
523
|
args[firstCookieIndex][c.name] = coerced;
|
|
492
524
|
}
|
|
493
525
|
} else {
|
|
494
526
|
for (const c of route.args.cookies) {
|
|
495
527
|
const cookieValue = cookies[c.name];
|
|
496
|
-
const
|
|
528
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "cookie", c.name) ?? (c.schemaRef ? getSchemaByRef(c.schemaRef) : null) ?? schemaFromType(c.schemaType);
|
|
529
|
+
const coerced = coerceParamValue(cookieValue, paramSchema, coerceCookieDates, openapi.components.schemas);
|
|
497
530
|
args[c.index] = coerced;
|
|
498
531
|
}
|
|
499
532
|
}
|
|
@@ -512,6 +545,49 @@ async function createExpressRouter(options) {
|
|
|
512
545
|
}
|
|
513
546
|
return router;
|
|
514
547
|
}
|
|
548
|
+
function getDateCoercionOptions(coerce, location) {
|
|
549
|
+
const enabled = coerce[location];
|
|
550
|
+
return {
|
|
551
|
+
dateTime: enabled && coerce.dateTime,
|
|
552
|
+
date: enabled && coerce.date
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
function toOpenApiPath(path3) {
|
|
556
|
+
return path3.replace(/:([^/]+)/g, "{$1}");
|
|
557
|
+
}
|
|
558
|
+
function getOpenApiOperation(openapi, route) {
|
|
559
|
+
const pathKey = toOpenApiPath(route.fullPath);
|
|
560
|
+
const pathItem = openapi.paths?.[pathKey];
|
|
561
|
+
if (!pathItem) return null;
|
|
562
|
+
return pathItem[route.httpMethod.toLowerCase()] ?? null;
|
|
563
|
+
}
|
|
564
|
+
function buildParamSchemaIndex(operation) {
|
|
565
|
+
const index = /* @__PURE__ */ new Map();
|
|
566
|
+
const params = operation?.parameters ?? [];
|
|
567
|
+
for (const param of params) {
|
|
568
|
+
if (!param?.name || !param?.in) continue;
|
|
569
|
+
if (param.schema) {
|
|
570
|
+
index.set(`${param.in}:${param.name}`, param.schema);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
return index;
|
|
574
|
+
}
|
|
575
|
+
function getParamSchemaFromIndex(index, location, name) {
|
|
576
|
+
return index.get(`${location}:${name}`) ?? null;
|
|
577
|
+
}
|
|
578
|
+
function getRequestBodySchema(operation, contentType) {
|
|
579
|
+
const content = operation?.requestBody?.content;
|
|
580
|
+
if (!content) return null;
|
|
581
|
+
if (contentType && content[contentType]?.schema) {
|
|
582
|
+
return content[contentType].schema;
|
|
583
|
+
}
|
|
584
|
+
const first = Object.values(content)[0];
|
|
585
|
+
return first?.schema ?? null;
|
|
586
|
+
}
|
|
587
|
+
function schemaFromType(schemaType) {
|
|
588
|
+
if (!schemaType) return null;
|
|
589
|
+
return { type: schemaType };
|
|
590
|
+
}
|
|
515
591
|
function validateRequestWithPrecompiled(route, req, validators) {
|
|
516
592
|
const errors = [];
|
|
517
593
|
if (route.args.body) {
|
|
@@ -534,12 +610,8 @@ function validateRequestWithPrecompiled(route, req, validators) {
|
|
|
534
610
|
for (const q of route.args.query) {
|
|
535
611
|
const value = req.query[q.name];
|
|
536
612
|
if (value === void 0) continue;
|
|
537
|
-
const schema = {};
|
|
538
|
-
|
|
539
|
-
const type = Array.isArray(q.schemaType) ? q.schemaType[0] : q.schemaType;
|
|
540
|
-
schema.type = type;
|
|
541
|
-
}
|
|
542
|
-
const coerced = coerceValue(value, q.schemaType);
|
|
613
|
+
const schema = schemaFromType(q.schemaType) ?? {};
|
|
614
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, {});
|
|
543
615
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
544
616
|
errors.push({
|
|
545
617
|
path: `#/query/${q.name}`,
|
|
@@ -552,12 +624,8 @@ function validateRequestWithPrecompiled(route, req, validators) {
|
|
|
552
624
|
for (const p of route.args.path) {
|
|
553
625
|
const value = req.params[p.name];
|
|
554
626
|
if (value === void 0) continue;
|
|
555
|
-
const schema = {};
|
|
556
|
-
|
|
557
|
-
const type = Array.isArray(p.schemaType) ? p.schemaType[0] : p.schemaType;
|
|
558
|
-
schema.type = type;
|
|
559
|
-
}
|
|
560
|
-
const coerced = coerceValue(value, p.schemaType);
|
|
627
|
+
const schema = schemaFromType(p.schemaType) ?? {};
|
|
628
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, {});
|
|
561
629
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
562
630
|
errors.push({
|
|
563
631
|
path: `#/path/${p.name}`,
|
|
@@ -575,6 +643,8 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
575
643
|
const schemaName = ref.replace("#/components/schemas/", "");
|
|
576
644
|
return openapi.components.schemas[schemaName] || null;
|
|
577
645
|
}
|
|
646
|
+
const openapiOperation = getOpenApiOperation(openapi, route);
|
|
647
|
+
const paramSchemaIndex = buildParamSchemaIndex(openapiOperation);
|
|
578
648
|
const errors = [];
|
|
579
649
|
if (route.args.body) {
|
|
580
650
|
const bodySchema = getSchemaByRef(route.args.body.schemaRef);
|
|
@@ -595,18 +665,23 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
595
665
|
}
|
|
596
666
|
for (const q of route.args.query) {
|
|
597
667
|
const value = req.query[q.name];
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
schema
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
668
|
+
const openapiSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name);
|
|
669
|
+
let schema = {};
|
|
670
|
+
if (openapiSchema) {
|
|
671
|
+
schema = resolveSchema(openapiSchema, openapi.components.schemas);
|
|
672
|
+
} else {
|
|
673
|
+
if (q.schemaType) {
|
|
674
|
+
const type = Array.isArray(q.schemaType) ? q.schemaType[0] : q.schemaType;
|
|
675
|
+
schema.type = type;
|
|
676
|
+
}
|
|
677
|
+
if (q.schemaRef && q.schemaRef.includes("Inline")) {
|
|
678
|
+
const inlineSchema = getSchemaByRef(q.schemaRef);
|
|
679
|
+
if (inlineSchema) {
|
|
680
|
+
Object.assign(schema, inlineSchema);
|
|
681
|
+
}
|
|
607
682
|
}
|
|
608
683
|
}
|
|
609
|
-
const coerced =
|
|
684
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, openapi.components.schemas);
|
|
610
685
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
611
686
|
const validate = validator.compile(schema);
|
|
612
687
|
const valid = validate(coerced);
|
|
@@ -624,18 +699,23 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
624
699
|
}
|
|
625
700
|
for (const p of route.args.path) {
|
|
626
701
|
const value = req.params[p.name];
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
schema
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
702
|
+
const openapiSchema = getParamSchemaFromIndex(paramSchemaIndex, "path", p.name);
|
|
703
|
+
let schema = {};
|
|
704
|
+
if (openapiSchema) {
|
|
705
|
+
schema = resolveSchema(openapiSchema, openapi.components.schemas);
|
|
706
|
+
} else {
|
|
707
|
+
if (p.schemaType) {
|
|
708
|
+
const type = Array.isArray(p.schemaType) ? p.schemaType[0] : p.schemaType;
|
|
709
|
+
schema.type = type;
|
|
710
|
+
}
|
|
711
|
+
if (p.schemaRef && p.schemaRef.includes("Inline")) {
|
|
712
|
+
const inlineSchema = getSchemaByRef(p.schemaRef);
|
|
713
|
+
if (inlineSchema) {
|
|
714
|
+
Object.assign(schema, inlineSchema);
|
|
715
|
+
}
|
|
636
716
|
}
|
|
637
717
|
}
|
|
638
|
-
const coerced =
|
|
718
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, openapi.components.schemas);
|
|
639
719
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
640
720
|
const validate = validator.compile(schema);
|
|
641
721
|
const valid = validate(coerced);
|
|
@@ -653,23 +733,127 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
653
733
|
}
|
|
654
734
|
return errors.length > 0 ? errors : null;
|
|
655
735
|
}
|
|
656
|
-
function
|
|
736
|
+
function resolveSchema(schema, components, seen = /* @__PURE__ */ new Set()) {
|
|
737
|
+
const ref = schema.$ref;
|
|
738
|
+
if (typeof ref !== "string" || !ref.startsWith("#/components/schemas/")) {
|
|
739
|
+
return schema;
|
|
740
|
+
}
|
|
741
|
+
const name = ref.replace("#/components/schemas/", "");
|
|
742
|
+
if (seen.has(name)) return schema;
|
|
743
|
+
const next = components[name];
|
|
744
|
+
if (!next) return schema;
|
|
745
|
+
seen.add(name);
|
|
746
|
+
return resolveSchema(next, components, seen);
|
|
747
|
+
}
|
|
748
|
+
function coerceDatesWithSchema(value, schema, dateCoercion, components) {
|
|
749
|
+
if (!schema || !dateCoercion.date && !dateCoercion.dateTime) return value;
|
|
750
|
+
return coerceWithSchema(value, schema, dateCoercion, components, { coercePrimitives: false });
|
|
751
|
+
}
|
|
752
|
+
function coerceParamValue(value, schema, dateCoercion, components) {
|
|
753
|
+
if (!schema) return value;
|
|
754
|
+
return coerceWithSchema(value, schema, dateCoercion, components, { coercePrimitives: true });
|
|
755
|
+
}
|
|
756
|
+
function coerceWithSchema(value, schema, dateCoercion, components, options) {
|
|
757
|
+
if (value === void 0 || value === null) return value;
|
|
758
|
+
if (value instanceof Date) return value;
|
|
759
|
+
const resolved = resolveSchema(schema, components);
|
|
760
|
+
const override = resolved["x-adorn-coerce"];
|
|
761
|
+
const allowDateTime = override === true ? true : override === false ? false : dateCoercion.dateTime;
|
|
762
|
+
const allowDate = override === true ? true : override === false ? false : dateCoercion.date;
|
|
763
|
+
const byFormat = coerceDateString(value, resolved, allowDateTime, allowDate);
|
|
764
|
+
if (byFormat !== value) return byFormat;
|
|
765
|
+
const allOf = resolved.allOf;
|
|
766
|
+
if (Array.isArray(allOf)) {
|
|
767
|
+
let out = value;
|
|
768
|
+
for (const entry of allOf) {
|
|
769
|
+
out = coerceWithSchema(out, entry, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
770
|
+
}
|
|
771
|
+
return out;
|
|
772
|
+
}
|
|
773
|
+
const variants = resolved.oneOf ?? resolved.anyOf;
|
|
774
|
+
if (Array.isArray(variants)) {
|
|
775
|
+
for (const entry of variants) {
|
|
776
|
+
const out = coerceWithSchema(value, entry, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
777
|
+
if (out !== value) return out;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
const schemaType = resolved.type;
|
|
781
|
+
const types = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
|
|
782
|
+
if ((types.includes("array") || resolved.items) && Array.isArray(value)) {
|
|
783
|
+
const itemSchema = resolved.items ?? {};
|
|
784
|
+
return value.map((item) => coerceWithSchema(item, itemSchema, { dateTime: allowDateTime, date: allowDate }, components, options));
|
|
785
|
+
}
|
|
786
|
+
if ((types.includes("object") || resolved.properties || resolved.additionalProperties) && isPlainObject(value)) {
|
|
787
|
+
const props = resolved.properties;
|
|
788
|
+
const out = { ...value };
|
|
789
|
+
if (props) {
|
|
790
|
+
for (const [key, propSchema] of Object.entries(props)) {
|
|
791
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
792
|
+
out[key] = coerceWithSchema(value[key], propSchema, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
const additional = resolved.additionalProperties;
|
|
797
|
+
if (additional && typeof additional === "object") {
|
|
798
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
799
|
+
if (props && Object.prototype.hasOwnProperty.call(props, key)) continue;
|
|
800
|
+
out[key] = coerceWithSchema(entry, additional, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return out;
|
|
804
|
+
}
|
|
805
|
+
if (options.coercePrimitives) {
|
|
806
|
+
return coercePrimitiveValue(value, types);
|
|
807
|
+
}
|
|
808
|
+
return value;
|
|
809
|
+
}
|
|
810
|
+
function coerceDateString(value, schema, allowDateTime, allowDate) {
|
|
811
|
+
if (typeof value !== "string") return value;
|
|
812
|
+
const format = schema.format;
|
|
813
|
+
const schemaType = schema.type;
|
|
814
|
+
const types = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
|
|
815
|
+
const allowsString = types.length === 0 || types.includes("string");
|
|
816
|
+
if (format === "date-time" && allowDateTime && allowsString) {
|
|
817
|
+
const parsed = new Date(value);
|
|
818
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
819
|
+
throw new Error(`Invalid date-time: ${value}`);
|
|
820
|
+
}
|
|
821
|
+
return parsed;
|
|
822
|
+
}
|
|
823
|
+
if (format === "date" && allowDate && allowsString) {
|
|
824
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
825
|
+
throw new Error(`Invalid date: ${value}`);
|
|
826
|
+
}
|
|
827
|
+
const parsed = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
|
|
828
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
829
|
+
throw new Error(`Invalid date: ${value}`);
|
|
830
|
+
}
|
|
831
|
+
return parsed;
|
|
832
|
+
}
|
|
833
|
+
return value;
|
|
834
|
+
}
|
|
835
|
+
function coercePrimitiveValue(value, types) {
|
|
657
836
|
if (value === void 0 || value === null) return value;
|
|
658
|
-
|
|
659
|
-
if (type === "number" || type === "integer") {
|
|
837
|
+
if (types.includes("number") || types.includes("integer")) {
|
|
660
838
|
const num = Number(value);
|
|
661
|
-
if (isNaN(num)) {
|
|
839
|
+
if (Number.isNaN(num)) {
|
|
662
840
|
throw new Error(`Invalid number: ${value}`);
|
|
663
841
|
}
|
|
664
842
|
return num;
|
|
665
843
|
}
|
|
666
|
-
if (
|
|
844
|
+
if (types.includes("boolean")) {
|
|
667
845
|
if (value === "true") return true;
|
|
668
846
|
if (value === "false") return false;
|
|
847
|
+
if (typeof value === "boolean") return value;
|
|
669
848
|
throw new Error(`Invalid boolean: ${value}`);
|
|
670
849
|
}
|
|
671
850
|
return value;
|
|
672
851
|
}
|
|
852
|
+
function isPlainObject(value) {
|
|
853
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
854
|
+
const proto = Object.getPrototypeOf(value);
|
|
855
|
+
return proto === Object.prototype || proto === null;
|
|
856
|
+
}
|
|
673
857
|
function parseQueryValue(value, param) {
|
|
674
858
|
if (value === void 0 || value === null) return value;
|
|
675
859
|
const isArray = Array.isArray(param.schemaType) ? param.schemaType.includes("array") : param.schemaType === "array";
|