adorn-api 1.0.19 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -306,7 +306,7 @@ function unwrapPromiseTypeNode(typeNode) {
306
306
  }
307
307
 
308
308
  // src/compiler/schema/openapi.ts
309
- import ts9 from "typescript";
309
+ import ts11 from "typescript";
310
310
 
311
311
  // src/compiler/schema/typeToJsonSchema.ts
312
312
  import ts7 from "typescript";
@@ -701,6 +701,48 @@ function getExplicitTypeNameFromNode3(typeNode) {
701
701
 
702
702
  // src/compiler/schema/objectHandler.ts
703
703
  import ts6 from "typescript";
704
+ function getTypeParameterName(type) {
705
+ if (type.flags & ts6.TypeFlags.TypeParameter) {
706
+ const typeParam = type;
707
+ return typeParam.symbol?.getName() ?? null;
708
+ }
709
+ return null;
710
+ }
711
+ function getTypeArguments(type) {
712
+ const typeRef = type;
713
+ const args = typeRef.typeArguments;
714
+ if (!args) return void 0;
715
+ return Array.from(args);
716
+ }
717
+ function createTypeParameterSubstitutions(type, typeNode, checker) {
718
+ const typeArgs = getTypeArguments(type);
719
+ if (!typeArgs || typeArgs.length === 0) {
720
+ return void 0;
721
+ }
722
+ if (!typeNode || !ts6.isTypeReferenceNode(typeNode)) {
723
+ return void 0;
724
+ }
725
+ const typeParams = typeNode.typeArguments;
726
+ if (!typeParams || typeParams.length !== typeArgs.length) {
727
+ return void 0;
728
+ }
729
+ const substitutions = /* @__PURE__ */ new Map();
730
+ for (let i = 0; i < typeParams.length; i++) {
731
+ const typeParamNode = typeParams[i];
732
+ const typeArg = typeArgs[i];
733
+ if (ts6.isIdentifier(typeParamNode)) {
734
+ substitutions.set(typeParamNode.text, typeArg);
735
+ }
736
+ }
737
+ return substitutions.size > 0 ? substitutions : void 0;
738
+ }
739
+ function resolveTypeParameter(type, substitutions, _checker) {
740
+ if (!substitutions) return null;
741
+ const paramName = getTypeParameterName(type);
742
+ if (!paramName) return null;
743
+ const resolved = substitutions.get(paramName);
744
+ return resolved ?? null;
745
+ }
704
746
  function handleObjectType(type, ctx, typeNode) {
705
747
  const { checker, components, typeStack } = ctx;
706
748
  const symbol = type.getSymbol();
@@ -720,7 +762,9 @@ function handleObjectType(type, ctx, typeNode) {
720
762
  }
721
763
  typeStack.add(type);
722
764
  }
723
- const schema = buildObjectSchema(type, ctx, typeNode);
765
+ const typeParamSubstitutions = createTypeParameterSubstitutions(type, typeNode, checker);
766
+ const buildCtx = typeParamSubstitutions ? { ...ctx, typeParameterSubstitutions: typeParamSubstitutions } : ctx;
767
+ const schema = buildObjectSchema(type, buildCtx, typeNode);
724
768
  if (typeName && typeName !== "__type") {
725
769
  typeStack.delete(type);
726
770
  const existing = components.get(typeName);
@@ -738,7 +782,7 @@ function handleObjectType(type, ctx, typeNode) {
738
782
  return schema;
739
783
  }
740
784
  function buildObjectSchema(type, ctx, _typeNode) {
741
- const { checker, mode } = ctx;
785
+ const { checker, mode, typeParameterSubstitutions } = ctx;
742
786
  const properties = {};
743
787
  const required = [];
744
788
  const props = checker.getPropertiesOfType(type);
@@ -747,10 +791,14 @@ function buildObjectSchema(type, ctx, _typeNode) {
747
791
  if (isIteratorOrSymbolProperty(propName)) {
748
792
  continue;
749
793
  }
750
- const propType = checker.getTypeOfSymbol(prop);
794
+ let propType = checker.getTypeOfSymbol(prop);
751
795
  if (isMethodLike(propType)) {
752
796
  continue;
753
797
  }
798
+ const resolvedType = resolveTypeParameter(propType, typeParameterSubstitutions, checker);
799
+ if (resolvedType) {
800
+ propType = resolvedType;
801
+ }
754
802
  const isOptional = !!(prop.flags & ts6.SymbolFlags.Optional);
755
803
  const isRelation = isMetalOrmWrapperType(propType, checker);
756
804
  const propCtx = { ...ctx, propertyName: propName };
@@ -770,7 +818,8 @@ function buildObjectSchema(type, ctx, _typeNode) {
770
818
  if (isRecordType(type, checker)) {
771
819
  const valueType = getRecordValueType(type, checker);
772
820
  if (valueType) {
773
- schema.additionalProperties = typeToJsonSchema(valueType, ctx);
821
+ const resolvedValueType = resolveTypeParameter(valueType, typeParameterSubstitutions, checker);
822
+ schema.additionalProperties = typeToJsonSchema(resolvedValueType ?? valueType, ctx);
774
823
  }
775
824
  }
776
825
  return schema;
@@ -1562,6 +1611,376 @@ function resolveAndCollectObjectProps(schema, components) {
1562
1611
  return { properties, required };
1563
1612
  }
1564
1613
 
1614
+ // src/compiler/schema/queryBuilderAnalyzer.ts
1615
+ import ts9 from "typescript";
1616
+ function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {}) {
1617
+ const body = methodDeclaration.body;
1618
+ if (!body) {
1619
+ return null;
1620
+ }
1621
+ const trackedSchema = analyzeWithVariableTracking(body, checker, options);
1622
+ if (trackedSchema) {
1623
+ return trackedSchema;
1624
+ }
1625
+ const returnStatement = findReturnStatement(body);
1626
+ if (!returnStatement) {
1627
+ return null;
1628
+ }
1629
+ const callChain = analyzeReturnExpression(returnStatement.expression);
1630
+ if (!callChain) {
1631
+ return null;
1632
+ }
1633
+ return parseQueryBuilderChain(callChain, checker, options);
1634
+ }
1635
+ function analyzeWithVariableTracking(body, checker, options) {
1636
+ let queryBuilderVar = null;
1637
+ let entityName = null;
1638
+ const selectedFields = /* @__PURE__ */ new Set();
1639
+ const includes = {};
1640
+ let isPaged = false;
1641
+ let hasReturn = false;
1642
+ for (const statement of body.statements) {
1643
+ if (ts9.isReturnStatement(statement)) {
1644
+ hasReturn = true;
1645
+ const returnExpr = statement.expression;
1646
+ if (returnExpr && ts9.isCallExpression(returnExpr)) {
1647
+ const callExpr = returnExpr;
1648
+ if (ts9.isIdentifier(callExpr.expression) && queryBuilderVar) {
1649
+ const varName = callExpr.expression.text;
1650
+ if (varName === queryBuilderVar) {
1651
+ const methodName = callExpr.expression.text;
1652
+ if (methodName === "executePaged") {
1653
+ isPaged = true;
1654
+ }
1655
+ }
1656
+ }
1657
+ if (ts9.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
1658
+ const propAccess = callExpr.expression;
1659
+ if (ts9.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
1660
+ const methodName = propAccess.name.text;
1661
+ if (methodName === "executePaged") {
1662
+ isPaged = true;
1663
+ }
1664
+ }
1665
+ }
1666
+ }
1667
+ continue;
1668
+ }
1669
+ if (!ts9.isExpressionStatement(statement)) {
1670
+ if (ts9.isVariableStatement(statement)) {
1671
+ for (const declaration of statement.declarationList.declarations) {
1672
+ if (!ts9.isIdentifier(declaration.name)) continue;
1673
+ const varName = declaration.name.text;
1674
+ const initializer = declaration.initializer;
1675
+ if (!initializer || !ts9.isCallExpression(initializer)) continue;
1676
+ const opInfo = extractChainedOperation(initializer);
1677
+ if (opInfo && (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom")) {
1678
+ queryBuilderVar = varName;
1679
+ if (opInfo.entityName) {
1680
+ entityName = opInfo.entityName;
1681
+ }
1682
+ }
1683
+ }
1684
+ }
1685
+ continue;
1686
+ }
1687
+ const expr = statement.expression;
1688
+ if (ts9.isBinaryExpression(expr) && expr.operatorToken.kind === ts9.SyntaxKind.EqualsToken) {
1689
+ if (!ts9.isIdentifier(expr.left)) {
1690
+ continue;
1691
+ }
1692
+ const varName = expr.left.text;
1693
+ const rightSide = expr.right;
1694
+ if (ts9.isCallExpression(rightSide)) {
1695
+ const opInfo = extractChainedOperation(rightSide);
1696
+ if (opInfo) {
1697
+ if (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom") {
1698
+ queryBuilderVar = varName;
1699
+ if (opInfo.entityName) {
1700
+ entityName = opInfo.entityName;
1701
+ }
1702
+ }
1703
+ if ((opInfo.operation === "select" || opInfo.operation === "include") && queryBuilderVar === varName) {
1704
+ if (opInfo.operation === "select") {
1705
+ for (const field of opInfo.fields || []) {
1706
+ selectedFields.add(field);
1707
+ }
1708
+ } else if (opInfo.operation === "include" && opInfo.includeArg) {
1709
+ const parsedIncludes = parseIncludeObjectLiteral(opInfo.includeArg);
1710
+ if (parsedIncludes) {
1711
+ for (const [relName, relSchema] of Object.entries(parsedIncludes)) {
1712
+ includes[relName] = relSchema;
1713
+ }
1714
+ }
1715
+ }
1716
+ }
1717
+ }
1718
+ }
1719
+ }
1720
+ }
1721
+ if (!hasReturn || !queryBuilderVar || !entityName) {
1722
+ return null;
1723
+ }
1724
+ return {
1725
+ entityName,
1726
+ selectedFields: Array.from(selectedFields),
1727
+ includes,
1728
+ isPaged
1729
+ };
1730
+ }
1731
+ function extractChainedOperation(callExpr) {
1732
+ if (ts9.isIdentifier(callExpr.expression)) {
1733
+ const methodName2 = callExpr.expression.text;
1734
+ if (methodName2 === "selectFromEntity" || methodName2 === "selectFrom") {
1735
+ const entityArg = callExpr.arguments[0];
1736
+ let entityName = null;
1737
+ if (ts9.isIdentifier(entityArg)) {
1738
+ entityName = entityArg.text;
1739
+ } else if (ts9.isPropertyAccessExpression(entityArg)) {
1740
+ entityName = entityArg.name.text;
1741
+ }
1742
+ return {
1743
+ operation: methodName2 === "selectFromEntity" ? "selectFromEntity" : "selectFrom",
1744
+ fields: null,
1745
+ includeArg: null,
1746
+ entityName
1747
+ };
1748
+ }
1749
+ }
1750
+ if (!ts9.isPropertyAccessExpression(callExpr.expression)) {
1751
+ return null;
1752
+ }
1753
+ const propAccess = callExpr.expression;
1754
+ const methodName = propAccess.name.text;
1755
+ if (methodName === "select") {
1756
+ const fields = [];
1757
+ for (const arg of callExpr.arguments) {
1758
+ if (ts9.isStringLiteral(arg)) {
1759
+ fields.push(arg.text);
1760
+ }
1761
+ }
1762
+ return {
1763
+ operation: "select",
1764
+ fields,
1765
+ includeArg: null,
1766
+ entityName: null
1767
+ };
1768
+ }
1769
+ if (methodName === "include") {
1770
+ return {
1771
+ operation: "include",
1772
+ fields: null,
1773
+ includeArg: callExpr.arguments[0] || null,
1774
+ entityName: null
1775
+ };
1776
+ }
1777
+ return null;
1778
+ }
1779
+ function parseIncludeObjectLiteral(arg) {
1780
+ if (!ts9.isObjectLiteralExpression(arg)) {
1781
+ return null;
1782
+ }
1783
+ const includes = {};
1784
+ for (const prop of arg.properties) {
1785
+ if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
1786
+ continue;
1787
+ }
1788
+ const relationName = prop.name.text;
1789
+ const value = prop.initializer;
1790
+ if (value.kind === ts9.SyntaxKind.TrueKeyword) {
1791
+ includes[relationName] = true;
1792
+ } else if (ts9.isObjectLiteralExpression(value)) {
1793
+ const nestedSchema = parseNestedInclude(value, 0);
1794
+ if (nestedSchema) {
1795
+ includes[relationName] = nestedSchema;
1796
+ }
1797
+ }
1798
+ }
1799
+ return includes;
1800
+ }
1801
+ function parseNestedInclude(obj, depth) {
1802
+ const selectedFields = [];
1803
+ const includes = {};
1804
+ for (const prop of obj.properties) {
1805
+ if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
1806
+ continue;
1807
+ }
1808
+ const propName = prop.name.text;
1809
+ const value = prop.initializer;
1810
+ if (propName === "select" && ts9.isArrayLiteralExpression(value)) {
1811
+ for (const element of value.elements) {
1812
+ if (ts9.isStringLiteral(element)) {
1813
+ selectedFields.push(element.text);
1814
+ }
1815
+ }
1816
+ } else if (propName === "include" && ts9.isObjectLiteralExpression(value)) {
1817
+ const nestedIncludes = parseIncludeObjectLiteral(value);
1818
+ if (nestedIncludes) {
1819
+ for (const [relName, relSchema] of Object.entries(nestedIncludes)) {
1820
+ includes[relName] = relSchema;
1821
+ }
1822
+ }
1823
+ }
1824
+ }
1825
+ return {
1826
+ entityName: "",
1827
+ selectedFields,
1828
+ includes,
1829
+ isPaged: false
1830
+ };
1831
+ }
1832
+ function getMethodName(expression) {
1833
+ if (ts9.isIdentifier(expression)) {
1834
+ return expression.text;
1835
+ }
1836
+ if (ts9.isPropertyAccessExpression(expression)) {
1837
+ return expression.name.text;
1838
+ }
1839
+ return null;
1840
+ }
1841
+ function findReturnStatement(body) {
1842
+ let returnStatement = null;
1843
+ for (const statement of body.statements) {
1844
+ if (ts9.isReturnStatement(statement)) {
1845
+ if (returnStatement !== null) {
1846
+ return null;
1847
+ }
1848
+ returnStatement = statement;
1849
+ }
1850
+ }
1851
+ return returnStatement;
1852
+ }
1853
+ function analyzeReturnExpression(expression) {
1854
+ if (!expression) {
1855
+ return null;
1856
+ }
1857
+ if (ts9.isCallExpression(expression)) {
1858
+ return buildCallChain(expression, null);
1859
+ }
1860
+ return null;
1861
+ }
1862
+ function buildCallChain(node, parent) {
1863
+ if (ts9.isCallExpression(node)) {
1864
+ const callNode = {
1865
+ expression: node.expression,
1866
+ methodName: getMethodName(node.expression),
1867
+ arguments: node.arguments,
1868
+ parent
1869
+ };
1870
+ if (ts9.isPropertyAccessExpression(node.expression)) {
1871
+ return buildCallChain(node.expression.expression, callNode);
1872
+ }
1873
+ return callNode;
1874
+ }
1875
+ return parent;
1876
+ }
1877
+ function parseQueryBuilderChain(chain, checker, options) {
1878
+ if (!chain) {
1879
+ return null;
1880
+ }
1881
+ const rootNode = findSelectFromEntityCall(chain);
1882
+ if (!rootNode) {
1883
+ return null;
1884
+ }
1885
+ const entityName = extractEntityName(rootNode, checker);
1886
+ if (!entityName) {
1887
+ return null;
1888
+ }
1889
+ const selectedFields = /* @__PURE__ */ new Set();
1890
+ const includes = {};
1891
+ let isPaged = false;
1892
+ let currentNode = chain;
1893
+ while (currentNode) {
1894
+ const methodName = currentNode.methodName;
1895
+ if (methodName === "select") {
1896
+ for (const arg of currentNode.arguments) {
1897
+ if (ts9.isStringLiteral(arg)) {
1898
+ selectedFields.add(arg.text);
1899
+ }
1900
+ }
1901
+ } else if (methodName === "include") {
1902
+ parseIncludeArgument(currentNode.arguments[0], includes, checker, options, 0);
1903
+ } else if (methodName === "executePaged") {
1904
+ isPaged = true;
1905
+ }
1906
+ currentNode = currentNode.parent;
1907
+ }
1908
+ return {
1909
+ entityName,
1910
+ selectedFields: Array.from(selectedFields),
1911
+ includes,
1912
+ isPaged
1913
+ };
1914
+ }
1915
+ function findSelectFromEntityCall(chain) {
1916
+ let currentNode = chain;
1917
+ let lastNode = null;
1918
+ while (currentNode) {
1919
+ if (currentNode.methodName === "selectFromEntity" || currentNode.methodName === "selectFrom") {
1920
+ return currentNode;
1921
+ }
1922
+ lastNode = currentNode;
1923
+ currentNode = currentNode.parent;
1924
+ }
1925
+ return lastNode;
1926
+ }
1927
+ function extractEntityName(callNode, checker) {
1928
+ if (callNode.arguments.length === 0) {
1929
+ return null;
1930
+ }
1931
+ const entityArg = callNode.arguments[0];
1932
+ if (ts9.isIdentifier(entityArg)) {
1933
+ return entityArg.text;
1934
+ }
1935
+ if (ts9.isPropertyAccessExpression(entityArg)) {
1936
+ return entityArg.name.text;
1937
+ }
1938
+ return null;
1939
+ }
1940
+ function parseIncludeArgument(arg, includes, checker, options, depth) {
1941
+ if (!arg) {
1942
+ return;
1943
+ }
1944
+ if (ts9.isObjectLiteralExpression(arg)) {
1945
+ for (const prop of arg.properties) {
1946
+ if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
1947
+ continue;
1948
+ }
1949
+ const relationName = prop.name.text;
1950
+ const value = prop.initializer;
1951
+ if (value.kind === ts9.SyntaxKind.TrueKeyword) {
1952
+ includes[relationName] = true;
1953
+ } else if (ts9.isObjectLiteralExpression(value)) {
1954
+ const maxDepth = options.maxDepth ?? 5;
1955
+ if (depth < maxDepth) {
1956
+ const nestedSchema = parseNestedInclude(value, depth + 1);
1957
+ if (nestedSchema) {
1958
+ includes[relationName] = nestedSchema;
1959
+ }
1960
+ }
1961
+ }
1962
+ }
1963
+ }
1964
+ }
1965
+
1966
+ // src/compiler/schema/queryBuilderSchemaBuilder.ts
1967
+ import "typescript";
1968
+ function wrapInPaginatedResult(schema) {
1969
+ return {
1970
+ type: "object",
1971
+ properties: {
1972
+ items: {
1973
+ type: "array",
1974
+ items: schema
1975
+ },
1976
+ page: { type: "integer" },
1977
+ pageSize: { type: "integer" },
1978
+ totalItems: { type: "integer" }
1979
+ },
1980
+ required: ["items", "page", "pageSize", "totalItems"]
1981
+ };
1982
+ }
1983
+
1565
1984
  // src/compiler/schema/openapi.ts
1566
1985
  var METAL_ORM_WRAPPER_NAMES2 = ["BelongsToReference", "HasOneReference", "HasManyCollection", "ManyToManyCollection"];
1567
1986
  function generateOpenAPI(controllers, checker, options = {}) {
@@ -1716,6 +2135,88 @@ function convertToOpenApiPath(basePath, path4) {
1716
2135
  }
1717
2136
  return fullPath;
1718
2137
  }
2138
+ function tryInferQueryBuilderSchema(operation, checker) {
2139
+ return analyzeQueryBuilderForSchema(operation.methodDeclaration, checker) ?? null;
2140
+ }
2141
+ function getEntityTypeFromReturnType(operation, checker) {
2142
+ const returnType = operation.returnType;
2143
+ const unwrapPromise2 = (type) => {
2144
+ const symbol2 = type.getSymbol();
2145
+ if (symbol2?.getName() === "Promise") {
2146
+ const typeArgs = type.typeArguments;
2147
+ if (typeArgs && typeArgs.length > 0) {
2148
+ return typeArgs[0];
2149
+ }
2150
+ }
2151
+ return type;
2152
+ };
2153
+ const innerType = unwrapPromise2(returnType);
2154
+ const symbol = innerType.getSymbol();
2155
+ if (symbol?.getName() === "PaginatedResult") {
2156
+ const typeArgs = innerType.typeArguments;
2157
+ if (typeArgs && typeArgs.length > 0) {
2158
+ return typeArgs[0];
2159
+ }
2160
+ }
2161
+ return null;
2162
+ }
2163
+ function filterSchemaByQueryBuilder(querySchema, operation, ctx) {
2164
+ const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
2165
+ if (!entityType) {
2166
+ return {};
2167
+ }
2168
+ const entitySchema = typeToJsonSchema(entityType, ctx);
2169
+ let baseSchema = entitySchema;
2170
+ if (entitySchema.$ref && entitySchema.$ref.startsWith("#/components/schemas/")) {
2171
+ const schemaName = entitySchema.$ref.replace("#/components/schemas/", "");
2172
+ const componentSchema = ctx.components.get(schemaName);
2173
+ if (componentSchema) {
2174
+ baseSchema = componentSchema;
2175
+ }
2176
+ }
2177
+ if (!baseSchema.properties || Object.keys(baseSchema.properties).length === 0) {
2178
+ return {};
2179
+ }
2180
+ const filteredSchema = buildFilteredSchema(querySchema, baseSchema);
2181
+ if (querySchema.isPaged) {
2182
+ return wrapInPaginatedResult(filteredSchema);
2183
+ }
2184
+ return filteredSchema;
2185
+ }
2186
+ function buildFilteredSchema(querySchema, entitySchema) {
2187
+ const properties = {};
2188
+ const required = [];
2189
+ for (const field of querySchema.selectedFields) {
2190
+ if (entitySchema.properties?.[field]) {
2191
+ properties[field] = entitySchema.properties[field];
2192
+ if (entitySchema.required && entitySchema.required.includes(field)) {
2193
+ required.push(field);
2194
+ }
2195
+ }
2196
+ }
2197
+ for (const [relationName, includeSpec] of Object.entries(querySchema.includes)) {
2198
+ if (entitySchema.properties?.[relationName]) {
2199
+ properties[relationName] = {
2200
+ type: "object",
2201
+ properties: {
2202
+ id: { type: "integer" }
2203
+ },
2204
+ required: ["id"]
2205
+ };
2206
+ if (entitySchema.required && entitySchema.required.includes(relationName)) {
2207
+ required.push(relationName);
2208
+ }
2209
+ }
2210
+ }
2211
+ const schema = {
2212
+ type: "object",
2213
+ properties
2214
+ };
2215
+ if (required.length > 0) {
2216
+ schema.required = required;
2217
+ }
2218
+ return schema;
2219
+ }
1719
2220
  function buildOperation(operation, ctx, controllerConsumes) {
1720
2221
  const op = {
1721
2222
  operationId: operation.operationId,
@@ -1730,7 +2231,18 @@ function buildOperation(operation, ctx, controllerConsumes) {
1730
2231
  op.parameters = parameters;
1731
2232
  }
1732
2233
  const responseCtx = { ...ctx, mode: "response" };
1733
- const responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
2234
+ let responseSchema;
2235
+ const querySchema = tryInferQueryBuilderSchema(operation, ctx.checker);
2236
+ if (querySchema) {
2237
+ const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
2238
+ if (entityType) {
2239
+ responseSchema = filterSchemaByQueryBuilder(querySchema, operation, responseCtx);
2240
+ } else {
2241
+ responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
2242
+ }
2243
+ } else {
2244
+ responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
2245
+ }
1734
2246
  const status = operation.httpMethod === "POST" ? 201 : 200;
1735
2247
  op.responses[status] = {
1736
2248
  description: status === 201 ? "Created" : "OK",
@@ -1772,12 +2284,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
1772
2284
  const declarations = typeSymbol.getDeclarations();
1773
2285
  if (!declarations || declarations.length === 0) return schema;
1774
2286
  const classDecl = declarations[0];
1775
- if (!ts9.isClassDeclaration(classDecl)) return schema;
2287
+ if (!ts11.isClassDeclaration(classDecl)) return schema;
1776
2288
  const result = { ...schema };
1777
2289
  const props = { ...result.properties };
1778
2290
  for (const member of classDecl.members) {
1779
- if (!ts9.isPropertyDeclaration(member) || !member.name) continue;
1780
- const propName = ts9.isIdentifier(member.name) ? member.name.text : null;
2291
+ if (!ts11.isPropertyDeclaration(member) || !member.name) continue;
2292
+ const propName = ts11.isIdentifier(member.name) ? member.name.text : null;
1781
2293
  if (!propName) continue;
1782
2294
  if (!props[propName]) continue;
1783
2295
  const frags = extractPropertySchemaFragments(ctx.checker, member);
@@ -1790,7 +2302,7 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
1790
2302
  }
1791
2303
 
1792
2304
  // src/compiler/manifest/emit.ts
1793
- import ts10 from "typescript";
2305
+ import ts12 from "typescript";
1794
2306
  function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
1795
2307
  const components = /* @__PURE__ */ new Map();
1796
2308
  const ctx = {
@@ -1812,7 +2324,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
1812
2324
  generator: {
1813
2325
  name: "adorn-api",
1814
2326
  version,
1815
- typescript: ts10.version
2327
+ typescript: ts12.version
1816
2328
  },
1817
2329
  schemas: {
1818
2330
  kind: "openapi-3.1",
@@ -2297,7 +2809,7 @@ async function isStale(params) {
2297
2809
  // src/compiler/cache/writeCache.ts
2298
2810
  import fs3 from "fs";
2299
2811
  import path3 from "path";
2300
- import ts11 from "typescript";
2812
+ import ts13 from "typescript";
2301
2813
  function statMtimeMs2(p) {
2302
2814
  return fs3.statSync(p).mtimeMs;
2303
2815
  }
@@ -2330,7 +2842,7 @@ function writeCache(params) {
2330
2842
  generator: {
2331
2843
  name: "adorn-api",
2332
2844
  version: params.adornVersion,
2333
- typescript: ts11.version
2845
+ typescript: ts13.version
2334
2846
  },
2335
2847
  project: {
2336
2848
  tsconfigPath: params.tsconfigAbs,
@@ -2850,7 +3362,7 @@ function partitionSchemas(schemas, graph, schemaGraph, config = {}) {
2850
3362
  complexity: totalComplexity,
2851
3363
  dependencies: []
2852
3364
  }];
2853
- recommendation = recommendation || "Single file mode (--no-split)";
3365
+ recommendation = recommendation || "Single file mode (--split not specified)";
2854
3366
  } else if (strategy === "controller") {
2855
3367
  groups = partitionByController(schemas, graph, finalConfig);
2856
3368
  } else if (strategy === "dependency") {
@@ -3083,7 +3595,7 @@ function getEdgesByRelation(graph, relation) {
3083
3595
  }
3084
3596
 
3085
3597
  // src/compiler/graph/builder.ts
3086
- import ts12 from "typescript";
3598
+ import ts14 from "typescript";
3087
3599
 
3088
3600
  // src/compiler/graph/schemaGraph.ts
3089
3601
  var SchemaGraph = class {
@@ -3335,7 +3847,7 @@ var SchemaGraph = class {
3335
3847
  };
3336
3848
 
3337
3849
  // src/cli.ts
3338
- import ts13 from "typescript";
3850
+ import ts15 from "typescript";
3339
3851
  import process2 from "process";
3340
3852
  var ADORN_VERSION = (() => {
3341
3853
  const tryReadPackageJson = (filePath) => {
@@ -3413,7 +3925,7 @@ function sanitizeForJson(obj) {
3413
3925
  return result;
3414
3926
  }
3415
3927
  function buildControllerGraph(controllers) {
3416
- const graph = createGraph(ts13.version);
3928
+ const graph = createGraph(ts15.version);
3417
3929
  const nodeMap = /* @__PURE__ */ new Map();
3418
3930
  for (const ctrl of controllers) {
3419
3931
  const nodeId = `Controller:${ctrl.className}`;
@@ -3504,7 +4016,7 @@ async function buildCommand(args) {
3504
4016
  const validationMode = validationModeIndex !== -1 ? args[validationModeIndex + 1] : "ajv-runtime";
3505
4017
  const verbose = args.includes("--verbose");
3506
4018
  const quiet = args.includes("--quiet");
3507
- const noSplit = args.includes("--no-split");
4019
+ const split = args.includes("--split");
3508
4020
  const splitStrategyIndex = args.indexOf("--split-strategy");
3509
4021
  const splitStrategy = splitStrategyIndex !== -1 ? args[splitStrategyIndex + 1] : void 0;
3510
4022
  const splitThresholdIndex = args.indexOf("--split-threshold");
@@ -3524,7 +4036,7 @@ async function buildCommand(args) {
3524
4036
  outDir: outputDir,
3525
4037
  project: projectPath,
3526
4038
  adornVersion: ADORN_VERSION,
3527
- typescriptVersion: ts13.version
4039
+ typescriptVersion: ts15.version
3528
4040
  });
3529
4041
  if (!stale.stale) {
3530
4042
  progress.completePhase("staleness-check");
@@ -3582,7 +4094,7 @@ async function buildCommand(args) {
3582
4094
  if (!quiet) openapiSpinner.stop();
3583
4095
  const schemaCount = Object.keys(openapi.components?.schemas || {}).length;
3584
4096
  let splitEnabled = false;
3585
- if (!noSplit && schemaCount >= splitThreshold) {
4097
+ if (split && schemaCount >= splitThreshold) {
3586
4098
  progress.verboseLog(`Schema count (${schemaCount}) >= threshold (${splitThreshold}), analyzing for auto-split...`);
3587
4099
  const graph = buildControllerGraph(controllers);
3588
4100
  const schemaGraph = new SchemaGraph(graph);
@@ -3622,9 +4134,9 @@ async function buildCommand(args) {
3622
4134
  log(` Auto-split not needed: ${partitioning.recommendation}`);
3623
4135
  }
3624
4136
  }
3625
- } else if (noSplit) {
4137
+ } else if (!split) {
3626
4138
  if (!quiet) {
3627
- log(` Splitting disabled (--no-split)`);
4139
+ log(` Splitting disabled (--split not specified)`);
3628
4140
  }
3629
4141
  } else {
3630
4142
  if (!quiet) {
@@ -3745,12 +4257,12 @@ Commands:
3745
4257
  build Generate OpenAPI and manifest from TypeScript source
3746
4258
  clean Remove generated artifacts
3747
4259
 
3748
- Options:
4260
+ Options:
3749
4261
  -p <path> Path to tsconfig.json (default: ./tsconfig.json)
3750
4262
  --output <dir> Output directory (default: .adorn)
3751
4263
  --if-stale Only rebuild if artifacts are stale
3752
4264
  --validation-mode <mode> Validation mode: none, ajv-runtime, precompiled (default: ajv-runtime)
3753
- --no-split Disable automatic schema splitting (default: auto-split enabled)
4265
+ --split Enable automatic schema splitting (default: disabled)
3754
4266
  --split-strategy <mode> Override splitting strategy: controller, dependency, size, auto (default: auto)
3755
4267
  --split-threshold <num> Schema count threshold for auto-split (default: 50)
3756
4268
  --verbose Show detailed progress information
@@ -3761,7 +4273,7 @@ Examples:
3761
4273
  adorn-api build --if-stale
3762
4274
  adorn-api build --validation-mode precompiled
3763
4275
  adorn-api build --verbose
3764
- adorn-api build --no-split # Force single file mode
4276
+ adorn-api build --split # Enable split mode
3765
4277
  adorn-api build --split-strategy controller # Force controller-based splitting
3766
4278
  adorn-api build --split-threshold 100 # Increase threshold to 100
3767
4279
  adorn-api clean