adorn-api 1.0.5 → 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 +19 -7
- 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 +4 -4
package/dist/express.cjs
CHANGED
|
@@ -284,7 +284,8 @@ function bootstrap(options) {
|
|
|
284
284
|
swaggerPath = "/docs",
|
|
285
285
|
swaggerJsonPath = "/docs/openapi.json",
|
|
286
286
|
middleware,
|
|
287
|
-
auth
|
|
287
|
+
auth,
|
|
288
|
+
coerce
|
|
288
289
|
} = options;
|
|
289
290
|
if (controllers.length === 0) {
|
|
290
291
|
reject(new Error("At least one controller must be provided to bootstrap()."));
|
|
@@ -304,7 +305,8 @@ function bootstrap(options) {
|
|
|
304
305
|
controllers,
|
|
305
306
|
artifactsDir: absoluteArtifactsDir,
|
|
306
307
|
middleware,
|
|
307
|
-
auth
|
|
308
|
+
auth,
|
|
309
|
+
coerce
|
|
308
310
|
});
|
|
309
311
|
app.use(router);
|
|
310
312
|
if (enableSwagger) {
|
|
@@ -359,6 +361,17 @@ function bootstrap(options) {
|
|
|
359
361
|
}
|
|
360
362
|
|
|
361
363
|
// src/adapter/express/index.ts
|
|
364
|
+
function normalizeCoerceOptions(coerce) {
|
|
365
|
+
return {
|
|
366
|
+
body: coerce?.body ?? false,
|
|
367
|
+
query: coerce?.query ?? false,
|
|
368
|
+
path: coerce?.path ?? false,
|
|
369
|
+
header: coerce?.header ?? false,
|
|
370
|
+
cookie: coerce?.cookie ?? false,
|
|
371
|
+
dateTime: coerce?.dateTime ?? false,
|
|
372
|
+
date: coerce?.date ?? false
|
|
373
|
+
};
|
|
374
|
+
}
|
|
362
375
|
async function createExpressRouter(options) {
|
|
363
376
|
const { controllers, artifactsDir = ".adorn", middleware = {} } = options;
|
|
364
377
|
let manifest;
|
|
@@ -385,6 +398,7 @@ async function createExpressRouter(options) {
|
|
|
385
398
|
const validator = precompiledValidators ? null : createValidator();
|
|
386
399
|
const router = (0, import_express2.Router)();
|
|
387
400
|
const instanceCache = /* @__PURE__ */ new Map();
|
|
401
|
+
const coerce = normalizeCoerceOptions(options.coerce);
|
|
388
402
|
function getInstance(Ctor) {
|
|
389
403
|
if (!instanceCache.has(Ctor)) {
|
|
390
404
|
instanceCache.set(Ctor, new Ctor());
|
|
@@ -447,6 +461,14 @@ async function createExpressRouter(options) {
|
|
|
447
461
|
}
|
|
448
462
|
for (const route of routes) {
|
|
449
463
|
const method = route.httpMethod.toLowerCase();
|
|
464
|
+
const openapiOperation = getOpenApiOperation(openapi, route);
|
|
465
|
+
const paramSchemaIndex = buildParamSchemaIndex(openapiOperation);
|
|
466
|
+
const bodySchema = getRequestBodySchema(openapiOperation, route.args.body?.contentType) ?? (route.args.body ? getSchemaByRef(route.args.body.schemaRef) : null);
|
|
467
|
+
const coerceBodyDates = getDateCoercionOptions(coerce, "body");
|
|
468
|
+
const coerceQueryDates = getDateCoercionOptions(coerce, "query");
|
|
469
|
+
const coercePathDates = getDateCoercionOptions(coerce, "path");
|
|
470
|
+
const coerceHeaderDates = getDateCoercionOptions(coerce, "header");
|
|
471
|
+
const coerceCookieDates = getDateCoercionOptions(coerce, "cookie");
|
|
450
472
|
const middlewareChain = [];
|
|
451
473
|
if (middleware.global) {
|
|
452
474
|
middlewareChain.push(...resolveMiddleware(middleware.global, middleware.named || {}));
|
|
@@ -474,10 +496,13 @@ async function createExpressRouter(options) {
|
|
|
474
496
|
}
|
|
475
497
|
const args = [];
|
|
476
498
|
if (route.args.body) {
|
|
477
|
-
|
|
499
|
+
const coercedBody = (coerceBodyDates.date || coerceBodyDates.dateTime) && bodySchema ? coerceDatesWithSchema(req.body, bodySchema, coerceBodyDates, openapi.components.schemas) : req.body;
|
|
500
|
+
args[route.args.body.index] = coercedBody;
|
|
478
501
|
}
|
|
479
502
|
for (const pathArg of route.args.path) {
|
|
480
|
-
const
|
|
503
|
+
const rawValue = req.params[pathArg.name];
|
|
504
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "path", pathArg.name) ?? (pathArg.schemaRef ? getSchemaByRef(pathArg.schemaRef) : null) ?? schemaFromType(pathArg.schemaType);
|
|
505
|
+
const coerced = coerceParamValue(rawValue, paramSchema, coercePathDates, openapi.components.schemas);
|
|
481
506
|
args[pathArg.index] = coerced;
|
|
482
507
|
}
|
|
483
508
|
if (route.args.query.length > 0) {
|
|
@@ -487,13 +512,15 @@ async function createExpressRouter(options) {
|
|
|
487
512
|
args[firstQueryIndex] = {};
|
|
488
513
|
for (const q of route.args.query) {
|
|
489
514
|
const parsed = parseQueryValue(req.query[q.name], q);
|
|
490
|
-
const
|
|
515
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name) ?? (q.schemaRef ? getSchemaByRef(q.schemaRef) : null) ?? schemaFromType(q.schemaType);
|
|
516
|
+
const coerced = coerceParamValue(parsed, paramSchema, coerceQueryDates, openapi.components.schemas);
|
|
491
517
|
args[firstQueryIndex][q.name] = coerced;
|
|
492
518
|
}
|
|
493
519
|
} else {
|
|
494
520
|
for (const q of route.args.query) {
|
|
495
521
|
const parsed = parseQueryValue(req.query[q.name], q);
|
|
496
|
-
const
|
|
522
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name) ?? (q.schemaRef ? getSchemaByRef(q.schemaRef) : null) ?? schemaFromType(q.schemaType);
|
|
523
|
+
const coerced = coerceParamValue(parsed, paramSchema, coerceQueryDates, openapi.components.schemas);
|
|
497
524
|
args[q.index] = coerced;
|
|
498
525
|
}
|
|
499
526
|
}
|
|
@@ -505,12 +532,16 @@ async function createExpressRouter(options) {
|
|
|
505
532
|
args[firstHeaderIndex] = {};
|
|
506
533
|
for (const h of route.args.headers) {
|
|
507
534
|
const headerValue = req.headers[h.name.toLowerCase()];
|
|
508
|
-
|
|
535
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "header", h.name) ?? (h.schemaRef ? getSchemaByRef(h.schemaRef) : null) ?? schemaFromType(h.schemaType);
|
|
536
|
+
const coerced = coerceParamValue(headerValue, paramSchema, coerceHeaderDates, openapi.components.schemas);
|
|
537
|
+
args[firstHeaderIndex][h.name] = coerced ?? void 0;
|
|
509
538
|
}
|
|
510
539
|
} else {
|
|
511
540
|
for (const h of route.args.headers) {
|
|
512
541
|
const headerValue = req.headers[h.name.toLowerCase()];
|
|
513
|
-
|
|
542
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "header", h.name) ?? (h.schemaRef ? getSchemaByRef(h.schemaRef) : null) ?? schemaFromType(h.schemaType);
|
|
543
|
+
const coerced = coerceParamValue(headerValue, paramSchema, coerceHeaderDates, openapi.components.schemas);
|
|
544
|
+
args[h.index] = coerced ?? void 0;
|
|
514
545
|
}
|
|
515
546
|
}
|
|
516
547
|
}
|
|
@@ -522,13 +553,15 @@ async function createExpressRouter(options) {
|
|
|
522
553
|
args[firstCookieIndex] = {};
|
|
523
554
|
for (const c of route.args.cookies) {
|
|
524
555
|
const cookieValue = cookies[c.name];
|
|
525
|
-
const
|
|
556
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "cookie", c.name) ?? (c.schemaRef ? getSchemaByRef(c.schemaRef) : null) ?? schemaFromType(c.schemaType);
|
|
557
|
+
const coerced = coerceParamValue(cookieValue, paramSchema, coerceCookieDates, openapi.components.schemas);
|
|
526
558
|
args[firstCookieIndex][c.name] = coerced;
|
|
527
559
|
}
|
|
528
560
|
} else {
|
|
529
561
|
for (const c of route.args.cookies) {
|
|
530
562
|
const cookieValue = cookies[c.name];
|
|
531
|
-
const
|
|
563
|
+
const paramSchema = getParamSchemaFromIndex(paramSchemaIndex, "cookie", c.name) ?? (c.schemaRef ? getSchemaByRef(c.schemaRef) : null) ?? schemaFromType(c.schemaType);
|
|
564
|
+
const coerced = coerceParamValue(cookieValue, paramSchema, coerceCookieDates, openapi.components.schemas);
|
|
532
565
|
args[c.index] = coerced;
|
|
533
566
|
}
|
|
534
567
|
}
|
|
@@ -547,6 +580,49 @@ async function createExpressRouter(options) {
|
|
|
547
580
|
}
|
|
548
581
|
return router;
|
|
549
582
|
}
|
|
583
|
+
function getDateCoercionOptions(coerce, location) {
|
|
584
|
+
const enabled = coerce[location];
|
|
585
|
+
return {
|
|
586
|
+
dateTime: enabled && coerce.dateTime,
|
|
587
|
+
date: enabled && coerce.date
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
function toOpenApiPath(path3) {
|
|
591
|
+
return path3.replace(/:([^/]+)/g, "{$1}");
|
|
592
|
+
}
|
|
593
|
+
function getOpenApiOperation(openapi, route) {
|
|
594
|
+
const pathKey = toOpenApiPath(route.fullPath);
|
|
595
|
+
const pathItem = openapi.paths?.[pathKey];
|
|
596
|
+
if (!pathItem) return null;
|
|
597
|
+
return pathItem[route.httpMethod.toLowerCase()] ?? null;
|
|
598
|
+
}
|
|
599
|
+
function buildParamSchemaIndex(operation) {
|
|
600
|
+
const index = /* @__PURE__ */ new Map();
|
|
601
|
+
const params = operation?.parameters ?? [];
|
|
602
|
+
for (const param of params) {
|
|
603
|
+
if (!param?.name || !param?.in) continue;
|
|
604
|
+
if (param.schema) {
|
|
605
|
+
index.set(`${param.in}:${param.name}`, param.schema);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return index;
|
|
609
|
+
}
|
|
610
|
+
function getParamSchemaFromIndex(index, location, name) {
|
|
611
|
+
return index.get(`${location}:${name}`) ?? null;
|
|
612
|
+
}
|
|
613
|
+
function getRequestBodySchema(operation, contentType) {
|
|
614
|
+
const content = operation?.requestBody?.content;
|
|
615
|
+
if (!content) return null;
|
|
616
|
+
if (contentType && content[contentType]?.schema) {
|
|
617
|
+
return content[contentType].schema;
|
|
618
|
+
}
|
|
619
|
+
const first = Object.values(content)[0];
|
|
620
|
+
return first?.schema ?? null;
|
|
621
|
+
}
|
|
622
|
+
function schemaFromType(schemaType) {
|
|
623
|
+
if (!schemaType) return null;
|
|
624
|
+
return { type: schemaType };
|
|
625
|
+
}
|
|
550
626
|
function validateRequestWithPrecompiled(route, req, validators) {
|
|
551
627
|
const errors = [];
|
|
552
628
|
if (route.args.body) {
|
|
@@ -569,12 +645,8 @@ function validateRequestWithPrecompiled(route, req, validators) {
|
|
|
569
645
|
for (const q of route.args.query) {
|
|
570
646
|
const value = req.query[q.name];
|
|
571
647
|
if (value === void 0) continue;
|
|
572
|
-
const schema = {};
|
|
573
|
-
|
|
574
|
-
const type = Array.isArray(q.schemaType) ? q.schemaType[0] : q.schemaType;
|
|
575
|
-
schema.type = type;
|
|
576
|
-
}
|
|
577
|
-
const coerced = coerceValue(value, q.schemaType);
|
|
648
|
+
const schema = schemaFromType(q.schemaType) ?? {};
|
|
649
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, {});
|
|
578
650
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
579
651
|
errors.push({
|
|
580
652
|
path: `#/query/${q.name}`,
|
|
@@ -587,12 +659,8 @@ function validateRequestWithPrecompiled(route, req, validators) {
|
|
|
587
659
|
for (const p of route.args.path) {
|
|
588
660
|
const value = req.params[p.name];
|
|
589
661
|
if (value === void 0) continue;
|
|
590
|
-
const schema = {};
|
|
591
|
-
|
|
592
|
-
const type = Array.isArray(p.schemaType) ? p.schemaType[0] : p.schemaType;
|
|
593
|
-
schema.type = type;
|
|
594
|
-
}
|
|
595
|
-
const coerced = coerceValue(value, p.schemaType);
|
|
662
|
+
const schema = schemaFromType(p.schemaType) ?? {};
|
|
663
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, {});
|
|
596
664
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
597
665
|
errors.push({
|
|
598
666
|
path: `#/path/${p.name}`,
|
|
@@ -610,6 +678,8 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
610
678
|
const schemaName = ref.replace("#/components/schemas/", "");
|
|
611
679
|
return openapi.components.schemas[schemaName] || null;
|
|
612
680
|
}
|
|
681
|
+
const openapiOperation = getOpenApiOperation(openapi, route);
|
|
682
|
+
const paramSchemaIndex = buildParamSchemaIndex(openapiOperation);
|
|
613
683
|
const errors = [];
|
|
614
684
|
if (route.args.body) {
|
|
615
685
|
const bodySchema = getSchemaByRef(route.args.body.schemaRef);
|
|
@@ -630,18 +700,23 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
630
700
|
}
|
|
631
701
|
for (const q of route.args.query) {
|
|
632
702
|
const value = req.query[q.name];
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
schema
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
703
|
+
const openapiSchema = getParamSchemaFromIndex(paramSchemaIndex, "query", q.name);
|
|
704
|
+
let schema = {};
|
|
705
|
+
if (openapiSchema) {
|
|
706
|
+
schema = resolveSchema(openapiSchema, openapi.components.schemas);
|
|
707
|
+
} else {
|
|
708
|
+
if (q.schemaType) {
|
|
709
|
+
const type = Array.isArray(q.schemaType) ? q.schemaType[0] : q.schemaType;
|
|
710
|
+
schema.type = type;
|
|
711
|
+
}
|
|
712
|
+
if (q.schemaRef && q.schemaRef.includes("Inline")) {
|
|
713
|
+
const inlineSchema = getSchemaByRef(q.schemaRef);
|
|
714
|
+
if (inlineSchema) {
|
|
715
|
+
Object.assign(schema, inlineSchema);
|
|
716
|
+
}
|
|
642
717
|
}
|
|
643
718
|
}
|
|
644
|
-
const coerced =
|
|
719
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, openapi.components.schemas);
|
|
645
720
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
646
721
|
const validate = validator.compile(schema);
|
|
647
722
|
const valid = validate(coerced);
|
|
@@ -659,18 +734,23 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
659
734
|
}
|
|
660
735
|
for (const p of route.args.path) {
|
|
661
736
|
const value = req.params[p.name];
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
schema
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
737
|
+
const openapiSchema = getParamSchemaFromIndex(paramSchemaIndex, "path", p.name);
|
|
738
|
+
let schema = {};
|
|
739
|
+
if (openapiSchema) {
|
|
740
|
+
schema = resolveSchema(openapiSchema, openapi.components.schemas);
|
|
741
|
+
} else {
|
|
742
|
+
if (p.schemaType) {
|
|
743
|
+
const type = Array.isArray(p.schemaType) ? p.schemaType[0] : p.schemaType;
|
|
744
|
+
schema.type = type;
|
|
745
|
+
}
|
|
746
|
+
if (p.schemaRef && p.schemaRef.includes("Inline")) {
|
|
747
|
+
const inlineSchema = getSchemaByRef(p.schemaRef);
|
|
748
|
+
if (inlineSchema) {
|
|
749
|
+
Object.assign(schema, inlineSchema);
|
|
750
|
+
}
|
|
671
751
|
}
|
|
672
752
|
}
|
|
673
|
-
const coerced =
|
|
753
|
+
const coerced = coerceParamValue(value, schema, { dateTime: false, date: false }, openapi.components.schemas);
|
|
674
754
|
if (Object.keys(schema).length > 0 && coerced !== void 0) {
|
|
675
755
|
const validate = validator.compile(schema);
|
|
676
756
|
const valid = validate(coerced);
|
|
@@ -688,23 +768,127 @@ function validateRequest(route, req, openapi, validator) {
|
|
|
688
768
|
}
|
|
689
769
|
return errors.length > 0 ? errors : null;
|
|
690
770
|
}
|
|
691
|
-
function
|
|
771
|
+
function resolveSchema(schema, components, seen = /* @__PURE__ */ new Set()) {
|
|
772
|
+
const ref = schema.$ref;
|
|
773
|
+
if (typeof ref !== "string" || !ref.startsWith("#/components/schemas/")) {
|
|
774
|
+
return schema;
|
|
775
|
+
}
|
|
776
|
+
const name = ref.replace("#/components/schemas/", "");
|
|
777
|
+
if (seen.has(name)) return schema;
|
|
778
|
+
const next = components[name];
|
|
779
|
+
if (!next) return schema;
|
|
780
|
+
seen.add(name);
|
|
781
|
+
return resolveSchema(next, components, seen);
|
|
782
|
+
}
|
|
783
|
+
function coerceDatesWithSchema(value, schema, dateCoercion, components) {
|
|
784
|
+
if (!schema || !dateCoercion.date && !dateCoercion.dateTime) return value;
|
|
785
|
+
return coerceWithSchema(value, schema, dateCoercion, components, { coercePrimitives: false });
|
|
786
|
+
}
|
|
787
|
+
function coerceParamValue(value, schema, dateCoercion, components) {
|
|
788
|
+
if (!schema) return value;
|
|
789
|
+
return coerceWithSchema(value, schema, dateCoercion, components, { coercePrimitives: true });
|
|
790
|
+
}
|
|
791
|
+
function coerceWithSchema(value, schema, dateCoercion, components, options) {
|
|
792
|
+
if (value === void 0 || value === null) return value;
|
|
793
|
+
if (value instanceof Date) return value;
|
|
794
|
+
const resolved = resolveSchema(schema, components);
|
|
795
|
+
const override = resolved["x-adorn-coerce"];
|
|
796
|
+
const allowDateTime = override === true ? true : override === false ? false : dateCoercion.dateTime;
|
|
797
|
+
const allowDate = override === true ? true : override === false ? false : dateCoercion.date;
|
|
798
|
+
const byFormat = coerceDateString(value, resolved, allowDateTime, allowDate);
|
|
799
|
+
if (byFormat !== value) return byFormat;
|
|
800
|
+
const allOf = resolved.allOf;
|
|
801
|
+
if (Array.isArray(allOf)) {
|
|
802
|
+
let out = value;
|
|
803
|
+
for (const entry of allOf) {
|
|
804
|
+
out = coerceWithSchema(out, entry, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
805
|
+
}
|
|
806
|
+
return out;
|
|
807
|
+
}
|
|
808
|
+
const variants = resolved.oneOf ?? resolved.anyOf;
|
|
809
|
+
if (Array.isArray(variants)) {
|
|
810
|
+
for (const entry of variants) {
|
|
811
|
+
const out = coerceWithSchema(value, entry, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
812
|
+
if (out !== value) return out;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
const schemaType = resolved.type;
|
|
816
|
+
const types = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
|
|
817
|
+
if ((types.includes("array") || resolved.items) && Array.isArray(value)) {
|
|
818
|
+
const itemSchema = resolved.items ?? {};
|
|
819
|
+
return value.map((item) => coerceWithSchema(item, itemSchema, { dateTime: allowDateTime, date: allowDate }, components, options));
|
|
820
|
+
}
|
|
821
|
+
if ((types.includes("object") || resolved.properties || resolved.additionalProperties) && isPlainObject(value)) {
|
|
822
|
+
const props = resolved.properties;
|
|
823
|
+
const out = { ...value };
|
|
824
|
+
if (props) {
|
|
825
|
+
for (const [key, propSchema] of Object.entries(props)) {
|
|
826
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
827
|
+
out[key] = coerceWithSchema(value[key], propSchema, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
const additional = resolved.additionalProperties;
|
|
832
|
+
if (additional && typeof additional === "object") {
|
|
833
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
834
|
+
if (props && Object.prototype.hasOwnProperty.call(props, key)) continue;
|
|
835
|
+
out[key] = coerceWithSchema(entry, additional, { dateTime: allowDateTime, date: allowDate }, components, options);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
return out;
|
|
839
|
+
}
|
|
840
|
+
if (options.coercePrimitives) {
|
|
841
|
+
return coercePrimitiveValue(value, types);
|
|
842
|
+
}
|
|
843
|
+
return value;
|
|
844
|
+
}
|
|
845
|
+
function coerceDateString(value, schema, allowDateTime, allowDate) {
|
|
846
|
+
if (typeof value !== "string") return value;
|
|
847
|
+
const format = schema.format;
|
|
848
|
+
const schemaType = schema.type;
|
|
849
|
+
const types = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
|
|
850
|
+
const allowsString = types.length === 0 || types.includes("string");
|
|
851
|
+
if (format === "date-time" && allowDateTime && allowsString) {
|
|
852
|
+
const parsed = new Date(value);
|
|
853
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
854
|
+
throw new Error(`Invalid date-time: ${value}`);
|
|
855
|
+
}
|
|
856
|
+
return parsed;
|
|
857
|
+
}
|
|
858
|
+
if (format === "date" && allowDate && allowsString) {
|
|
859
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
860
|
+
throw new Error(`Invalid date: ${value}`);
|
|
861
|
+
}
|
|
862
|
+
const parsed = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
|
|
863
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
864
|
+
throw new Error(`Invalid date: ${value}`);
|
|
865
|
+
}
|
|
866
|
+
return parsed;
|
|
867
|
+
}
|
|
868
|
+
return value;
|
|
869
|
+
}
|
|
870
|
+
function coercePrimitiveValue(value, types) {
|
|
692
871
|
if (value === void 0 || value === null) return value;
|
|
693
|
-
|
|
694
|
-
if (type === "number" || type === "integer") {
|
|
872
|
+
if (types.includes("number") || types.includes("integer")) {
|
|
695
873
|
const num = Number(value);
|
|
696
|
-
if (isNaN(num)) {
|
|
874
|
+
if (Number.isNaN(num)) {
|
|
697
875
|
throw new Error(`Invalid number: ${value}`);
|
|
698
876
|
}
|
|
699
877
|
return num;
|
|
700
878
|
}
|
|
701
|
-
if (
|
|
879
|
+
if (types.includes("boolean")) {
|
|
702
880
|
if (value === "true") return true;
|
|
703
881
|
if (value === "false") return false;
|
|
882
|
+
if (typeof value === "boolean") return value;
|
|
704
883
|
throw new Error(`Invalid boolean: ${value}`);
|
|
705
884
|
}
|
|
706
885
|
return value;
|
|
707
886
|
}
|
|
887
|
+
function isPlainObject(value) {
|
|
888
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
889
|
+
const proto = Object.getPrototypeOf(value);
|
|
890
|
+
return proto === Object.prototype || proto === null;
|
|
891
|
+
}
|
|
708
892
|
function parseQueryValue(value, param) {
|
|
709
893
|
if (value === void 0 || value === null) return value;
|
|
710
894
|
const isArray = Array.isArray(param.schemaType) ? param.schemaType.includes("array") : param.schemaType === "array";
|