adorn-api 1.0.12 → 1.0.13

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.
Files changed (43) hide show
  1. package/dist/adapter/express/bootstrap.d.ts.map +1 -1
  2. package/dist/adapter/express/merge.d.ts.map +1 -1
  3. package/dist/adapter/express/router.d.ts.map +1 -1
  4. package/dist/cli.cjs +799 -409
  5. package/dist/cli.cjs.map +1 -1
  6. package/dist/cli.js +799 -409
  7. package/dist/cli.js.map +1 -1
  8. package/dist/compiler/cache/isStale.d.ts.map +1 -1
  9. package/dist/compiler/cache/writeCache.d.ts.map +1 -1
  10. package/dist/compiler/schema/intersectionHandler.d.ts +7 -0
  11. package/dist/compiler/schema/intersectionHandler.d.ts.map +1 -0
  12. package/dist/compiler/schema/objectHandler.d.ts +20 -0
  13. package/dist/compiler/schema/objectHandler.d.ts.map +1 -0
  14. package/dist/compiler/schema/openapi.d.ts +1 -1
  15. package/dist/compiler/schema/openapi.d.ts.map +1 -1
  16. package/dist/compiler/schema/parameters.d.ts +18 -0
  17. package/dist/compiler/schema/parameters.d.ts.map +1 -0
  18. package/dist/compiler/schema/primitives.d.ts +10 -0
  19. package/dist/compiler/schema/primitives.d.ts.map +1 -0
  20. package/dist/compiler/schema/typeToJsonSchema.d.ts +2 -51
  21. package/dist/compiler/schema/typeToJsonSchema.d.ts.map +1 -1
  22. package/dist/compiler/schema/types.d.ts +54 -0
  23. package/dist/compiler/schema/types.d.ts.map +1 -0
  24. package/dist/compiler/schema/unionHandler.d.ts +10 -0
  25. package/dist/compiler/schema/unionHandler.d.ts.map +1 -0
  26. package/dist/express.cjs +41 -44
  27. package/dist/express.cjs.map +1 -1
  28. package/dist/express.js +41 -44
  29. package/dist/express.js.map +1 -1
  30. package/dist/http.d.ts +1 -2
  31. package/dist/http.d.ts.map +1 -1
  32. package/dist/index.cjs +1 -1
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/metal/index.cjs +2 -2
  37. package/dist/metal/index.cjs.map +1 -1
  38. package/dist/metal/index.js +2 -2
  39. package/dist/metal/index.js.map +1 -1
  40. package/dist/metal/listQuery.d.ts.map +1 -1
  41. package/dist/metal/queryOptions.d.ts.map +1 -1
  42. package/dist/metal/registerMetalEntities.d.ts.map +1 -1
  43. package/package.json +4 -1
package/dist/cli.cjs CHANGED
@@ -103,7 +103,7 @@ function analyzeClass(node, sourceFile, checker) {
103
103
  produces
104
104
  };
105
105
  }
