adorn-api 1.0.22 → 1.0.23

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 ts11 from "typescript";
309
+ import ts12 from "typescript";
310
310
 
311
311
  // src/compiler/schema/typeToJsonSchema.ts
312
312
  import ts7 from "typescript";
@@ -1612,7 +1612,221 @@ function resolveAndCollectObjectProps(schema, components) {
1612
1612
  }
1613
1613
 
1614
1614
  // src/compiler/schema/queryBuilderAnalyzer.ts
1615
+ import ts10 from "typescript";
1616
+
1617
+ // src/compiler/schema/serviceCallAnalyzer.ts
1615
1618
  import ts9 from "typescript";
1619
+ var ServiceCallAnalyzer = class {
1620
+ checker;
1621
+ program;
1622
+ cache = /* @__PURE__ */ new Map();
1623
+ analyzedMethods = /* @__PURE__ */ new Set();
1624
+ constructor(checker, program) {
1625
+ this.checker = checker;
1626
+ this.program = program;
1627
+ }
1628
+ /**
1629
+ * Analyzes a controller method for query builder patterns, following service calls
1630
+ */
1631
+ analyzeControllerMethod(methodDeclaration, options = {}) {
1632
+ const cacheKey = this.getMethodCacheKey(methodDeclaration);
1633
+ if (this.cache.has(cacheKey)) {
1634
+ return this.cache.get(cacheKey) ?? null;
1635
+ }
1636
+ const maxDepth = options.maxDepth ?? 3;
1637
+ const schema = this.analyzeMethodWithServiceCalls(methodDeclaration, 0, maxDepth, options);
1638
+ this.cache.set(cacheKey, schema);
1639
+ return schema;
1640
+ }
1641
+ /**
1642
+ * Recursively analyzes method with service call traversal
1643
+ */
1644
+ analyzeMethodWithServiceCalls(methodDeclaration, currentDepth, maxDepth, options) {
1645
+ if (currentDepth >= maxDepth) {
1646
+ return null;
1647
+ }
1648
+ const methodKey = this.getMethodCacheKey(methodDeclaration);
1649
+ if (this.analyzedMethods.has(methodKey)) {
1650
+ return null;
1651
+ }
1652
+ this.analyzedMethods.add(methodKey);
1653
+ const directSchema = analyzeQueryBuilderForSchema(methodDeclaration, this.checker);
1654
+ if (directSchema) {
1655
+ return directSchema;
1656
+ }
1657
+ const serviceCalls = this.findServiceCalls(methodDeclaration);
1658
+ for (const serviceCall of serviceCalls) {
1659
+ const serviceSchema = this.analyzeServiceMethod(serviceCall, currentDepth, maxDepth, options);
1660
+ if (serviceSchema) {
1661
+ return serviceSchema;
1662
+ }
1663
+ }
1664
+ return null;
1665
+ }
1666
+ /**
1667
+ * Analyzes a service method for query builder patterns
1668
+ */
1669
+ analyzeServiceMethod(serviceCall, currentDepth, maxDepth, options) {
1670
+ const directSchema = analyzeQueryBuilderForSchema(serviceCall.methodDeclaration, this.checker);
1671
+ if (directSchema) {
1672
+ return directSchema;
1673
+ }
1674
+ if (options.analyzeHelpers) {
1675
+ return this.analyzeMethodWithServiceCalls(
1676
+ serviceCall.methodDeclaration,
1677
+ currentDepth + 1,
1678
+ maxDepth,
1679
+ options
1680
+ );
1681
+ }
1682
+ return null;
1683
+ }
1684
+ /**
1685
+ * Finds service calls in a method body
1686
+ */
1687
+ findServiceCalls(methodDeclaration) {
1688
+ const serviceCalls = [];
1689
+ const body = methodDeclaration.body;
1690
+ if (!body) {
1691
+ return serviceCalls;
1692
+ }
1693
+ const visitor = (node) => {
1694
+ if (ts9.isCallExpression(node)) {
1695
+ const serviceCall = this.resolveServiceCall(node);
1696
+ if (serviceCall) {
1697
+ serviceCalls.push(serviceCall);
1698
+ }
1699
+ }
1700
+ ts9.forEachChild(node, visitor);
1701
+ };
1702
+ ts9.forEachChild(body, visitor);
1703
+ return serviceCalls;
1704
+ }
1705
+ /**
1706
+ * Resolves a call expression to a service method
1707
+ */
1708
+ resolveServiceCall(callExpression) {
1709
+ if (ts9.isPropertyAccessExpression(callExpression.expression)) {
1710
+ const propAccess = callExpression.expression;
1711
+ const methodName = propAccess.name.text;
1712
+ const objectType = this.checker.getTypeAtLocation(propAccess.expression);
1713
+ const objectSymbol = objectType.getSymbol();
1714
+ if (objectSymbol) {
1715
+ const classDeclaration = this.findClassDeclaration(objectSymbol);
1716
+ if (classDeclaration) {
1717
+ const methodDeclaration = this.findMethodDeclaration(classDeclaration, methodName);
1718
+ if (methodDeclaration) {
1719
+ return {
1720
+ serviceName: classDeclaration.name?.text || "Unknown",
1721
+ methodName,
1722
+ filePath: classDeclaration.getSourceFile().fileName,
1723
+ classDeclaration,
1724
+ methodDeclaration
1725
+ };
1726
+ }
1727
+ }
1728
+ }
1729
+ }
1730
+ if (ts9.isPropertyAccessExpression(callExpression.expression)) {
1731
+ const propAccess = callExpression.expression;
1732
+ const methodName = propAccess.name.text;
1733
+ if (ts9.isIdentifier(propAccess.expression)) {
1734
+ const className = propAccess.expression.text;
1735
+ const classSymbol = this.checker.getSymbolAtLocation(propAccess.expression);
1736
+ if (classSymbol) {
1737
+ const classDeclaration = this.findClassDeclaration(classSymbol);
1738
+ if (classDeclaration && classDeclaration.name?.text === className) {
1739
+ const methodDeclaration = this.findMethodDeclaration(classDeclaration, methodName);
1740
+ if (methodDeclaration) {
1741
+ return {
1742
+ serviceName: className,
1743
+ methodName,
1744
+ filePath: classDeclaration.getSourceFile().fileName,
1745
+ classDeclaration,
1746
+ methodDeclaration
1747
+ };
1748
+ }
1749
+ }
1750
+ }
1751
+ }
1752
+ }
1753
+ return null;
1754
+ }
1755
+ /**
1756
+ * Finds class declaration from a symbol
1757
+ */
1758
+ findClassDeclaration(symbol) {
1759
+ const declarations = symbol.getDeclarations();
1760
+ if (!declarations) return null;
1761
+ for (const declaration of declarations) {
1762
+ if (ts9.isClassDeclaration(declaration)) {
1763
+ return declaration;
1764
+ }
1765
+ }
1766
+ return null;
1767
+ }
1768
+ /**
1769
+ * Finds method declaration in a class
1770
+ */
1771
+ findMethodDeclaration(classDeclaration, methodName) {
1772
+ for (const member of classDeclaration.members) {
1773
+ if (ts9.isMethodDeclaration(member) && member.name) {
1774
+ if (ts9.isIdentifier(member.name) && member.name.text === methodName) {
1775
+ return member;
1776
+ }
1777
+ }
1778
+ }
1779
+ return null;
1780
+ }
1781
+ /**
1782
+ * Generates cache key for a method
1783
+ */
1784
+ getMethodCacheKey(methodDeclaration) {
1785
+ const sourceFile = methodDeclaration.getSourceFile();
1786
+ const className = this.getClassName(methodDeclaration);
1787
+ const methodName = methodDeclaration.name?.getText() || "unknown";
1788
+ const line = sourceFile.getLineAndCharacterOfPosition(methodDeclaration.getStart()).line;
1789
+ return `${sourceFile.fileName}:${className}:${methodName}:${line}`;
1790
+ }
1791
+ /**
1792
+ * Gets class name from method declaration
1793
+ */
1794
+ getClassName(methodDeclaration) {
1795
+ let node = methodDeclaration;
1796
+ while (node) {
1797
+ if (ts9.isClassDeclaration(node)) {
1798
+ return node.name?.text || "Unknown";
1799
+ }
1800
+ node = node.parent;
1801
+ }
1802
+ return "Unknown";
1803
+ }
1804
+ /**
1805
+ * Clears the analysis cache
1806
+ */
1807
+ clearCache() {
1808
+ this.cache.clear();
1809
+ this.analyzedMethods.clear();
1810
+ }
1811
+ /**
1812
+ * Gets cache statistics
1813
+ */
1814
+ getCacheStats() {
1815
+ return {
1816
+ cached: this.cache.size,
1817
+ analyzed: this.analyzedMethods.size
1818
+ };
1819
+ }
1820
+ };
1821
+ function analyzeControllerWithServiceCalls(methodDeclaration, checker, program, options = {}) {
1822
+ if (!program) {
1823
+ return null;
1824
+ }
1825
+ const analyzer = new ServiceCallAnalyzer(checker, program);
1826
+ return analyzer.analyzeControllerMethod(methodDeclaration, options);
1827
+ }
1828
+
1829
+ // src/compiler/schema/queryBuilderAnalyzer.ts
1616
1830
  function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {}) {
1617
1831
  const body = methodDeclaration.body;
1618
1832
  if (!body) {
@@ -1632,8 +1846,18 @@ function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {})
1632
1846
  }