106
- function extractClassConsumes(node, checker) {
106
+ function extractClassConsumes(node, _checker) {
107
107
  const decorator = findDecorator(node, "Consumes");
108
108
  if (!decorator) return void 0;
109
109
  const callExpr = decorator.expression;
@@ -119,7 +119,7 @@ function extractClassConsumes(node, checker) {
119
119
  }
120
120
  return void 0;
121
121
  }
122
- function extractClassProduces(node, checker) {
122
+ function extractClassProduces(node, _checker) {
123
123
  const decorator = findDecorator(node, "Produces");
124
124
  if (!decorator) return void 0;
125
125
  const callExpr = decorator.expression;
@@ -301,7 +301,7 @@ function extractDecoratorStringArg(decorator) {
301
301
  }
302
302
  return null;
303
303
  }
304
- function unwrapPromise(type, checker) {
304
+ function unwrapPromise(type, _checker) {
305
305
  const symbol = type.getSymbol();
306
306
  if (symbol?.getName() === "Promise") {
307
307
  const typeArgs = type.typeArguments;
@@ -322,12 +322,15 @@ function unwrapPromiseTypeNode(typeNode) {
322
322
  }
323
323
 
324
324
  // src/compiler/schema/openapi.ts
325
- var import_typescript5 = __toESM(require("typescript"), 1);
325
+ var import_typescript9 = __toESM(require("typescript"), 1);
326
326
 
327
327
  // src/compiler/schema/typeToJsonSchema.ts
328
+ var import_typescript7 = __toESM(require("typescript"), 1);
329
+
330
+ // src/compiler/schema/primitives.ts
328
331
  var import_typescript3 = __toESM(require("typescript"), 1);
329
- function typeToJsonSchema(type, ctx, typeNode) {
330
- const { checker } = ctx;
332
+ function handlePrimitiveType(type, ctx, typeNode) {
333
+ const { checker, propertyName } = ctx;
331
334
  if (type.flags & import_typescript3.default.TypeFlags.Undefined) {
332
335
  return {};
333
336
  }
@@ -341,7 +344,7 @@ function typeToJsonSchema(type, ctx, typeNode) {
341
344
  return { type: "string" };
342
345
  }
343
346
  if (type.flags & import_typescript3.default.TypeFlags.Number) {
344
- return normalizeNumericType(type, checker, typeNode);
347
+ return normalizeNumericType(type, checker, typeNode, propertyName);
345
348
  }
346
349
  if (type.flags & import_typescript3.default.TypeFlags.Boolean) {
347
350
  return { type: "boolean" };
@@ -365,26 +368,7 @@ function typeToJsonSchema(type, ctx, typeNode) {
365
368
  const intrinsic = type.intrinsicName;
366
369
  return { type: "boolean", enum: [intrinsic === "true"] };
367
370
  }
368
- if (type.isUnion()) {
369
- return handleUnion(type, ctx, typeNode);
370
- }
371
- if (type.isIntersection()) {
372
- return handleIntersection(type, ctx, typeNode);
373
- }
374
- if (checker.isArrayType(type)) {
375
- const typeArgs = type.typeArguments;
376
- const itemType = typeArgs?.[0];
377
- const items = itemType ? typeToJsonSchema(itemType, ctx) : {};
378
- return {
379
- type: "array",
380
- items,
381
- uniqueItems: isSetType(type, checker) ? true : void 0
382
- };
383
- }
384
- if (type.flags & import_typescript3.default.TypeFlags.Object) {
385
- return handleObjectType(type, ctx, typeNode);
386
- }
387
- return {};
371
+ return null;
388
372
  }
389
373
  function isDateType(type, checker) {
390
374
  const symbol = type.getSymbol();
@@ -399,53 +383,51 @@ function isDateType(type, checker) {
399
383
  }
400
384
  return symbol?.getName() === "Date";
401
385
  }
402
- function isSetType(type, checker) {
403
- const symbol = type.getSymbol();
404
- if (!symbol) return false;
405
- const name = symbol.getName();
406
- if (name === "Set") return true;
407
- return false;
408
- }
409
- function getSchemaName(type, typeNode) {
410
- const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
411
- const aliasName = aliasSymbol?.getName();
412
- if (aliasName && aliasName !== "__type") {
413
- return aliasName;
386
+ function normalizeNumericType(type, checker, typeNode, propertyName) {
387
+ const typeName = getExplicitTypeNameFromNode(typeNode) ?? null;
388
+ const symbol = getEffectiveSymbol(type, checker);
389
+ const symbolName = symbol?.getName() ?? null;
390
+ if (shouldBeIntegerType(typeName) || shouldBeIntegerType(symbolName) || shouldBeIntegerType(propertyName ?? null)) {
391
+ return { type: "integer" };
414
392
  }
415
- const symbol = type.getSymbol();
416
- const symbolName = symbol?.getName?.();
417
- if (symbolName && symbolName !== "__type") {
418
- return symbolName;
393
+ return { type: "number" };
394
+ }
395
+ function shouldBeIntegerType(typeName) {
396
+ if (!typeName) return false;
397
+ const lower = typeName.toLowerCase();
398
+ return lower === "id" || lower.endsWith("id") || lower === "primarykey" || lower === "pk" || lower === "page" || lower === "pagesize" || lower === "totalitems" || lower === "limit" || lower === "offset";
399
+ }
400
+ function getExplicitTypeNameFromNode(typeNode) {
401
+ if (!typeNode) return null;
402
+ if (import_typescript3.default.isTypeReferenceNode(typeNode)) {
403
+ if (import_typescript3.default.isIdentifier(typeNode.typeName)) {
404
+ return typeNode.typeName.text;
405
+ }
419
406
  }
420
- const nodeName = getExplicitTypeNameFromNode(typeNode);
421
- if (nodeName && nodeName !== "__type") {
422
- return nodeName;
407
+ if (import_typescript3.default.isTypeAliasDeclaration(typeNode.parent)) {
408
+ if (import_typescript3.default.isIdentifier(typeNode.parent.name)) {
409
+ return typeNode.parent.name.text;
410
+ }
423
411
  }
424
412
  return null;
425
413
  }
426
- function buildNamedSchema(type, ctx, typeNode, build) {
427
- const name = getSchemaName(type, typeNode);
428
- if (!name) {
429
- return build();
430
- }
431
- const { components, typeStack } = ctx;
432
- if (components.has(name) || typeStack.has(type)) {
433
- return { $ref: `#/components/schemas/${name}` };
434
- }
435
- typeStack.add(type);
436
- const schema = build();
437
- typeStack.delete(type);
438
- if (!components.has(name)) {
439
- components.set(name, schema);
414
+ function getEffectiveSymbol(type, checker) {
415
+ const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
416
+ if (aliasSymbol && aliasSymbol.flags & import_typescript3.default.SymbolFlags.Alias) {
417
+ return checker.getAliasedSymbol(aliasSymbol);
440
418
  }
441
- return { $ref: `#/components/schemas/${name}` };
419
+ return type.getSymbol() ?? null;
442
420
  }
421
+
422
+ // src/compiler/schema/unionHandler.ts
423
+ var import_typescript4 = __toESM(require("typescript"), 1);
443
424
  function handleUnion(type, ctx, typeNode) {
444
425
  return buildNamedSchema(type, ctx, typeNode, () => {
445
426
  const types = type.types;
446
- const nullType = types.find((t) => t.flags & import_typescript3.default.TypeFlags.Null);
447
- const otherTypes = types.filter((t) => !(t.flags & import_typescript3.default.TypeFlags.Null) && !(t.flags & import_typescript3.default.TypeFlags.Undefined));
448
- const allStringLiterals = otherTypes.every((t) => t.flags & import_typescript3.default.TypeFlags.StringLiteral);
427
+ const nullType = types.find((t) => t.flags & import_typescript4.default.TypeFlags.Null);
428
+ const undefinedType = types.find((t) => t.flags & import_typescript4.default.TypeFlags.Undefined);
429
+ const otherTypes = types.filter((t) => !(t.flags & import_typescript4.default.TypeFlags.Null) && !(t.flags & import_typescript4.default.TypeFlags.Undefined));
430
+ const allStringLiterals = otherTypes.every((t) => t.flags & import_typescript4.default.TypeFlags.StringLiteral);
449
431
  if (allStringLiterals && otherTypes.length > 0) {
450
432
  const enumValues = otherTypes.map((t) => t.value);
451
433
  const schema = { type: "string", enum: enumValues };
@@ -454,6 +436,14 @@ function handleUnion(type, ctx, typeNode) {
454
436
  }
455
437
  return schema;
456
438
  }
439
+ const allBooleanLiterals = otherTypes.length > 0 && otherTypes.every((t) => t.flags & import_typescript4.default.TypeFlags.BooleanLiteral);
440
+ if (allBooleanLiterals) {
441
+ const schema = { type: "boolean" };
442
+ if (nullType || undefinedType) {
443
+ schema.type = ["boolean", "null"];
444
+ }
445
+ return schema;
446
+ }
457
447
  if (otherTypes.length === 1 && nullType) {
458
448
  const innerSchema = typeToJsonSchema(otherTypes[0], ctx);
459
449
  if (typeof innerSchema.type === "string") {
@@ -483,49 +473,7 @@ function handleUnion(type, ctx, typeNode) {
483
473
  return {};
484
474
  });
485
475
  }
486
- function handleIntersection(type, ctx, typeNode) {
487
- return buildNamedSchema(type, ctx, typeNode, () => {
488
- const types = type.types;
489
- const brandCollapsed = tryCollapseBrandedIntersection(types, ctx, typeNode);
490
- if (brandCollapsed) {
491
- return brandCollapsed;
492
- }
493
- const allOf = [];
494
- for (const t of types) {
495
- allOf.push(typeToJsonSchema(t, ctx));
496
- }
497
- return { allOf };
498
- });
499
- }
500
- function tryCollapseBrandedIntersection(types, ctx, typeNode) {
501
- const { checker } = ctx;
502
- const parts = [...types];
503
- const prim = parts.find(isPrimitiveLike);
504
- if (!prim) return null;
505
- const rest = parts.filter((p) => p !== prim);
506
- if (rest.every((r) => isBrandObject(checker, r, ctx))) {
507
- return typeToJsonSchema(prim, ctx);
508
- }
509
- return null;
510
- }
511
- function isPrimitiveLike(t) {
512
- return (t.flags & (import_typescript3.default.TypeFlags.String | import_typescript3.default.TypeFlags.Number | import_typescript3.default.TypeFlags.Boolean | import_typescript3.default.TypeFlags.BigInt)) !== 0 || (t.flags & import_typescript3.default.TypeFlags.StringLiteral) !== 0 || (t.flags & import_typescript3.default.TypeFlags.NumberLiteral) !== 0;
513
- }
514
- function isBrandObject(checker, t, ctx) {
515
- if (!(t.flags & import_typescript3.default.TypeFlags.Object)) return false;
516
- const props = t.getProperties();
517
- if (props.length === 0) return false;
518
- const allowed = /* @__PURE__ */ new Set(["__brand", "__type", "__tag", "brand"]);
519
- for (const p of props) {
520
- if (!allowed.has(p.getName())) return false;
521
- }
522
- const callSigs = t.getCallSignatures?.();
523
- if (callSigs && callSigs.length > 0) return false;
524
- const constructSigs = t.getConstructSignatures?.();
525
- if (constructSigs && constructSigs.length > 0) return false;
526
- return true;
527
- }
528
- function detectDiscriminatedUnion(types, ctx, branches) {
476
+ function detectDiscriminatedUnion(types, ctx, _branches) {
529
477
  if (types.length < 2) return null;
530
478
  const candidates = findCommonPropertyNames(ctx.checker, types);
531
479
  for (const propName of candidates) {
@@ -556,10 +504,10 @@ function findCommonPropertyNames(checker, types) {
556
504
  function isRequiredProperty(checker, type, propName) {
557
505
  const sym = checker.getPropertyOfType(type, propName);
558
506
  if (!sym) return false;
559
- if (sym.flags & import_typescript3.default.SymbolFlags.Optional) return false;
507
+ if (sym.flags & import_typescript4.default.SymbolFlags.Optional) return false;
560
508
  const propType = checker.getTypeOfSymbol(sym);
561
509
  if (propType.isUnion?.()) {
562
- const hasUndefined = propType.types.some((t) => (t.flags & import_typescript3.default.TypeFlags.Undefined) !== 0);
510
+ const hasUndefined = propType.types.some((t) => (t.flags & import_typescript4.default.TypeFlags.Undefined) !== 0);
563
511
  if (hasUndefined) return false;
564
512
  }
565
513
  return true;
@@ -602,14 +550,187 @@ function getBranchSchemaName(type, ctx) {
602
550
  }
603
551
  return `Anonymous_${ctx.typeNameStack.length}`;
604
552
  }
553
+ function buildNamedSchema(type, ctx, typeNode, build) {
554
+ const name = getSchemaName(type, typeNode);
555
+ if (!name) {
556
+ return build();
557
+ }
558
+ const { components, typeStack } = ctx;
559
+ if (components.has(name) || typeStack.has(type)) {
560
+ return { $ref: `#/components/schemas/${name}` };
561
+ }
562
+ typeStack.add(type);
563
+ const schema = build();
564
+ typeStack.delete(type);
565
+ if (!components.has(name)) {
566
+ components.set(name, schema);
567
+ }
568
+ return { $ref: `#/components/schemas/${name}` };
569
+ }
570
+ function getSchemaName(type, typeNode) {
571
+ const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
572
+ const aliasName = aliasSymbol?.getName();
573
+ if (aliasName && aliasName !== "__type") {
574
+ return aliasName;
575
+ }
576
+ const symbol = type.getSymbol();
577
+ const symbolName = symbol?.getName?.();
578
+ if (symbolName && symbolName !== "__type") {
579
+ return symbolName;
580
+ }
581
+ const nodeName = getExplicitTypeNameFromNode2(typeNode);
582
+ if (nodeName && nodeName !== "__type") {
583
+ return nodeName;
584
+ }
585
+ return null;
586
+ }
587
+ function getExplicitTypeNameFromNode2(typeNode) {
588
+ if (!typeNode) return null;
589
+ if (import_typescript4.default.isTypeReferenceNode(typeNode)) {
590
+ if (import_typescript4.default.isIdentifier(typeNode.typeName)) {
591
+ return typeNode.typeName.text;
592
+ }
593
+ }
594
+ if (import_typescript4.default.isTypeAliasDeclaration(typeNode.parent)) {
595
+ if (import_typescript4.default.isIdentifier(typeNode.parent.name)) {
596
+ return typeNode.parent.name.text;
597
+ }
598
+ }
599
+ return null;
600
+ }
601
+
602
+ // src/compiler/schema/intersectionHandler.ts
603
+ var import_typescript5 = __toESM(require("typescript"), 1);
604
+ function handleIntersection(type, ctx, typeNode) {
605
+ return buildNamedSchema2(type, ctx, typeNode, () => {
606
+ const types = type.types;
607
+ const brandCollapsed = tryCollapseBrandedIntersection(types, ctx, typeNode);
608
+ if (brandCollapsed) {
609
+ return brandCollapsed;
610
+ }
611
+ const allOf = [];
612
+ for (const t of types) {
613
+ const schema = typeToJsonSchema(t, ctx);
614
+ if (Object.keys(schema).length > 0) {
615
+ if (isEmptyObjectSchema(schema)) {
616
+ continue;
617
+ }
618
+ allOf.push(schema);
619
+ }
620
+ }
621
+ if (allOf.length === 0) {
622
+ return {};
623
+ }
624
+ if (allOf.length === 1) {
625
+ return allOf[0];
626
+ }
627
+ return { allOf };
628
+ });
629
+ }
630
+ function tryCollapseBrandedIntersection(types, ctx, _typeNode) {
631
+ const { checker } = ctx;
632
+ const parts = [...types];
633
+ const prim = parts.find(isPrimitiveLike);
634
+ if (!prim) return null;
635
+ const rest = parts.filter((p) => p !== prim);
636
+ if (rest.every((r) => isBrandObject(checker, r, ctx))) {
637
+ return typeToJsonSchema(prim, ctx);
638
+ }
639
+ return null;
640
+ }
641
+ function isPrimitiveLike(t) {
642
+ return (t.flags & (import_typescript5.default.TypeFlags.String | import_typescript5.default.TypeFlags.Number | import_typescript5.default.TypeFlags.Boolean | import_typescript5.default.TypeFlags.BigInt)) !== 0 || (t.flags & import_typescript5.default.TypeFlags.StringLiteral) !== 0 || (t.flags & import_typescript5.default.TypeFlags.NumberLiteral) !== 0;
643
+ }
644
+ function isBrandObject(checker, t, _ctx) {
645
+ if (!(t.flags & import_typescript5.default.TypeFlags.Object)) return false;
646
+ const props = t.getProperties();
647
+ if (props.length === 0) return false;
648
+ const allowed = /* @__PURE__ */ new Set(["__brand", "__type", "__tag", "brand"]);
649
+ for (const p of props) {
650
+ if (!allowed.has(p.getName())) return false;
651
+ }
652
+ const callSigs = t.getCallSignatures?.();
653
+ if (callSigs && callSigs.length > 0) return false;
654
+ const constructSigs = t.getConstructSignatures?.();
655
+ if (constructSigs && constructSigs.length > 0) return false;
656
+ return true;
657
+ }
658
+ function isEmptyObjectSchema(schema) {
659
+ if (schema.type !== "object") {
660
+ return false;
661
+ }
662
+ if (!schema.properties || Object.keys(schema.properties).length === 0) {
663
+ if (!schema.additionalProperties) {
664
+ return true;
665
+ }
666
+ }
667
+ return false;
668
+ }
669
+ function buildNamedSchema2(type, ctx, typeNode, build) {
670
+ const name = getSchemaName2(type, typeNode);
671
+ if (!name) {
672
+ return build();
673
+ }
674
+ const { components, typeStack } = ctx;
675
+ if (components.has(name) || typeStack.has(type)) {
676
+ return { $ref: `#/components/schemas/${name}` };
677
+ }
678
+ typeStack.add(type);
679
+ const schema = build();
680
+ typeStack.delete(type);
681
+ if (!components.has(name)) {
682
+ components.set(name, schema);
683
+ }
684
+ return { $ref: `#/components/schemas/${name}` };
685
+ }
686
+ function getSchemaName2(type, typeNode) {
687
+ const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
688
+ const aliasName = aliasSymbol?.getName();
689
+ if (aliasName && aliasName !== "__type") {
690
+ return aliasName;
691
+ }
692
+ const symbol = type.getSymbol();
693
+ const symbolName = symbol?.getName?.();
694
+ if (symbolName && symbolName !== "__type") {
695
+ return symbolName;
696
+ }
697
+ const nodeName = getExplicitTypeNameFromNode3(typeNode);
698
+ if (nodeName && nodeName !== "__type") {
699
+ return nodeName;
700
+ }
701
+ return null;
702
+ }
703
+ function getExplicitTypeNameFromNode3(typeNode) {
704
+ if (!typeNode) return null;
705
+ if (import_typescript5.default.isTypeReferenceNode(typeNode)) {
706
+ if (import_typescript5.default.isIdentifier(typeNode.typeName)) {
707
+ return typeNode.typeName.text;
708
+ }
709
+ }
710
+ if (import_typescript5.default.isTypeAliasDeclaration(typeNode.parent)) {
711
+ if (import_typescript5.default.isIdentifier(typeNode.parent.name)) {
712
+ return typeNode.parent.name.text;
713
+ }
714
+ }
715
+ return null;
716
+ }
717
+
718
+ // src/compiler/schema/objectHandler.ts
719
+ var import_typescript6 = __toESM(require("typescript"), 1);
605
720
  function handleObjectType(type, ctx, typeNode) {
606
- const { checker, components, typeStack, mode } = ctx;
721
+ const { checker, components, typeStack } = ctx;
607
722
  const symbol = type.getSymbol();
608
723
  const typeName = symbol?.getName?.() ?? getTypeNameFromNode(typeNode, ctx);
609
724
  if (isMetalOrmWrapperType(type, checker)) {
610
725
  return handleMetalOrmWrapper(type, ctx);
611
726
  }
612
727
  if (typeName && typeName !== "__type") {
728
+ const isMetalOrmGeneric = METAL_ORM_WRAPPER_NAMES.some(
729
+ (name) => typeName === name || typeName.endsWith("Api")
730
+ );
731
+ if (isMetalOrmGeneric) {
732
+ return {};
733
+ }
613
734
  if (components.has(typeName)) {
614
735
  return { $ref: `#/components/schemas/${typeName}` };
615
736
  }
@@ -630,40 +751,7 @@ function handleObjectType(type, ctx, typeNode) {
630
751
  typeStack.delete(type);
631
752
  return schema;
632
753
  }
633
- function getExplicitTypeNameFromNode(typeNode) {
634
- if (!typeNode) return null;
635
- if (import_typescript3.default.isTypeReferenceNode(typeNode)) {
636
- if (import_typescript3.default.isIdentifier(typeNode.typeName)) {
637
- return typeNode.typeName.text;
638
- }
639
- }
640
- if (import_typescript3.default.isTypeAliasDeclaration(typeNode.parent)) {
641
- if (import_typescript3.default.isIdentifier(typeNode.parent.name)) {
642
- return typeNode.parent.name.text;
643
- }
644
- }
645
- return null;
646
- }
647
- function shouldBeIntegerType(typeName) {
648
- if (!typeName) return false;
649
- const lower = typeName.toLowerCase();
650
- return lower === "id" || lower.endsWith("id") || lower === "primarykey" || lower === "pk";
651
- }
652
- function normalizeNumericType(type, checker, typeNode) {
653
- const typeName = getExplicitTypeNameFromNode(typeNode) ?? null;
654
- const symbol = getEffectiveSymbol(type, checker);
655
- const symbolName = symbol?.getName() ?? null;
656
- if (shouldBeIntegerType(typeName) || shouldBeIntegerType(symbolName)) {
657
- return { type: "integer" };
658
- }
659
- return { type: "number" };
660
- }
661
- function getTypeNameFromNode(typeNode, ctx) {
662
- const explicitName = getExplicitTypeNameFromNode(typeNode);
663
- if (explicitName) return explicitName;
664
- return `Anonymous_${ctx.typeNameStack.length}`;
665
- }
666
- function buildObjectSchema(type, ctx, typeNode) {
754
+ function buildObjectSchema(type, ctx, _typeNode) {
667
755
  const { checker, mode } = ctx;
668
756
  const properties = {};
669
757
  const required = [];
@@ -677,9 +765,10 @@ function buildObjectSchema(type, ctx, typeNode) {
677
765
  if (isMethodLike(propType)) {
678
766
  continue;
679
767
  }
680
- const isOptional = !!(prop.flags & import_typescript3.default.SymbolFlags.Optional);
768
+ const isOptional = !!(prop.flags & import_typescript6.default.SymbolFlags.Optional);
681
769
  const isRelation = isMetalOrmWrapperType(propType, checker);
682
- properties[propName] = typeToJsonSchema(propType, ctx);
770
+ const propCtx = { ...ctx, propertyName: propName };
771
+ properties[propName] = typeToJsonSchema(propType, propCtx);
683
772
  const shouldRequire = mode === "response" ? !isRelation && !isOptional : !isOptional;
684
773
  if (shouldRequire) {
685
774
  required.push(propName);
@@ -700,14 +789,14 @@ function buildObjectSchema(type, ctx, typeNode) {
700
789
  }
701
790
  return schema;
702
791
  }
703
- function isRecordType(type, checker) {
792
+ function isRecordType(type, _checker) {
704
793
  const symbol = type.getSymbol();
705
794
  if (!symbol) return false;
706
795
  const name = symbol.getName();
707
796
  if (name === "Record") return true;
708
797
  return false;
709
798
  }
710
- function getRecordValueType(type, checker) {
799
+ function getRecordValueType(type, _checker) {
711
800
  const symbol = type.getSymbol();
712
801
  if (!symbol) return null;
713
802
  const name = symbol.getName();
@@ -720,24 +809,8 @@ function getRecordValueType(type, checker) {
720
809
  }
721
810
  return null;
722
811
  }
723
- var METAL_ORM_WRAPPER_NAMES = ["HasManyCollection", "ManyToManyCollection", "BelongsToReference", "HasOneReference"];
724
812
  function isMetalOrmWrapperType(type, checker) {
725
- const aliasSymbol = type.aliasSymbol || type.symbol;
726
- if (!aliasSymbol) return false;
727
- return METAL_ORM_WRAPPER_NAMES.includes(aliasSymbol.getName());
728
- }
729
- function getWrapperTypeName(type, checker) {
730
- const symbol = getEffectiveSymbol(type, checker);
731
- if (!symbol) return null;
732
- const name = symbol.getName();
733
- return METAL_ORM_WRAPPER_NAMES.includes(name) ? name : null;
734
- }
735
- function getEffectiveSymbol(type, checker) {
736
- const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
737
- if (aliasSymbol && aliasSymbol.flags & import_typescript3.default.SymbolFlags.Alias) {
738
- return checker.getAliasedSymbol(aliasSymbol);
739
- }
740
- return type.getSymbol() ?? null;
813
+ return !!findMetalOrmWrapper(type, checker);
741
814
  }
742
815
  function isMethodLike(type) {
743
816
  const callSigs = type.getCallSignatures?.();
@@ -746,6 +819,69 @@ function isMethodLike(type) {
746
819
  function isIteratorOrSymbolProperty(propName) {
747
820
  return propName.startsWith("__@") || propName.startsWith("[") || propName === Symbol.iterator.toString();
748
821
  }
822
+ function getTypeNameFromNode(typeNode, _ctx) {
823
+ const explicitName = getExplicitTypeNameFromNode4(typeNode);
824
+ if (explicitName) return explicitName;
825
+ return "Anonymous_${ctx.typeNameStack.length}";
826
+ }
827
+ function getExplicitTypeNameFromNode4(typeNode) {
828
+ if (!typeNode) return null;
829
+ if (import_typescript6.default.isTypeReferenceNode(typeNode)) {
830
+ if (import_typescript6.default.isIdentifier(typeNode.typeName)) {
831
+ return typeNode.typeName.text;
832
+ }
833
+ }
834
+ if (import_typescript6.default.isTypeAliasDeclaration(typeNode.parent)) {
835
+ if (import_typescript6.default.isIdentifier(typeNode.parent.name)) {
836
+ return typeNode.parent.name.text;
837
+ }
838
+ }
839
+ return null;
840
+ }
841
+ var METAL_ORM_WRAPPER_NAMES = ["HasManyCollection", "ManyToManyCollection", "BelongsToReference", "HasOneReference"];
842
+ function findMetalOrmWrapper(type, checker) {
843
+ if (type.isIntersection()) {
844
+ let wrapperInfo = null;
845
+ let hasReadonlyArray = false;
846
+ for (const constituent of type.types) {
847
+ const result = findWrapperInType(constituent, checker);
848
+ if (result) {
849
+ wrapperInfo = result;
850
+ }
851
+ if (!(constituent.flags & import_typescript6.default.TypeFlags.Object)) continue;
852
+ const symbol = constituent.getSymbol();
853
+ if (symbol?.getName() === "ReadonlyArray") {
854
+ hasReadonlyArray = true;
855
+ }
856
+ }
857
+ if (wrapperInfo) {
858
+ return { ...wrapperInfo, isReadonlyArray: hasReadonlyArray };
859
+ }
860
+ return null;
861
+ }
862
+ return findWrapperInType(type, checker);
863
+ }
864
+ function findWrapperInType(type, checker) {
865
+ const aliasSymbol = type.aliasSymbol ?? type.aliasSymbol;
866
+ const symbol = type.getSymbol();
867
+ const effectiveSymbol = aliasSymbol && aliasSymbol.flags & import_typescript6.default.SymbolFlags.Alias ? checker.getAliasedSymbol(aliasSymbol) : symbol;
868
+ if (!effectiveSymbol) return null;
869
+ const name = effectiveSymbol.getName();
870
+ if (!METAL_ORM_WRAPPER_NAMES.includes(name)) return null;
871
+ const typeRef = type;
872
+ const typeArgs = typeRef.typeArguments || [];
873
+ return {
874
+ wrapperName: name,
875
+ targetTypeArgs: typeArgs,
876
+ isReadonlyArray: false
877
+ };
878
+ }
879
+ function getWrapperTypeName(type, _checker) {
880
+ const symbol = type.getSymbol();
881
+ if (!symbol) return null;
882
+ const name = symbol.getName();
883
+ return METAL_ORM_WRAPPER_NAMES.includes(name) ? name : null;
884
+ }
749
885
  function handleMetalOrmWrapper(type, ctx) {
750
886
  const typeRef = type;
751
887
  const typeArgs = typeRef.typeArguments;
@@ -764,30 +900,138 @@ function handleMetalOrmWrapper(type, ctx) {
764
900
  "x-metal-orm-rel": wrapperRel
765
901
  };
766
902
  }
767
- const targetSchema = targetType ? typeToJsonSchema(targetType, ctx) : {};
903
+ if (!targetType) {
904
+ return { "x-metal-orm-rel": wrapperRel };
905
+ }
906
+ if (wrapperName === "BelongsToReference" || wrapperName === "HasOneReference") {
907
+ return handleBelongsToReference(targetType, ctx, wrapperRel);
908
+ }
909
+ const targetSchema = typeToJsonSchema(targetType, ctx);
768
910
  return {
769
911
  ...targetSchema,
770
912
  "x-metal-orm-rel": wrapperRel
771
913
  };
772
914
  }
915
+ function handleBelongsToReference(targetType, ctx, wrapperRel) {
916
+ const { components } = ctx;
917
+ const targetSymbol = targetType.getSymbol();
918
+ const typeName = targetSymbol?.getName();
919
+ if (!typeName) {
920
+ return {
921
+ type: "object",
922
+ properties: {},
923
+ "x-metal-orm-rel": wrapperRel
924
+ };
925
+ }
926
+ const refSchemaName = `${typeName}Ref`;
927
+ if (components.has(refSchemaName)) {
928
+ return {
929
+ $ref: `#/components/schemas/${refSchemaName}`,
930
+ "x-metal-orm-rel": wrapperRel
931
+ };
932
+ }
933
+ const refSchema = buildRefSchema(targetType, ctx);
934
+ components.set(refSchemaName, refSchema);
935
+ return {
936
+ $ref: `#/components/schemas/${refSchemaName}`,
937
+ "x-metal-orm-rel": wrapperRel
938
+ };
939
+ }
940
+ function buildRefSchema(type, ctx) {
941
+ const { checker } = ctx;
942
+ if (!(type.flags & import_typescript6.default.TypeFlags.Object)) {
943
+ return { type: "object", properties: {} };
944
+ }
945
+ const objectType = type;
946
+ const properties = {};
947
+ const required = [];
948
+ const props = checker.getPropertiesOfType(objectType);
949
+ for (const prop of props) {
950
+ const propName = prop.getName();
951
+ if (isIteratorOrSymbolProperty(propName)) {
952
+ continue;
953
+ }
954
+ const propType = checker.getTypeOfSymbol(prop);
955
+ if (isMethodLike(propType)) {
956
+ continue;
957
+ }
958
+ const isOptional = !!(prop.flags & import_typescript6.default.SymbolFlags.Optional);
959
+ const isRelation = isMetalOrmWrapperType(propType, checker);
960
+ if (isRelation) {
961
+ continue;
962
+ }
963
+ const propCtx = { ...ctx, propertyName: propName };
964
+ properties[propName] = typeToJsonSchema(propType, propCtx);
965
+ if (!isOptional) {
966
+ required.push(propName);
967
+ }
968
+ }
969
+ const schema = {
970
+ type: "object",
971
+ properties
972
+ };
973
+ if (required.length > 0) {
974
+ schema.required = required;
975
+ }
976
+ return schema;
977
+ }
978
+
979
+ // src/compiler/schema/typeToJsonSchema.ts
980
+ function typeToJsonSchema(type, ctx, typeNode) {
981
+ const primitiveResult = handlePrimitiveType(type, ctx, typeNode);
982
+ if (primitiveResult) {
983
+ return primitiveResult;
984
+ }
985
+ if (type.isUnion()) {
986
+ return handleUnion(type, ctx, typeNode);
987
+ }
988
+ if (type.isIntersection()) {
989
+ return handleIntersection(type, ctx, typeNode);
990
+ }
991
+ if (ctx.checker.isArrayType(type)) {
992
+ const typeArgs = type.typeArguments;
993
+ const itemType = typeArgs?.[0];
994
+ const items = itemType ? typeToJsonSchema(itemType, ctx) : {};
995
+ return {
996
+ type: "array",
997
+ items,
998
+ uniqueItems: isSetType(type, ctx.checker) ? true : void 0
999
+ };
1000
+ }
1001
+ if (type.flags & import_typescript7.default.TypeFlags.Object) {
1002
+ const objectType = type;
1003
+ if (isMetalOrmWrapperType(type, ctx.checker)) {
1004
+ return handleMetalOrmWrapper(objectType, ctx);
1005
+ }
1006
+ return handleObjectType(objectType, ctx, typeNode);
1007
+ }
1008
+ return {};
1009
+ }
1010
+ function isSetType(type, _checker) {
1011
+ const symbol = type.getSymbol();
1012
+ if (!symbol) return false;
1013
+ const name = symbol.getName();
1014
+ if (name === "Set") return true;
1015
+ return false;
1016
+ }
773
1017
 
774
1018
  // src/compiler/schema/extractAnnotations.ts
775
- var import_typescript4 = __toESM(require("typescript"), 1);
1019
+ var import_typescript8 = __toESM(require("typescript"), 1);
776
1020
  function extractPropertySchemaFragments(checker, prop) {
777
- if (!import_typescript4.default.canHaveDecorators(prop)) return [];
778
- const decs = import_typescript4.default.getDecorators(prop);
1021
+ if (!import_typescript8.default.canHaveDecorators(prop)) return [];
1022
+ const decs = import_typescript8.default.getDecorators(prop);
779
1023
  if (!decs || decs.length === 0) return [];
780
1024
  const frags = [];
781
1025
  for (const d of decs) {
782
1026
  const expr = d.expression;
783
1027
  let callee;
784
1028
  let args;
785
- if (import_typescript4.default.isCallExpression(expr)) {
1029
+ if (import_typescript8.default.isCallExpression(expr)) {
786
1030
  callee = expr.expression;
787
1031
  args = expr.arguments;
788
1032
  } else {
789
1033
  callee = expr;
790
- args = import_typescript4.default.factory.createNodeArray([]);
1034
+ args = import_typescript8.default.factory.createNodeArray([]);
791
1035
  }
792
1036
  const sym = checker.getSymbolAtLocation(callee);
793
1037
  if (!sym) continue;
@@ -796,7 +1040,7 @@ function extractPropertySchemaFragments(checker, prop) {
796
1040
  const name = resolved.name;
797
1041
  if (name === "Schema") {
798
1042
  const obj = args[0];
799
- if (obj && import_typescript4.default.isObjectLiteralExpression(obj)) {
1043
+ if (obj && import_typescript8.default.isObjectLiteralExpression(obj)) {
800
1044
  const frag = objectLiteralToJson(obj);
801
1045
  if (frag) frags.push(frag);
802
1046
  }
@@ -818,7 +1062,7 @@ function extractPropertySchemaFragments(checker, prop) {
818
1062
  frags.push({ format: args[0].text });
819
1063
  } else if (name === "Pattern") {
820
1064
  const arg = args[0];
821
- if (arg && import_typescript4.default.isRegularExpressionLiteral(arg)) {
1065
+ if (arg && import_typescript8.default.isRegularExpressionLiteral(arg)) {
822
1066
  frags.push({ pattern: extractRegexPattern(arg.text) });
823
1067
  } else if (isStringLiteral(arg)) {
824
1068
  frags.push({ pattern: arg.text });
@@ -835,11 +1079,11 @@ function extractPropertySchemaFragments(checker, prop) {
835
1079
  frags.push({ multipleOf: Number(args[0].text) });
836
1080
  } else if (name === "Example") {
837
1081
  frags.push({ example: literalToJson(args[0]) });
838
- } else if (name === "Examples" && import_typescript4.default.isArrayLiteralExpression(args[0])) {
1082
+ } else if (name === "Examples" && import_typescript8.default.isArrayLiteralExpression(args[0])) {
839
1083
  frags.push({ examples: args[0].elements.map((e) => literalToJson(e)) });
840
1084
  } else if (name === "Description" && isStringLiteral(args[0])) {
841
1085
  frags.push({ description: args[0].text });
842
- } else if (name === "Enum" && import_typescript4.default.isArrayLiteralExpression(args[0])) {
1086
+ } else if (name === "Enum" && import_typescript8.default.isArrayLiteralExpression(args[0])) {
843
1087
  frags.push({ enum: args[0].elements.map((e) => literalToJson(e)) });
844
1088
  } else if (name === "Const") {
845
1089
  frags.push({ const: literalToJson(args[0]) });
@@ -847,9 +1091,9 @@ function extractPropertySchemaFragments(checker, prop) {
847
1091
  frags.push({ default: literalToJson(args[0]) });
848
1092
  } else if (name === "AdditionalProperties") {
849
1093
  const arg = args[0];
850
- if (arg && (arg.kind === import_typescript4.default.SyntaxKind.FalseKeyword || arg.kind === import_typescript4.default.SyntaxKind.TrueKeyword)) {
851
- frags.push({ additionalProperties: arg.kind === import_typescript4.default.SyntaxKind.TrueKeyword });
852
- } else if (arg && import_typescript4.default.isObjectLiteralExpression(arg)) {
1094
+ if (arg && (arg.kind === import_typescript8.default.SyntaxKind.FalseKeyword || arg.kind === import_typescript8.default.SyntaxKind.TrueKeyword)) {
1095
+ frags.push({ additionalProperties: arg.kind === import_typescript8.default.SyntaxKind.TrueKeyword });
1096
+ } else if (arg && import_typescript8.default.isObjectLiteralExpression(arg)) {
853
1097
  const obj = objectLiteralToJson(arg);
854
1098
  if (obj) frags.push({ additionalProperties: obj });
855
1099
  }
@@ -862,7 +1106,7 @@ function extractPropertySchemaFragments(checker, prop) {
862
1106
  return frags;
863
1107
  }
864
1108
  function resolveImportedDecorator(checker, sym) {
865
- const target = sym.flags & import_typescript4.default.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
1109
+ const target = sym.flags & import_typescript8.default.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
866
1110
  const name = target.getName();
867
1111
  const decl = target.declarations?.[0];
868
1112
  if (!decl) return null;
@@ -873,10 +1117,10 @@ function resolveImportedDecorator(checker, sym) {
873
1117
  return null;
874
1118
  }
875
1119
  function isNumberLiteral(node) {
876
- return !!node && import_typescript4.default.isNumericLiteral(node);
1120
+ return !!node && import_typescript8.default.isNumericLiteral(node);
877
1121
  }
878
1122
  function isStringLiteral(node) {
879
- return !!node && import_typescript4.default.isStringLiteral(node);
1123
+ return !!node && import_typescript8.default.isStringLiteral(node);
880
1124
  }
881
1125
  function extractRegexPattern(text) {
882
1126
  const match = text.match(/^\/(.+)\/[gimsuy]*$/);
@@ -885,12 +1129,12 @@ function extractRegexPattern(text) {
885
1129
  function objectLiteralToJson(obj) {
886
1130
  const out = {};
887
1131
  for (const prop of obj.properties) {
888
- if (!import_typescript4.default.isPropertyAssignment(prop)) continue;
1132
+ if (!import_typescript8.default.isPropertyAssignment(prop)) continue;
889
1133
  const name = prop.name;
890
1134
  let key;
891
- if (import_typescript4.default.isIdentifier(name)) {
1135
+ if (import_typescript8.default.isIdentifier(name)) {
892
1136
  key = name.text;
893
- } else if (import_typescript4.default.isStringLiteral(name)) {
1137
+ } else if (import_typescript8.default.isStringLiteral(name)) {
894
1138
  key = name.text;
895
1139
  } else {
896
1140
  continue;
@@ -900,13 +1144,13 @@ function objectLiteralToJson(obj) {
900
1144
  return out;
901
1145
  }
902
1146
  function literalToJson(node) {
903
- if (import_typescript4.default.isStringLiteral(node)) return node.text;
904
- if (import_typescript4.default.isNumericLiteral(node)) return Number(node.text);
905
- if (node.kind === import_typescript4.default.SyntaxKind.TrueKeyword) return true;
906
- if (node.kind === import_typescript4.default.SyntaxKind.FalseKeyword) return false;
907
- if (node.kind === import_typescript4.default.SyntaxKind.NullKeyword) return null;
908
- if (import_typescript4.default.isObjectLiteralExpression(node)) return objectLiteralToJson(node);
909
- if (import_typescript4.default.isArrayLiteralExpression(node)) return node.elements.map((e) => literalToJson(e));
1147
+ if (import_typescript8.default.isStringLiteral(node)) return node.text;
1148
+ if (import_typescript8.default.isNumericLiteral(node)) return Number(node.text);
1149
+ if (node.kind === import_typescript8.default.SyntaxKind.TrueKeyword) return true;
1150
+ if (node.kind === import_typescript8.default.SyntaxKind.FalseKeyword) return false;
1151
+ if (node.kind === import_typescript8.default.SyntaxKind.NullKeyword) return null;
1152
+ if (import_typescript8.default.isObjectLiteralExpression(node)) return objectLiteralToJson(node);
1153
+ if (import_typescript8.default.isArrayLiteralExpression(node)) return node.elements.map((e) => literalToJson(e));
910
1154
  return void 0;
911
1155
  }
912
1156
  function mergeFragments(base, ...frags) {
@@ -917,120 +1161,7 @@ function mergeFragments(base, ...frags) {
917
1161
  return result;
918
1162
  }
919
1163
 
920
- // src/compiler/schema/openapi.ts
921
- function generateOpenAPI(controllers, checker, options = {}) {
922
- const components = /* @__PURE__ */ new Map();
923
- const ctx = {
924
- checker,
925
- components,
926
- typeStack: /* @__PURE__ */ new Set(),
927
- typeNameStack: [],
928
- mode: "response"
929
- };
930
- const paths = {};
931
- for (const controller of controllers) {
932
- for (const operation of controller.operations) {
933
- const fullPath = convertToOpenApiPath(controller.basePath, operation.path);
934
- if (!paths[fullPath]) {
935
- paths[fullPath] = {};
936
- }
937
- const method = operation.httpMethod.toLowerCase();
938
- paths[fullPath][method] = buildOperation(operation, ctx, controller.consumes);
939
- }
940
- }
941
- return {
942
- openapi: "3.1.0",
943
- info: {
944
- title: options.title ?? "API",
945
- version: options.version ?? "1.0.0"
946
- },
947
- components: {
948
- schemas: Object.fromEntries(components)
949
- },
950
- paths
951
- };
952
- }
953
- function convertToOpenApiPath(basePath, path4) {
954
- const base = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
955
- const converted = path4.replace(/:([^/]+)/g, "{$1}");
956
- let fullPath = base + converted || "/";
957
- if (fullPath.endsWith("/") && fullPath !== "/") {
958
- fullPath = fullPath.slice(0, -1);
959
- }
960
- return fullPath;
961
- }
962
- function buildOperation(operation, ctx, controllerConsumes) {
963
- const op = {
964
- operationId: operation.operationId,
965
- responses: {}
966
- };
967
- const parameters = [];
968
- buildPathParameters(operation, ctx, parameters);
969
- buildQueryParameters(operation, ctx, parameters);
970
- buildHeaderParameters(operation, ctx, parameters);
971
- buildCookieParameters(operation, ctx, parameters);
972
- if (parameters.length > 0) {
973
- op.parameters = parameters;
974
- }
975
- const responseCtx = { ...ctx, mode: "response" };
976
- const responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
977
- const status = operation.httpMethod === "POST" ? 201 : 200;
978
- op.responses[status] = {
979
- description: status === 201 ? "Created" : "OK",
980
- content: {
981
- "application/json": {
982
- schema: responseSchema
983
- }
984
- }
985
- };
986
- if (["POST", "PUT", "PATCH"].includes(operation.httpMethod) && operation.bodyParamIndex !== null) {
987
- const bodyParam = operation.parameters[operation.bodyParamIndex];
988
- if (bodyParam) {
989
- const requestCtx = { ...ctx, mode: "request" };
990
- let bodySchema = typeToJsonSchema(bodyParam.type, requestCtx);
991
- bodySchema = mergeBodySchemaAnnotations(bodyParam, requestCtx, bodySchema);
992
- const contentType = operation.bodyContentType ?? controllerConsumes?.[0] ?? "application/json";
993
- const requestBody = {
994
- required: !bodyParam.isOptional,
995
- content: {}
996
- };
997
- if (contentType === "multipart/form-data") {
998
- requestBody.content["multipart/form-data"] = {
999
- schema: bodySchema
1000
- };
1001
- } else {
1002
- requestBody.content[contentType] = {
1003
- schema: bodySchema
1004
- };
1005
- }
1006
- op.requestBody = requestBody;
1007
- }
1008
- }
1009
- return op;
1010
- }
1011
- function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
1012
- if (!schema.properties) return schema;
1013
- const typeSymbol = bodyParam.type.getSymbol();
1014
- if (!typeSymbol) return schema;
1015
- const declarations = typeSymbol.getDeclarations();
1016
- if (!declarations || declarations.length === 0) return schema;
1017
- const classDecl = declarations[0];
1018
- if (!import_typescript5.default.isClassDeclaration(classDecl)) return schema;
1019
- const result = { ...schema };
1020
- const props = { ...result.properties };
1021
- for (const member of classDecl.members) {
1022
- if (!import_typescript5.default.isPropertyDeclaration(member) || !member.name) continue;
1023
- const propName = import_typescript5.default.isIdentifier(member.name) ? member.name.text : null;
1024
- if (!propName) continue;
1025
- if (!props[propName]) continue;
1026
- const frags = extractPropertySchemaFragments(ctx.checker, member);
1027
- if (frags.length > 0) {
1028
- props[propName] = mergeFragments(props[propName], ...frags);
1029
- }
1030
- }
1031
- result.properties = props;
1032
- return result;
1033
- }
1164
+ // src/compiler/schema/parameters.ts
1034
1165
  function buildPathParameters(operation, ctx, parameters) {
1035
1166
  for (const paramIndex of operation.pathParamIndices) {
1036
1167
  const param = operation.parameters[paramIndex];
@@ -1043,71 +1174,22 @@ function buildPathParameters(operation, ctx, parameters) {
1043
1174
  }
1044
1175
  }
1045
1176
  const schema = paramSchema.$ref ? { $ref: paramSchema.$ref } : paramSchema;
1046
- parameters.push({
1047
- name: param.name,
1048
- in: "path",
1049
- required: !param.isOptional,
1050
- schema
1051
- });
1052
- }
1053
- }
1054
- }
1055
- function isObjectLikeSchema(schema, ctx) {
1056
- const resolved = resolveSchemaRef(schema, ctx.components);
1057
- if (resolved.type === "object" || resolved.properties || resolved.additionalProperties) {
1058
- return true;
1059
- }
1060
- if (resolved.allOf) {
1061
- for (const branch of resolved.allOf) {
1062
- if (isObjectLikeSchema(branch, ctx)) {
1063
- return true;
1064
- }
1065
- }
1066
- }
1067
- if (resolved.type === "array" && resolved.items) {
1068
- const itemsSchema = resolveSchemaRef(resolved.items, ctx.components);
1069
- return isObjectLikeSchema(itemsSchema, ctx);
1070
- }
1071
- return false;
1072
- }
1073
- function resolveSchemaRef(schema, components) {
1074
- const ref = schema.$ref;
1075
- if (typeof ref !== "string" || !ref.startsWith("#/components/schemas/")) {
1076
- return schema;
1077
- }
1078
- const name = ref.replace("#/components/schemas/", "");
1079
- const next = components.get(name);
1080
- if (!next) return schema;
1081
- return resolveSchemaRef(next, components);
1082
- }
1083
- function resolveAndCollectObjectProps(schema, components) {
1084
- const resolved = resolveSchemaRef(schema, components);
1085
- const properties = {};
1086
- const required = [];
1087
- const processSchema = (s) => {
1088
- const current = resolveSchemaRef(s, components);
1089
- if (current.properties) {
1090
- for (const [key, val] of Object.entries(current.properties)) {
1091
- if (!properties[key]) {
1092
- properties[key] = val;
1093
- }
1094
- }
1095
- }
1096
- if (current.required) {
1097
- for (const req of current.required) {
1098
- if (!required.includes(req)) {
1099
- required.push(req);
1177
+ const paramName = param.name.toLowerCase();
1178
+ const isIdParam = paramName === "id" || paramName.endsWith("id");
1179
+ if (!schema.$ref && schema.type === "number" && isIdParam) {
1180
+ schema.type = "integer";
1181
+ if (!schema.minimum) {
1182
+ schema.minimum = 1;
1100
1183
  }
1101
1184
  }
1185
+ parameters.push({
1186
+ name: param.name,
1187
+ in: "path",
1188
+ required: !param.isOptional,
1189
+ schema
1190
+ });
1102
1191
  }
1103
- if (current.allOf) {
1104
- for (const branch of current.allOf) {
1105
- processSchema(branch);
1106
- }
1107
- }
1108
- };
1109
- processSchema(resolved);
1110
- return { properties, required };
1192
+ }
1111
1193
  }
1112
1194
  function buildQueryParameters(operation, ctx, parameters) {
1113
1195
  if (operation.queryObjectParamIndex !== null) {
@@ -1116,20 +1198,22 @@ function buildQueryParameters(operation, ctx, parameters) {
1116
1198
  const querySchema = typeToJsonSchema(queryParam.type, ctx);
1117
1199
  const { properties: queryObjProps, required: queryRequired } = resolveAndCollectObjectProps(querySchema, ctx.components);
1118
1200
  for (const [propName, propSchema] of Object.entries(queryObjProps)) {
1119
- const isRequired = queryRequired.includes(propName) ?? false;
1201
+ const isRequired = queryRequired.includes(propName);
1120
1202
  const isObjectLike = isObjectLikeSchema(propSchema, ctx);
1121
1203
  const serialization = determineQuerySerialization(propSchema.type);
1204
+ const exampleValue = generateExampleValue(propSchema, propName);
1122
1205
  if (isObjectLike) {
1206
+ const schemaRef = propSchema.$ref || "#/components/schemas/InlineQueryParam";
1123
1207
  parameters.push({
1124
1208
  name: propName,
1125
1209
  in: "query",
1126
1210
  required: isRequired,
1127
- content: {
1128
- "application/json": {
1129
- schema: propSchema.$ref ? { $ref: propSchema.$ref } : propSchema
1130
- }
1211
+ schema: { type: "string" },
1212
+ description: `JSON-encoded object. ${exampleValue}`,
1213
+ examples: {
1214
+ default: { value: parseExampleValue(exampleValue) }
1131
1215
  },
1132
- description: `URL-encoded JSON. Example: ${propName}=${encodeURIComponent(JSON.stringify({ example: "value" }))}`
1216
+ "x-adorn-jsonSchemaRef": schemaRef
1133
1217
  });
1134
1218
  } else {
1135
1219
  const paramDef = {
@@ -1175,15 +1259,18 @@ function buildQueryParameters(operation, ctx, parameters) {
1175
1259
  }
1176
1260
  const isObjectLike = isObjectLikeSchema(paramSchema, ctx);
1177
1261
  if (isObjectLike) {
1262
+ const schemaRef = paramSchema.$ref || "#/components/schemas/InlineQueryParam";
1263
+ const exampleValue = generateExampleValue(paramSchema, param.name);
1178
1264
  parameters.push({
1179
1265
  name: param.name,
1180
1266
  in: "query",
1181
1267
  required: !param.isOptional,
1182
- content: {
1183
- "application/json": {
1184
- schema: paramSchema.$ref ? { $ref: paramSchema.$ref } : paramSchema
1185
- }
1186
- }
1268
+ schema: { type: "string" },
1269
+ description: `JSON-encoded object. ${exampleValue}`,
1270
+ examples: {
1271
+ default: { value: parseExampleValue(exampleValue) }
1272
+ },
1273
+ "x-adorn-jsonSchemaRef": schemaRef
1187
1274
  });
1188
1275
  } else {
1189
1276
  const serialization = determineQuerySerialization(paramSchema.type);
@@ -1198,14 +1285,6 @@ function buildQueryParameters(operation, ctx, parameters) {
1198
1285
  }
1199
1286
  }
1200
1287
  }
1201
- function determineQuerySerialization(schemaType) {
1202
- const typeArray = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
1203
- const isArray = typeArray.includes("array");
1204
- if (isArray) {
1205
- return { style: "form", explode: true };
1206
- }
1207
- return {};
1208
- }
1209
1288
  function buildHeaderParameters(operation, ctx, parameters) {
1210
1289
  if (operation.headerObjectParamIndex === null) return;
1211
1290
  const headerParam = operation.parameters[operation.headerObjectParamIndex];
@@ -1242,9 +1321,324 @@ function buildCookieParameters(operation, ctx, parameters) {
1242
1321
  });
1243
1322
  }
1244
1323
  }
1324
+ function determineQuerySerialization(schemaType) {
1325
+ const typeArray = Array.isArray(schemaType) ? schemaType : schemaType ? [schemaType] : [];
1326
+ const isArray = typeArray.includes("array");
1327
+ if (isArray) {
1328
+ return { style: "form", explode: true };
1329
+ }
1330
+ return {};
1331
+ }
1332
+ function generateExampleValue(schema, propName) {
1333
+ const resolved = resolveSchemaRef(schema, /* @__PURE__ */ new Map());
1334
+ if (resolved.type === "object" && resolved.properties) {
1335
+ const example = {};
1336
+ for (const [key, prop] of Object.entries(resolved.properties)) {
1337
+ const propResolved = resolveSchemaRef(prop, /* @__PURE__ */ new Map());
1338
+ if (propResolved.type === "string") {
1339
+ example[key] = "value";
1340
+ } else if (propResolved.type === "number" || propResolved.type === "integer") {
1341
+ example[key] = 1;
1342
+ } else if (propResolved.type === "boolean") {
1343
+ example[key] = true;
1344
+ } else if (Array.isArray(propResolved.type) && propResolved.type.includes("null")) {
1345
+ example[key] = null;
1346
+ } else if (propResolved.enum) {
1347
+ example[key] = propResolved.enum[0];
1348
+ } else {
1349
+ example[key] = "value";
1350
+ }
1351
+ }
1352
+ return `Example: ${propName}=${JSON.stringify(example)}`;
1353
+ }
1354
+ return `Example: ${propName}=${JSON.stringify({ key: "value" })}`;
1355
+ }
1356
+ function parseExampleValue(description) {
1357
+ const match = description.match(/Example:\s*\w+=(\{[^}]+\})/);
1358
+ if (match) {
1359
+ return match[1];
1360
+ }
1361
+ return JSON.stringify({ key: "value" });
1362
+ }
1363
+ function isObjectLikeSchema(schema, ctx) {
1364
+ const resolved = resolveSchemaRef(schema, ctx.components);
1365
+ if (resolved.type === "object" || resolved.properties || resolved.additionalProperties) {
1366
+ return true;
1367
+ }
1368
+ if (resolved.allOf) {
1369
+ for (const branch of resolved.allOf) {
1370
+ if (isObjectLikeSchema(branch, ctx)) {
1371
+ return true;
1372
+ }
1373
+ }
1374
+ }
1375
+ if (resolved.type === "array" && resolved.items) {
1376
+ const itemsSchema = resolveSchemaRef(resolved.items, ctx.components);
1377
+ return isObjectLikeSchema(itemsSchema, ctx);
1378
+ }
1379
+ return false;
1380
+ }
1381
+ function resolveSchemaRef(schema, components) {
1382
+ const ref = schema.$ref;
1383
+ if (typeof ref !== "string" || !ref.startsWith("#/components/schemas/")) {
1384
+ return schema;
1385
+ }
1386
+ const name = ref.replace("#/components/schemas/", "");
1387
+ const next = components.get(name);
1388
+ if (!next) return schema;
1389
+ return resolveSchemaRef(next, components);
1390
+ }
1391
+ function resolveAndCollectObjectProps(schema, components) {
1392
+ const resolved = resolveSchemaRef(schema, components);
1393
+ const properties = {};
1394
+ const required = [];
1395
+ const processSchema = (s) => {
1396
+ const current = resolveSchemaRef(s, components);
1397
+ if (current.properties) {
1398
+ for (const [key, val] of Object.entries(current.properties)) {
1399
+ if (!properties[key]) {
1400
+ properties[key] = val;
1401
+ }
1402
+ }
1403
+ }
1404
+ if (current.required) {
1405
+ for (const req of current.required) {
1406
+ if (!required.includes(req)) {
1407
+ required.push(req);
1408
+ }
1409
+ }
1410
+ }
1411
+ if (current.allOf) {
1412
+ for (const branch of current.allOf) {
1413
+ processSchema(branch);
1414
+ }
1415
+ }
1416
+ };
1417
+ processSchema(resolved);
1418
+ return { properties, required };
1419
+ }
1420
+
1421
+ // src/compiler/schema/openapi.ts
1422
+ var METAL_ORM_WRAPPER_NAMES2 = ["BelongsToReference", "HasOneReference", "HasManyCollection", "ManyToManyCollection"];
1423
+ function generateOpenAPI(controllers, checker, options = {}) {
1424
+ const components = /* @__PURE__ */ new Map();
1425
+ const ctx = {
1426
+ checker,
1427
+ components,
1428
+ typeStack: /* @__PURE__ */ new Set(),
1429
+ typeNameStack: [],
1430
+ mode: "response"
1431
+ };
1432
+ const paths = {};
1433
+ for (const controller of controllers) {
1434
+ for (const operation of controller.operations) {
1435
+ const fullPath = convertToOpenApiPath(controller.basePath, operation.path);
1436
+ if (!paths[fullPath]) {
1437
+ paths[fullPath] = {};
1438
+ }
1439
+ const method = operation.httpMethod.toLowerCase();
1440
+ paths[fullPath][method] = buildOperation(operation, ctx, controller.consumes);
1441
+ }
1442
+ }
1443
+ const schemas = Object.fromEntries(components);
1444
+ cleanupMetalOrmWrappers(schemas, paths);
1445
+ return {
1446
+ openapi: "3.1.0",
1447
+ info: {
1448
+ title: options.title ?? "API",
1449
+ version: options.version ?? "1.0.0"
1450
+ },
1451
+ components: {
1452
+ schemas
1453
+ },
1454
+ paths
1455
+ };
1456
+ }
1457
+ function cleanupMetalOrmWrappers(schemas, paths) {
1458
+ const schemasToDelete = /* @__PURE__ */ new Set();
1459
+ for (const wrapperName of METAL_ORM_WRAPPER_NAMES2) {
1460
+ if (schemas[wrapperName]) {
1461
+ schemasToDelete.add(wrapperName);
1462
+ }
1463
+ if (schemas[`${wrapperName}Api`]) {
1464
+ schemasToDelete.add(`${wrapperName}Api`);
1465
+ }
1466
+ }
1467
+ for (const schema of Object.values(schemas)) {
1468
+ cleanupSchemaRefs(schema, schemasToDelete);
1469
+ }
1470
+ for (const pathItem of Object.values(paths)) {
1471
+ cleanupPathItemRefs(pathItem, schemasToDelete);
1472
+ }
1473
+ for (const schemaName of schemasToDelete) {
1474
+ delete schemas[schemaName];
1475
+ }
1476
+ }
1477
+ function cleanupSchemaRefs(schema, schemasToDelete) {
1478
+ if (typeof schema !== "object" || schema === null) {
1479
+ return;
1480
+ }
1481
+ if (schema.properties) {
1482
+ for (const propName of Object.keys(schema.properties)) {
1483
+ const propSchema = schema.properties[propName];
1484
+ if (propSchema.$ref && typeof propSchema.$ref === "string") {
1485
+ const refName = propSchema.$ref.replace("#/components/schemas/", "");
1486
+ if (schemasToDelete.has(refName)) {
1487
+ delete schema.properties[propName];
1488
+ if (schema.required && Array.isArray(schema.required)) {
1489
+ schema.required = schema.required.filter((r) => r !== propName);
1490
+ }
1491
+ }
1492
+ } else {
1493
+ cleanupSchemaRefs(propSchema, schemasToDelete);
1494
+ }
1495
+ }
1496
+ }
1497
+ if (schema.items) {
1498
+ cleanupSchemaRefs(schema.items, schemasToDelete);
1499
+ }
1500
+ if (schema.allOf) {
1501
+ for (const item of schema.allOf) {
1502
+ cleanupSchemaRefs(item, schemasToDelete);
1503
+ }
1504
+ }
1505
+ }
1506
+ function cleanupPathItemRefs(pathItem, schemasToDelete) {
1507
+ if (typeof pathItem !== "object" || pathItem === null) {
1508
+ return;
1509
+ }
1510
+ for (const method of Object.keys(pathItem)) {
1511
+ const operation = pathItem[method];
1512
+ if (typeof operation !== "object" || operation === null) continue;
1513
+ if (operation.requestBody) {
1514
+ cleanupRequestBodyRefs(operation.requestBody, schemasToDelete);
1515
+ }
1516
+ if (operation.responses) {
1517
+ const responses = Object.values(operation.responses);
1518
+ for (const response of responses) {
1519
+ if (response.content) {
1520
+ const contentTypes = Object.values(response.content);
1521
+ for (const contentType of contentTypes) {
1522
+ if (contentType.schema) {
1523
+ cleanupSchemaRefs(contentType.schema, schemasToDelete);
1524
+ }
1525
+ }
1526
+ }
1527
+ }
1528
+ }
1529
+ }
1530
+ }
1531
+ function cleanupRequestBodyRefs(requestBody, schemasToDelete) {
1532
+ if (typeof requestBody !== "object" || requestBody === null) return;
1533
+ if (requestBody.content) {
1534
+ const contentTypes = Object.values(requestBody.content);
1535
+ for (const contentType of contentTypes) {
1536
+ if (contentType.schema) {
1537
+ cleanupSchemaRefs(contentType.schema, schemasToDelete);
1538
+ }
1539
+ }
1540
+ }
1541
+ if (requestBody.properties) {
1542
+ for (const propName of Object.keys(requestBody.properties)) {
1543
+ const propSchema = requestBody.properties[propName];
1544
+ if (propSchema.$ref && typeof propSchema.$ref === "string") {
1545
+ const refName = propSchema.$ref.replace("#/components/schemas/", "");
1546
+ if (schemasToDelete.has(refName)) {
1547
+ delete requestBody.properties[propName];
1548
+ if (requestBody.required && Array.isArray(requestBody.required)) {
1549
+ requestBody.required = requestBody.required.filter((r) => r !== propName);
1550
+ }
1551
+ }
1552
+ } else {
1553
+ cleanupSchemaRefs(propSchema, schemasToDelete);
1554
+ }
1555
+ }
1556
+ }
1557
+ }
1558
+ function convertToOpenApiPath(basePath, path4) {
1559
+ const base = basePath.endsWith("/") ? basePath.slice(0, -1) : basePath;
1560
+ const converted = path4.replace(/:([^/]+)/g, "{$1}");
1561
+ let fullPath = base + converted || "/";
1562
+ if (fullPath.endsWith("/") && fullPath !== "/") {
1563
+ fullPath = fullPath.slice(0, -1);
1564
+ }
1565
+ return fullPath;
1566
+ }
1567
+ function buildOperation(operation, ctx, controllerConsumes) {
1568
+ const op = {
1569
+ operationId: operation.operationId,
1570
+ responses: {}
1571
+ };
1572
+ const parameters = [];
1573
+ buildPathParameters(operation, ctx, parameters);
1574
+ buildQueryParameters(operation, ctx, parameters);
1575
+ buildHeaderParameters(operation, ctx, parameters);
1576
+ buildCookieParameters(operation, ctx, parameters);
1577
+ if (parameters.length > 0) {
1578
+ op.parameters = parameters;
1579
+ }
1580
+ const responseCtx = { ...ctx, mode: "response" };
1581
+ const responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
1582
+ const status = operation.httpMethod === "POST" ? 201 : 200;
1583
+ op.responses[status] = {
1584
+ description: status === 201 ? "Created" : "OK",
1585
+ content: {
1586
+ "application/json": {
1587
+ schema: responseSchema
1588
+ }
1589
+ }
1590
+ };
1591
+ if (["POST", "PUT", "PATCH"].includes(operation.httpMethod) && operation.bodyParamIndex !== null) {
1592
+ const bodyParam = operation.parameters[operation.bodyParamIndex];
1593
+ if (bodyParam) {
1594
+ const requestCtx = { ...ctx, mode: "request" };
1595
+ let bodySchema = typeToJsonSchema(bodyParam.type, requestCtx);
1596
+ bodySchema = mergeBodySchemaAnnotations(bodyParam, requestCtx, bodySchema);
1597
+ const contentType = operation.bodyContentType ?? controllerConsumes?.[0] ?? "application/json";
1598
+ const requestBody = {
1599
+ required: !bodyParam.isOptional,
1600
+ content: {}
1601
+ };
1602
+ if (contentType === "multipart/form-data") {
1603
+ requestBody.content["multipart/form-data"] = {
1604
+ schema: bodySchema
1605
+ };
1606
+ } else {
1607
+ requestBody.content[contentType] = {
1608
+ schema: bodySchema
1609
+ };
1610
+ }
1611
+ op.requestBody = requestBody;
1612
+ }
1613
+ }
1614
+ return op;
1615
+ }
1616
+ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
1617
+ if (!schema.properties) return schema;
1618
+ const typeSymbol = bodyParam.type.getSymbol();
1619
+ if (!typeSymbol) return schema;
1620
+ const declarations = typeSymbol.getDeclarations();
1621
+ if (!declarations || declarations.length === 0) return schema;
1622
+ const classDecl = declarations[0];
1623
+ if (!import_typescript9.default.isClassDeclaration(classDecl)) return schema;
1624
+ const result = { ...schema };
1625
+ const props = { ...result.properties };
1626
+ for (const member of classDecl.members) {
1627
+ if (!import_typescript9.default.isPropertyDeclaration(member) || !member.name) continue;
1628
+ const propName = import_typescript9.default.isIdentifier(member.name) ? member.name.text : null;
1629
+ if (!propName) continue;
1630
+ if (!props[propName]) continue;
1631
+ const frags = extractPropertySchemaFragments(ctx.checker, member);
1632
+ if (frags.length > 0) {
1633
+ props[propName] = mergeFragments(props[propName], ...frags);
1634
+ }
1635
+ }
1636
+ result.properties = props;
1637
+ return result;
1638
+ }
1245
1639
 
1246
1640
  // src/compiler/manifest/emit.ts
1247
- var import_typescript6 = __toESM(require("typescript"), 1);
1641
+ var import_typescript10 = __toESM(require("typescript"), 1);
1248
1642
  function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
1249
1643
  const components = /* @__PURE__ */ new Map();
1250
1644
  const ctx = {
@@ -1266,7 +1660,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
1266
1660
  generator: {
1267
1661
  name: "adorn-api",
1268
1662
  version,
1269
- typescript: import_typescript6.default.version
1663
+ typescript: import_typescript10.default.version
1270
1664
  },
1271
1665
  schemas: {
1272
1666
  kind: "openapi-3.1",
@@ -1420,7 +1814,7 @@ function buildQueryArgs(op, ctx, args) {
1420
1814
  args.query.push({
1421
1815
  name: propName,
1422
1816
  index: queryParam.index,
1423
- required: !isRequired,
1817
+ required: isRequired,
1424
1818
  schemaRef,
1425
1819
  schemaType: propSchema.type,
1426
1820
  content: isObjectLike ? "application/json" : void 0
@@ -1459,7 +1853,7 @@ function buildHeaderArgs(op, ctx, args) {
1459
1853
  args.headers.push({
1460
1854
  name: propName,
1461
1855
  index: headerParam.index,
1462
- required: !isRequired,
1856
+ required: isRequired,
1463
1857
  schemaRef,
1464
1858
  schemaType: propSchema.type
1465
1859
  });
@@ -1480,7 +1874,7 @@ function buildCookieArgs(op, ctx, args) {
1480
1874
  args.cookies.push({
1481
1875
  name: propName,
1482
1876
  index: cookieParam.index,
1483
- required: !isRequired,
1877
+ required: isRequired,
1484
1878
  schemaRef,
1485
1879
  schemaType: propSchema.type,
1486
1880
  serialization: { style: "form", explode: true }
@@ -1496,7 +1890,7 @@ var import_ajv = __toESM(require("ajv"), 1);
1496
1890
  var import_ajv_formats = __toESM(require("ajv-formats"), 1);
1497
1891
  var OAS_SCHEMA_ONLY = /* @__PURE__ */ new Set(["discriminator", "xml", "externalDocs", "example"]);
1498
1892
  function sanitizeSchemaForAjv(schema) {
1499
- if (schema == null || typeof schema !== "object") return schema;
1893
+ if (schema === null || typeof schema !== "object") return schema;
1500
1894
  if (Array.isArray(schema)) return schema.map(sanitizeSchemaForAjv);
1501
1895
  const out = {};
1502
1896
  for (const [k, v] of Object.entries(schema)) {
@@ -1507,7 +1901,7 @@ function sanitizeSchemaForAjv(schema) {
1507
1901
  return out;
1508
1902
  }
1509
1903
  function rewriteComponentRefs(schema) {
1510
- if (schema == null || typeof schema !== "object") return schema;
1904
+ if (schema === null || typeof schema !== "object") return schema;
1511
1905
  if (Array.isArray(schema)) return schema.map(rewriteComponentRefs);
1512
1906
  if (typeof schema.$ref === "string") {
1513
1907
  const ref = schema.$ref;
@@ -1584,16 +1978,13 @@ async function emitPrecompiledValidators(opts) {
1584
1978
  `;
1585
1979
  cjs += ` body: ${v.body ? `exports[${JSON.stringify(v.body)}]` : "undefined"},
1586
1980
  `;
1587
- cjs += ` response: {
1588
- `;
1981
+ cjs += " response: {\n";
1589
1982
  for (const [key, id] of Object.entries(v.response)) {
1590
1983
  cjs += ` ${JSON.stringify(key)}: exports[${JSON.stringify(id)}],
1591
1984
  `;
1592
1985
  }
1593
- cjs += ` }
1594
- `;
1595
- cjs += ` },
1596
- `;
1986
+ cjs += " }\n";
1987
+ cjs += " },\n";
1597
1988
  }
1598
1989
  cjs += "};\n";
1599
1990
  import_node_fs2.default.writeFileSync(cjsPath, cjs, "utf8");
@@ -1628,7 +2019,6 @@ export function validateResponse(operationId, status, contentType, data) {
1628
2019
  // src/compiler/cache/isStale.ts
1629
2020
  var import_node_fs3 = __toESM(require("fs"), 1);
1630
2021
  var import_node_path3 = __toESM(require("path"), 1);
1631
- var import_typescript7 = require("typescript");
1632
2022
  var import_meta = {};
1633
2023
  function readJson(p) {
1634
2024
  try {
@@ -1686,7 +2076,7 @@ function findLockfile(startDir) {
1686
2076
  for (const n of names) {
1687
2077
  const p = import_node_path3.default.join(dir, n);
1688
2078
  const mt = statMtimeMs(p);
1689
- if (mt != null) return { path: p, mtimeMs: mt };
2079
+ if (mt !== null) return { path: p, mtimeMs: mt };
1690
2080
  }
1691
2081
  const parent = import_node_path3.default.dirname(dir);
1692
2082
  if (parent === dir) break;
@@ -1711,22 +2101,22 @@ async function isStale(params) {
1711
2101
  const chain = collectTsconfigChain(tsconfigAbs);
1712
2102
  for (const cfg of chain) {
1713
2103
  const mt = statMtimeMs(cfg);
1714
- if (mt == null) return { stale: true, reason: "config-missing", detail: cfg };
2104
+ if (mt === null) return { stale: true, reason: "config-missing", detail: cfg };
1715
2105
  const cachedMt = cache.project.configFiles[cfg];
1716
- if (cachedMt == null || Math.abs(cachedMt - mt) > 1e-4) {
2106
+ if (cachedMt === null || Math.abs(cachedMt - mt) > 1e-4) {
1717
2107
  return { stale: true, reason: "config-updated", detail: cfg };
1718
2108
  }
1719
2109
  }
1720
2110
  if (cache.project.lockfile?.path) {
1721
2111
  const mt = statMtimeMs(cache.project.lockfile.path);
1722
- if (mt == null) return { stale: true, reason: "lockfile-missing", detail: cache.project.lockfile.path };
2112
+ if (mt === null) return { stale: true, reason: "lockfile-missing", detail: cache.project.lockfile.path };
1723
2113
  if (Math.abs(cache.project.lockfile.mtimeMs - mt) > 1e-4) {
1724
2114
  return { stale: true, reason: "lockfile-updated", detail: cache.project.lockfile.path };
1725
2115
  }
1726
2116
  }
1727
2117
  for (const [file, cachedMt] of Object.entries(cache.inputs)) {
1728
2118
  const mt = statMtimeMs(file);
1729
- if (mt == null) return { stale: true, reason: "input-missing", detail: file };
2119
+ if (mt === null) return { stale: true, reason: "input-missing", detail: file };
1730
2120
  if (Math.abs(cachedMt - mt) > 1e-4) return { stale: true, reason: "input-updated", detail: file };
1731
2121
  }
1732
2122
  return { stale: false, reason: "up-to-date" };
@@ -1735,7 +2125,7 @@ async function isStale(params) {
1735
2125
  // src/compiler/cache/writeCache.ts
1736
2126
  var import_node_fs4 = __toESM(require("fs"), 1);
1737
2127
  var import_node_path4 = __toESM(require("path"), 1);
1738
- var import_typescript8 = __toESM(require("typescript"), 1);
2128
+ var import_typescript11 = __toESM(require("typescript"), 1);
1739
2129
  function statMtimeMs2(p) {
1740
2130
  return import_node_fs4.default.statSync(p).mtimeMs;
1741
2131
  }
@@ -1768,7 +2158,7 @@ function writeCache(params) {
1768
2158
  generator: {
1769
2159
  name: "adorn-api",
1770
2160
  version: params.adornVersion,
1771
- typescript: import_typescript8.default.version
2161
+ typescript: import_typescript11.default.version
1772
2162
  },
1773
2163
  project: {
1774
2164
  tsconfigPath: params.tsconfigAbs,
@@ -1781,7 +2171,7 @@ function writeCache(params) {
1781
2171
  }
1782
2172
 
1783
2173
  // src/cli.ts
1784
- var import_typescript9 = __toESM(require("typescript"), 1);
2174
+ var import_typescript12 = __toESM(require("typescript"), 1);
1785
2175
  var import_node_process = __toESM(require("process"), 1);
1786
2176
  var ADORN_VERSION = "0.1.0";
1787
2177
  function log(msg) {
@@ -1829,7 +2219,7 @@ async function buildCommand(args) {
1829
2219
  outDir: outputDir,
1830
2220
  project: projectPath,
1831
2221
  adornVersion: ADORN_VERSION,
1832
- typescriptVersion: import_typescript9.default.version
2222
+ typescriptVersion: import_typescript12.default.version
1833
2223
  });
1834
2224
  if (!stale.stale) {
1835
2225
  log("adorn-api: artifacts up-to-date");