1633
1847
  return parseQueryBuilderChain(callChain, checker, options);
1634
1848
  }
1635
- function analyzeQueryBuilderWithDetails(methodDeclaration, checker, options = {}, operationInfo) {
1636
- const schema = analyzeQueryBuilderForSchema(methodDeclaration, checker, options);
1849
+ function analyzeQueryBuilderWithServiceCalls(methodDeclaration, checker, program, options = {}, operationInfo) {
1850
+ let schema = analyzeQueryBuilderForSchema(methodDeclaration, checker, options);
1851
+ if (!schema && program) {
1852
+ try {
1853
+ schema = analyzeControllerWithServiceCalls(methodDeclaration, checker, program, {
1854
+ maxDepth: options.maxDepth,
1855
+ analyzeHelpers: options.analyzeHelpers
1856
+ });
1857
+ } catch (error) {
1858
+ console.warn("Service call analysis failed:", error);
1859
+ }
1860
+ }
1637
1861
  return {
1638
1862
  detected: schema !== null,
1639
1863
  schema,
@@ -1648,12 +1872,12 @@ function analyzeWithVariableTracking(body, checker, options) {
1648
1872
  let isPaged = false;
1649
1873
  let hasReturn = false;
1650
1874
  for (const statement of body.statements) {
1651
- if (ts9.isReturnStatement(statement)) {
1875
+ if (ts10.isReturnStatement(statement)) {
1652
1876
  hasReturn = true;
1653
1877
  const returnExpr = statement.expression;
1654
- if (returnExpr && ts9.isCallExpression(returnExpr)) {
1878
+ if (returnExpr && ts10.isCallExpression(returnExpr)) {
1655
1879
  const callExpr = returnExpr;
1656
- if (ts9.isIdentifier(callExpr.expression) && queryBuilderVar) {
1880
+ if (ts10.isIdentifier(callExpr.expression) && queryBuilderVar) {
1657
1881
  const varName = callExpr.expression.text;
1658
1882
  if (varName === queryBuilderVar) {
1659
1883
  const methodName = callExpr.expression.text;
@@ -1662,9 +1886,9 @@ function analyzeWithVariableTracking(body, checker, options) {
1662
1886
  }
1663
1887
  }
1664
1888
  }
1665
- if (ts9.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
1889
+ if (ts10.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
1666
1890
  const propAccess = callExpr.expression;
1667
- if (ts9.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
1891
+ if (ts10.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
1668
1892
  const methodName = propAccess.name.text;
1669
1893
  if (methodName === "executePaged") {
1670
1894
  isPaged = true;
@@ -1674,13 +1898,13 @@ function analyzeWithVariableTracking(body, checker, options) {
1674
1898
  }
1675
1899
  continue;
1676
1900
  }
1677
- if (!ts9.isExpressionStatement(statement)) {
1678
- if (ts9.isVariableStatement(statement)) {
1901
+ if (!ts10.isExpressionStatement(statement)) {
1902
+ if (ts10.isVariableStatement(statement)) {
1679
1903
  for (const declaration of statement.declarationList.declarations) {
1680
- if (!ts9.isIdentifier(declaration.name)) continue;
1904
+ if (!ts10.isIdentifier(declaration.name)) continue;
1681
1905
  const varName = declaration.name.text;
1682
1906
  const initializer = declaration.initializer;
1683
- if (!initializer || !ts9.isCallExpression(initializer)) continue;
1907
+ if (!initializer || !ts10.isCallExpression(initializer)) continue;
1684
1908
  const opInfo = extractChainedOperation(initializer);
1685
1909
  if (opInfo && (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom")) {
1686
1910
  queryBuilderVar = varName;
@@ -1693,13 +1917,13 @@ function analyzeWithVariableTracking(body, checker, options) {
1693
1917
  continue;
1694
1918
  }
1695
1919
  const expr = statement.expression;
1696
- if (ts9.isBinaryExpression(expr) && expr.operatorToken.kind === ts9.SyntaxKind.EqualsToken) {
1697
- if (!ts9.isIdentifier(expr.left)) {
1920
+ if (ts10.isBinaryExpression(expr) && expr.operatorToken.kind === ts10.SyntaxKind.EqualsToken) {
1921
+ if (!ts10.isIdentifier(expr.left)) {
1698
1922
  continue;
1699
1923
  }
1700
1924
  const varName = expr.left.text;
1701
1925
  const rightSide = expr.right;
1702
- if (ts9.isCallExpression(rightSide)) {
1926
+ if (ts10.isCallExpression(rightSide)) {
1703
1927
  const opInfo = extractChainedOperation(rightSide);
1704
1928
  if (opInfo) {
1705
1929
  if (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom") {
@@ -1737,14 +1961,14 @@ function analyzeWithVariableTracking(body, checker, options) {
1737
1961
  };
1738
1962
  }
1739
1963
  function extractChainedOperation(callExpr) {
1740
- if (ts9.isIdentifier(callExpr.expression)) {
1964
+ if (ts10.isIdentifier(callExpr.expression)) {
1741
1965
  const methodName2 = callExpr.expression.text;
1742
1966
  if (methodName2 === "selectFromEntity" || methodName2 === "selectFrom") {
1743
1967
  const entityArg = callExpr.arguments[0];
1744
1968
  let entityName = null;
1745
- if (ts9.isIdentifier(entityArg)) {
1969
+ if (ts10.isIdentifier(entityArg)) {
1746
1970
  entityName = entityArg.text;
1747
- } else if (ts9.isPropertyAccessExpression(entityArg)) {
1971
+ } else if (ts10.isPropertyAccessExpression(entityArg)) {
1748
1972
  entityName = entityArg.name.text;
1749
1973
  }
1750
1974
  return {
@@ -1755,7 +1979,7 @@ function extractChainedOperation(callExpr) {
1755
1979
  };
1756
1980
  }
1757
1981
  }
1758
- if (!ts9.isPropertyAccessExpression(callExpr.expression)) {
1982
+ if (!ts10.isPropertyAccessExpression(callExpr.expression)) {
1759
1983
  return null;
1760
1984
  }
1761
1985
  const propAccess = callExpr.expression;
@@ -1763,7 +1987,7 @@ function extractChainedOperation(callExpr) {
1763
1987
  if (methodName === "select") {
1764
1988
  const fields = [];
1765
1989
  for (const arg of callExpr.arguments) {
1766
- if (ts9.isStringLiteral(arg)) {
1990
+ if (ts10.isStringLiteral(arg)) {
1767
1991
  fields.push(arg.text);
1768
1992
  }
1769
1993
  }
@@ -1785,19 +2009,19 @@ function extractChainedOperation(callExpr) {
1785
2009
  return null;
1786
2010
  }
1787
2011
  function parseIncludeObjectLiteral(arg) {
1788
- if (!ts9.isObjectLiteralExpression(arg)) {
2012
+ if (!ts10.isObjectLiteralExpression(arg)) {
1789
2013
  return null;
1790
2014
  }
1791
2015
  const includes = {};
1792
2016
  for (const prop of arg.properties) {
1793
- if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
2017
+ if (!ts10.isPropertyAssignment(prop) || !ts10.isIdentifier(prop.name)) {
1794
2018
  continue;
1795
2019
  }
1796
2020
  const relationName = prop.name.text;
1797
2021
  const value = prop.initializer;
1798
- if (value.kind === ts9.SyntaxKind.TrueKeyword) {
2022
+ if (value.kind === ts10.SyntaxKind.TrueKeyword) {
1799
2023
  includes[relationName] = true;
1800
- } else if (ts9.isObjectLiteralExpression(value)) {
2024
+ } else if (ts10.isObjectLiteralExpression(value)) {
1801
2025
  const nestedSchema = parseNestedInclude(value, 0);
1802
2026
  if (nestedSchema) {
1803
2027
  includes[relationName] = nestedSchema;
@@ -1810,18 +2034,18 @@ function parseNestedInclude(obj, depth) {
1810
2034
  const selectedFields = [];
1811
2035
  const includes = {};
1812
2036
  for (const prop of obj.properties) {
1813
- if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
2037
+ if (!ts10.isPropertyAssignment(prop) || !ts10.isIdentifier(prop.name)) {
1814
2038
  continue;
1815
2039
  }
1816
2040
  const propName = prop.name.text;
1817
2041
  const value = prop.initializer;
1818
- if (propName === "select" && ts9.isArrayLiteralExpression(value)) {
2042
+ if (propName === "select" && ts10.isArrayLiteralExpression(value)) {
1819
2043
  for (const element of value.elements) {
1820
- if (ts9.isStringLiteral(element)) {
2044
+ if (ts10.isStringLiteral(element)) {
1821
2045
  selectedFields.push(element.text);
1822
2046
  }
1823
2047
  }
1824
- } else if (propName === "include" && ts9.isObjectLiteralExpression(value)) {
2048
+ } else if (propName === "include" && ts10.isObjectLiteralExpression(value)) {
1825
2049
  const nestedIncludes = parseIncludeObjectLiteral(value);
1826
2050
  if (nestedIncludes) {
1827
2051
  for (const [relName, relSchema] of Object.entries(nestedIncludes)) {
@@ -1838,10 +2062,10 @@ function parseNestedInclude(obj, depth) {
1838
2062
  };
1839
2063
  }
1840
2064
  function getMethodName(expression) {
1841
- if (ts9.isIdentifier(expression)) {
2065
+ if (ts10.isIdentifier(expression)) {
1842
2066
  return expression.text;
1843
2067
  }
1844
- if (ts9.isPropertyAccessExpression(expression)) {
2068
+ if (ts10.isPropertyAccessExpression(expression)) {
1845
2069
  return expression.name.text;
1846
2070
  }
1847
2071
  return null;
@@ -1849,7 +2073,7 @@ function getMethodName(expression) {
1849
2073
  function findReturnStatement(body) {
1850
2074
  let returnStatement = null;
1851
2075
  for (const statement of body.statements) {
1852
- if (ts9.isReturnStatement(statement)) {
2076
+ if (ts10.isReturnStatement(statement)) {
1853
2077
  if (returnStatement !== null) {
1854
2078
  return null;
1855
2079
  }
@@ -1862,20 +2086,20 @@ function analyzeReturnExpression(expression) {
1862
2086
  if (!expression) {
1863
2087
  return null;
1864
2088
  }
1865
- if (ts9.isCallExpression(expression)) {
2089
+ if (ts10.isCallExpression(expression)) {
1866
2090
  return buildCallChain(expression, null);
1867
2091
  }
1868
2092
  return null;
1869
2093
  }
1870
2094
  function buildCallChain(node, parent) {
1871
- if (ts9.isCallExpression(node)) {
2095
+ if (ts10.isCallExpression(node)) {
1872
2096
  const callNode = {
1873
2097
  expression: node.expression,
1874
2098
  methodName: getMethodName(node.expression),
1875
2099
  arguments: node.arguments,
1876
2100
  parent
1877
2101
  };
1878
- if (ts9.isPropertyAccessExpression(node.expression)) {
2102
+ if (ts10.isPropertyAccessExpression(node.expression)) {
1879
2103
  return buildCallChain(node.expression.expression, callNode);
1880
2104
  }
1881
2105
  return callNode;
@@ -1902,7 +2126,7 @@ function parseQueryBuilderChain(chain, checker, options) {
1902
2126
  const methodName = currentNode.methodName;
1903
2127
  if (methodName === "select") {
1904
2128
  for (const arg of currentNode.arguments) {
1905
- if (ts9.isStringLiteral(arg)) {
2129
+ if (ts10.isStringLiteral(arg)) {
1906
2130
  selectedFields.add(arg.text);
1907
2131
  }
1908
2132
  }
@@ -1937,10 +2161,10 @@ function extractEntityName(callNode, checker) {
1937
2161
  return null;
1938
2162
  }
1939
2163
  const entityArg = callNode.arguments[0];
1940
- if (ts9.isIdentifier(entityArg)) {
2164
+ if (ts10.isIdentifier(entityArg)) {
1941
2165
  return entityArg.text;
1942
2166
  }
1943
- if (ts9.isPropertyAccessExpression(entityArg)) {
2167
+ if (ts10.isPropertyAccessExpression(entityArg)) {
1944
2168
  return entityArg.name.text;
1945
2169
  }
1946
2170
  return null;
@@ -1949,16 +2173,16 @@ function parseIncludeArgument(arg, includes, checker, options, depth) {
1949
2173
  if (!arg) {
1950
2174
  return;
1951
2175
  }
1952
- if (ts9.isObjectLiteralExpression(arg)) {
2176
+ if (ts10.isObjectLiteralExpression(arg)) {
1953
2177
  for (const prop of arg.properties) {
1954
- if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
2178
+ if (!ts10.isPropertyAssignment(prop) || !ts10.isIdentifier(prop.name)) {
1955
2179
  continue;
1956
2180
  }
1957
2181
  const relationName = prop.name.text;
1958
2182
  const value = prop.initializer;
1959
- if (value.kind === ts9.SyntaxKind.TrueKeyword) {
2183
+ if (value.kind === ts10.SyntaxKind.TrueKeyword) {
1960
2184
  includes[relationName] = true;
1961
- } else if (ts9.isObjectLiteralExpression(value)) {
2185
+ } else if (ts10.isObjectLiteralExpression(value)) {
1962
2186
  const maxDepth = options.maxDepth ?? 5;
1963
2187
  if (depth < maxDepth) {
1964
2188
  const nestedSchema = parseNestedInclude(value, depth + 1);
@@ -2018,9 +2242,11 @@ function generateOpenAPI(controllers, checker, options = {}) {
2018
2242
  paths[fullPath] = {};
2019
2243
  }
2020
2244
  const method = operation.httpMethod.toLowerCase();
2021
- const analysisResult = analyzeQueryBuilderWithDetails(
2245
+ const analysisResult = analyzeQueryBuilderWithServiceCalls(
2022
2246
  operation.methodDeclaration,
2023
2247
  checker,
2248
+ null,
2249
+ // TODO: Pass program when available
2024
2250
  {},
2025
2251
  {
2026
2252
  methodName: operation.operationId,
@@ -2323,12 +2549,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
2323
2549
  const declarations = typeSymbol.getDeclarations();
2324
2550
  if (!declarations || declarations.length === 0) return schema;
2325
2551
  const classDecl = declarations[0];
2326
- if (!ts11.isClassDeclaration(classDecl)) return schema;
2552
+ if (!ts12.isClassDeclaration(classDecl)) return schema;
2327
2553
  const result = { ...schema };
2328
2554
  const props = { ...result.properties };
2329
2555
  for (const member of classDecl.members) {
2330
- if (!ts11.isPropertyDeclaration(member) || !member.name) continue;
2331
- const propName = ts11.isIdentifier(member.name) ? member.name.text : null;
2556
+ if (!ts12.isPropertyDeclaration(member) || !member.name) continue;
2557
+ const propName = ts12.isIdentifier(member.name) ? member.name.text : null;
2332
2558
  if (!propName) continue;
2333
2559
  if (!props[propName]) continue;
2334
2560
  const frags = extractPropertySchemaFragments(ctx.checker, member);
@@ -2341,7 +2567,7 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
2341
2567
  }
2342
2568
 
2343
2569
  // src/compiler/manifest/emit.ts
2344
- import ts12 from "typescript";
2570
+ import ts13 from "typescript";
2345
2571
  function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
2346
2572
  const components = /* @__PURE__ */ new Map();
2347
2573
  const ctx = {
@@ -2363,7 +2589,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
2363
2589
  generator: {
2364
2590
  name: "adorn-api",
2365
2591
  version,
2366
- typescript: ts12.version
2592
+ typescript: ts13.version
2367
2593
  },
2368
2594
  schemas: {
2369
2595
  kind: "openapi-3.1",
@@ -2848,7 +3074,7 @@ async function isStale(params) {
2848
3074
  // src/compiler/cache/writeCache.ts
2849
3075
  import fs3 from "fs";
2850
3076
  import path3 from "path";
2851
- import ts13 from "typescript";
3077
+ import ts14 from "typescript";
2852
3078
  function statMtimeMs2(p) {
2853
3079
  return fs3.statSync(p).mtimeMs;
2854
3080
  }
@@ -2881,7 +3107,7 @@ function writeCache(params) {
2881
3107
  generator: {
2882
3108
  name: "adorn-api",
2883
3109
  version: params.adornVersion,
2884
- typescript: ts13.version
3110
+ typescript: ts14.version
2885
3111
  },
2886
3112
  project: {
2887
3113
  tsconfigPath: params.tsconfigAbs,
@@ -3043,6 +3269,8 @@ var Spinner = class {
3043
3269
  current = 0;
3044
3270
  total = 0;
3045
3271
  customStatus;
3272
+ frameIndex = 0;
3273
+ lastLineLength = 0;
3046
3274
  constructor(message = "") {
3047
3275
  this.message = message;
3048
3276
  }
@@ -3050,9 +3278,8 @@ var Spinner = class {
3050
3278
  * Start the spinner.
3051
3279
  */
3052
3280
  start() {
3053
- let frameIndex = 0;
3054
3281
  this.interval = setInterval(() => {
3055
- const frame = this.frames[frameIndex];
3282
+ const frame = this.frames[this.frameIndex];
3056
3283
  let output;
3057
3284
  if (this.customStatus) {
3058
3285
  output = `\r${frame} ${this.customStatus}`;
@@ -3061,11 +3288,12 @@ var Spinner = class {
3061
3288
  } else {
3062
3289
  output = `\r${frame} ${this.message}`;
3063
3290
  }
3291
+ this.lastLineLength = output.length - 1;
3064
3292
  process.stdout.write(output);
3065
3293
  if (process.stdout.writable) {
3066
3294
  process.stdout.write("");
3067
3295
  }
3068
- frameIndex = (frameIndex + 1) % this.frames.length;
3296
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
3069
3297
  }, 80);
3070
3298
  }
3071
3299
  /**
@@ -3080,8 +3308,12 @@ var Spinner = class {
3080
3308
  */
3081
3309
  setStatus(status) {
3082
3310
  this.customStatus = status;
3083
- const frame = this.frames[this.current];
3084
- process.stdout.write(`\r${frame} ${status}`);
3311
+ const frame = this.frames[this.frameIndex];
3312
+ const output = `\r${frame} ${status}`;
3313
+ const clearLength = Math.max(this.lastLineLength, output.length - 1);
3314
+ process.stdout.write("\r" + " ".repeat(clearLength) + "\r");
3315
+ this.lastLineLength = output.length - 1;
3316
+ process.stdout.write(output);
3085
3317
  if (process.stdout.writable) {
3086
3318
  process.stdout.write("");
3087
3319
  }
@@ -3100,7 +3332,7 @@ var Spinner = class {
3100
3332
  clearInterval(this.interval);
3101
3333
  this.interval = void 0;
3102
3334
  }
3103
- process.stdout.write("\r" + " ".repeat(60) + "\r");
3335
+ process.stdout.write("\r" + " ".repeat(this.lastLineLength) + "\r");
3104
3336
  if (completedMessage) {
3105
3337
  process.stdout.write(completedMessage + "\n");
3106
3338
  }
@@ -3634,7 +3866,7 @@ function getEdgesByRelation(graph, relation) {
3634
3866
  }
3635
3867
 
3636
3868
  // src/compiler/graph/builder.ts
3637
- import ts14 from "typescript";
3869
+ import ts15 from "typescript";
3638
3870
 
3639
3871
  // src/compiler/graph/schemaGraph.ts
3640
3872
  var SchemaGraph = class {
@@ -3886,7 +4118,7 @@ var SchemaGraph = class {
3886
4118
  };
3887
4119
 
3888
4120
  // src/cli.ts
3889
- import ts15 from "typescript";
4121
+ import ts16 from "typescript";
3890
4122
  import process2 from "process";
3891
4123
  var ADORN_VERSION = (() => {
3892
4124
  const tryReadPackageJson = (filePath) => {
@@ -3964,7 +4196,7 @@ function sanitizeForJson(obj) {
3964
4196
  return result;
3965
4197
  }
3966
4198
  function buildControllerGraph(controllers) {
3967
- const graph = createGraph(ts15.version);
4199
+ const graph = createGraph(ts16.version);
3968
4200
  const nodeMap = /* @__PURE__ */ new Map();
3969
4201
  for (const ctrl of controllers) {
3970
4202
  const nodeId = `Controller:${ctrl.className}`;
@@ -4076,7 +4308,7 @@ async function buildCommand(args) {
4076
4308
  outDir: outputDir,
4077
4309
  project: projectPath,
4078
4310
  adornVersion: ADORN_VERSION,
4079
- typescriptVersion: ts15.version
4311
+ typescriptVersion: ts16.version
4080
4312
  });
4081
4313
  if (!stale.stale) {
4082
4314
  progress.completePhase("staleness-check");