adorn-api 1.0.21 → 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.cjs CHANGED
@@ -323,7 +323,7 @@ function unwrapPromiseTypeNode(typeNode) {
323
323
  }
324
324
 
325
325
  // src/compiler/schema/openapi.ts
326
- var import_typescript11 = __toESM(require("typescript"), 1);
326
+ var import_typescript12 = __toESM(require("typescript"), 1);
327
327
 
328
328
  // src/compiler/schema/typeToJsonSchema.ts
329
329
  var import_typescript7 = __toESM(require("typescript"), 1);
@@ -1629,7 +1629,221 @@ function resolveAndCollectObjectProps(schema, components) {
1629
1629
  }
1630
1630
 
1631
1631
  // src/compiler/schema/queryBuilderAnalyzer.ts
1632
+ var import_typescript10 = __toESM(require("typescript"), 1);
1633
+
1634
+ // src/compiler/schema/serviceCallAnalyzer.ts
1632
1635
  var import_typescript9 = __toESM(require("typescript"), 1);
1636
+ var ServiceCallAnalyzer = class {
1637
+ checker;
1638
+ program;
1639
+ cache = /* @__PURE__ */ new Map();
1640
+ analyzedMethods = /* @__PURE__ */ new Set();
1641
+ constructor(checker, program) {
1642
+ this.checker = checker;
1643
+ this.program = program;
1644
+ }
1645
+ /**
1646
+ * Analyzes a controller method for query builder patterns, following service calls
1647
+ */
1648
+ analyzeControllerMethod(methodDeclaration, options = {}) {
1649
+ const cacheKey = this.getMethodCacheKey(methodDeclaration);
1650
+ if (this.cache.has(cacheKey)) {
1651
+ return this.cache.get(cacheKey) ?? null;
1652
+ }
1653
+ const maxDepth = options.maxDepth ?? 3;
1654
+ const schema = this.analyzeMethodWithServiceCalls(methodDeclaration, 0, maxDepth, options);
1655
+ this.cache.set(cacheKey, schema);
1656
+ return schema;
1657
+ }
1658
+ /**
1659
+ * Recursively analyzes method with service call traversal
1660
+ */
1661
+ analyzeMethodWithServiceCalls(methodDeclaration, currentDepth, maxDepth, options) {
1662
+ if (currentDepth >= maxDepth) {
1663
+ return null;
1664
+ }
1665
+ const methodKey = this.getMethodCacheKey(methodDeclaration);
1666
+ if (this.analyzedMethods.has(methodKey)) {
1667
+ return null;
1668
+ }
1669
+ this.analyzedMethods.add(methodKey);
1670
+ const directSchema = analyzeQueryBuilderForSchema(methodDeclaration, this.checker);
1671
+ if (directSchema) {
1672
+ return directSchema;
1673
+ }
1674
+ const serviceCalls = this.findServiceCalls(methodDeclaration);
1675
+ for (const serviceCall of serviceCalls) {
1676
+ const serviceSchema = this.analyzeServiceMethod(serviceCall, currentDepth, maxDepth, options);
1677
+ if (serviceSchema) {
1678
+ return serviceSchema;
1679
+ }
1680
+ }
1681
+ return null;
1682
+ }
1683
+ /**
1684
+ * Analyzes a service method for query builder patterns
1685
+ */
1686
+ analyzeServiceMethod(serviceCall, currentDepth, maxDepth, options) {
1687
+ const directSchema = analyzeQueryBuilderForSchema(serviceCall.methodDeclaration, this.checker);
1688
+ if (directSchema) {
1689
+ return directSchema;
1690
+ }
1691
+ if (options.analyzeHelpers) {
1692
+ return this.analyzeMethodWithServiceCalls(
1693
+ serviceCall.methodDeclaration,
1694
+ currentDepth + 1,
1695
+ maxDepth,
1696
+ options
1697
+ );
1698
+ }
1699
+ return null;
1700
+ }
1701
+ /**
1702
+ * Finds service calls in a method body
1703
+ */
1704
+ findServiceCalls(methodDeclaration) {
1705
+ const serviceCalls = [];
1706
+ const body = methodDeclaration.body;
1707
+ if (!body) {
1708
+ return serviceCalls;
1709
+ }
1710
+ const visitor = (node) => {
1711
+ if (import_typescript9.default.isCallExpression(node)) {
1712
+ const serviceCall = this.resolveServiceCall(node);
1713
+ if (serviceCall) {
1714
+ serviceCalls.push(serviceCall);
1715
+ }
1716
+ }
1717
+ import_typescript9.default.forEachChild(node, visitor);
1718
+ };
1719
+ import_typescript9.default.forEachChild(body, visitor);
1720
+ return serviceCalls;
1721
+ }
1722
+ /**
1723
+ * Resolves a call expression to a service method
1724
+ */
1725
+ resolveServiceCall(callExpression) {
1726
+ if (import_typescript9.default.isPropertyAccessExpression(callExpression.expression)) {
1727
+ const propAccess = callExpression.expression;
1728
+ const methodName = propAccess.name.text;
1729
+ const objectType = this.checker.getTypeAtLocation(propAccess.expression);
1730
+ const objectSymbol = objectType.getSymbol();
1731
+ if (objectSymbol) {
1732
+ const classDeclaration = this.findClassDeclaration(objectSymbol);
1733
+ if (classDeclaration) {
1734
+ const methodDeclaration = this.findMethodDeclaration(classDeclaration, methodName);
1735
+ if (methodDeclaration) {
1736
+ return {
1737
+ serviceName: classDeclaration.name?.text || "Unknown",
1738
+ methodName,
1739
+ filePath: classDeclaration.getSourceFile().fileName,
1740
+ classDeclaration,
1741
+ methodDeclaration
1742
+ };
1743
+ }
1744
+ }
1745
+ }
1746
+ }
1747
+ if (import_typescript9.default.isPropertyAccessExpression(callExpression.expression)) {
1748
+ const propAccess = callExpression.expression;
1749
+ const methodName = propAccess.name.text;
1750
+ if (import_typescript9.default.isIdentifier(propAccess.expression)) {
1751
+ const className = propAccess.expression.text;
1752
+ const classSymbol = this.checker.getSymbolAtLocation(propAccess.expression);
1753
+ if (classSymbol) {
1754
+ const classDeclaration = this.findClassDeclaration(classSymbol);
1755
+ if (classDeclaration && classDeclaration.name?.text === className) {
1756
+ const methodDeclaration = this.findMethodDeclaration(classDeclaration, methodName);
1757
+ if (methodDeclaration) {
1758
+ return {
1759
+ serviceName: className,
1760
+ methodName,
1761
+ filePath: classDeclaration.getSourceFile().fileName,
1762
+ classDeclaration,
1763
+ methodDeclaration
1764
+ };
1765
+ }
1766
+ }
1767
+ }
1768
+ }
1769
+ }
1770
+ return null;
1771
+ }
1772
+ /**
1773
+ * Finds class declaration from a symbol
1774
+ */
1775
+ findClassDeclaration(symbol) {
1776
+ const declarations = symbol.getDeclarations();
1777
+ if (!declarations) return null;
1778
+ for (const declaration of declarations) {
1779
+ if (import_typescript9.default.isClassDeclaration(declaration)) {
1780
+ return declaration;
1781
+ }
1782
+ }
1783
+ return null;
1784
+ }
1785
+ /**
1786
+ * Finds method declaration in a class
1787
+ */
1788
+ findMethodDeclaration(classDeclaration, methodName) {
1789
+ for (const member of classDeclaration.members) {
1790
+ if (import_typescript9.default.isMethodDeclaration(member) && member.name) {
1791
+ if (import_typescript9.default.isIdentifier(member.name) && member.name.text === methodName) {
1792
+ return member;
1793
+ }
1794
+ }
1795
+ }
1796
+ return null;
1797
+ }
1798
+ /**
1799
+ * Generates cache key for a method
1800
+ */
1801
+ getMethodCacheKey(methodDeclaration) {
1802
+ const sourceFile = methodDeclaration.getSourceFile();
1803
+ const className = this.getClassName(methodDeclaration);
1804
+ const methodName = methodDeclaration.name?.getText() || "unknown";
1805
+ const line = sourceFile.getLineAndCharacterOfPosition(methodDeclaration.getStart()).line;
1806
+ return `${sourceFile.fileName}:${className}:${methodName}:${line}`;
1807
+ }
1808
+ /**
1809
+ * Gets class name from method declaration
1810
+ */
1811
+ getClassName(methodDeclaration) {
1812
+ let node = methodDeclaration;
1813
+ while (node) {
1814
+ if (import_typescript9.default.isClassDeclaration(node)) {
1815
+ return node.name?.text || "Unknown";
1816
+ }
1817
+ node = node.parent;
1818
+ }
1819
+ return "Unknown";
1820
+ }
1821
+ /**
1822
+ * Clears the analysis cache
1823
+ */
1824
+ clearCache() {
1825
+ this.cache.clear();
1826
+ this.analyzedMethods.clear();
1827
+ }
1828
+ /**
1829
+ * Gets cache statistics
1830
+ */
1831
+ getCacheStats() {
1832
+ return {
1833
+ cached: this.cache.size,
1834
+ analyzed: this.analyzedMethods.size
1835
+ };
1836
+ }
1837
+ };
1838
+ function analyzeControllerWithServiceCalls(methodDeclaration, checker, program, options = {}) {
1839
+ if (!program) {
1840
+ return null;
1841
+ }
1842
+ const analyzer = new ServiceCallAnalyzer(checker, program);
1843
+ return analyzer.analyzeControllerMethod(methodDeclaration, options);
1844
+ }
1845
+
1846
+ // src/compiler/schema/queryBuilderAnalyzer.ts
1633
1847
  function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {}) {
1634
1848
  const body = methodDeclaration.body;
1635
1849
  if (!body) {
@@ -1649,6 +1863,24 @@ function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {})
1649
1863
  }
1650
1864
  return parseQueryBuilderChain(callChain, checker, options);
1651
1865
  }
1866
+ function analyzeQueryBuilderWithServiceCalls(methodDeclaration, checker, program, options = {}, operationInfo) {
1867
+ let schema = analyzeQueryBuilderForSchema(methodDeclaration, checker, options);
1868
+ if (!schema && program) {
1869
+ try {
1870
+ schema = analyzeControllerWithServiceCalls(methodDeclaration, checker, program, {
1871
+ maxDepth: options.maxDepth,
1872
+ analyzeHelpers: options.analyzeHelpers
1873
+ });
1874
+ } catch (error) {
1875
+ console.warn("Service call analysis failed:", error);
1876
+ }
1877
+ }
1878
+ return {
1879
+ detected: schema !== null,
1880
+ schema,
1881
+ ...operationInfo
1882
+ };
1883
+ }
1652
1884
  function analyzeWithVariableTracking(body, checker, options) {
1653
1885
  let queryBuilderVar = null;
1654
1886
  let entityName = null;
@@ -1657,12 +1889,12 @@ function analyzeWithVariableTracking(body, checker, options) {
1657
1889
  let isPaged = false;
1658
1890
  let hasReturn = false;
1659
1891
  for (const statement of body.statements) {
1660
- if (import_typescript9.default.isReturnStatement(statement)) {
1892
+ if (import_typescript10.default.isReturnStatement(statement)) {
1661
1893
  hasReturn = true;
1662
1894
  const returnExpr = statement.expression;
1663
- if (returnExpr && import_typescript9.default.isCallExpression(returnExpr)) {
1895
+ if (returnExpr && import_typescript10.default.isCallExpression(returnExpr)) {
1664
1896
  const callExpr = returnExpr;
1665
- if (import_typescript9.default.isIdentifier(callExpr.expression) && queryBuilderVar) {
1897
+ if (import_typescript10.default.isIdentifier(callExpr.expression) && queryBuilderVar) {
1666
1898
  const varName = callExpr.expression.text;
1667
1899
  if (varName === queryBuilderVar) {
1668
1900
  const methodName = callExpr.expression.text;
@@ -1671,9 +1903,9 @@ function analyzeWithVariableTracking(body, checker, options) {
1671
1903
  }
1672
1904
  }
1673
1905
  }
1674
- if (import_typescript9.default.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
1906
+ if (import_typescript10.default.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
1675
1907
  const propAccess = callExpr.expression;
1676
- if (import_typescript9.default.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
1908
+ if (import_typescript10.default.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
1677
1909
  const methodName = propAccess.name.text;
1678
1910
  if (methodName === "executePaged") {
1679
1911
  isPaged = true;
@@ -1683,13 +1915,13 @@ function analyzeWithVariableTracking(body, checker, options) {
1683
1915
  }
1684
1916
  continue;
1685
1917
  }
1686
- if (!import_typescript9.default.isExpressionStatement(statement)) {
1687
- if (import_typescript9.default.isVariableStatement(statement)) {
1918
+ if (!import_typescript10.default.isExpressionStatement(statement)) {
1919
+ if (import_typescript10.default.isVariableStatement(statement)) {
1688
1920
  for (const declaration of statement.declarationList.declarations) {
1689
- if (!import_typescript9.default.isIdentifier(declaration.name)) continue;
1921
+ if (!import_typescript10.default.isIdentifier(declaration.name)) continue;
1690
1922
  const varName = declaration.name.text;
1691
1923
  const initializer = declaration.initializer;
1692
- if (!initializer || !import_typescript9.default.isCallExpression(initializer)) continue;
1924
+ if (!initializer || !import_typescript10.default.isCallExpression(initializer)) continue;
1693
1925
  const opInfo = extractChainedOperation(initializer);
1694
1926
  if (opInfo && (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom")) {
1695
1927
  queryBuilderVar = varName;
@@ -1702,13 +1934,13 @@ function analyzeWithVariableTracking(body, checker, options) {
1702
1934
  continue;
1703
1935
  }
1704
1936
  const expr = statement.expression;
1705
- if (import_typescript9.default.isBinaryExpression(expr) && expr.operatorToken.kind === import_typescript9.default.SyntaxKind.EqualsToken) {
1706
- if (!import_typescript9.default.isIdentifier(expr.left)) {
1937
+ if (import_typescript10.default.isBinaryExpression(expr) && expr.operatorToken.kind === import_typescript10.default.SyntaxKind.EqualsToken) {
1938
+ if (!import_typescript10.default.isIdentifier(expr.left)) {
1707
1939
  continue;
1708
1940
  }
1709
1941
  const varName = expr.left.text;
1710
1942
  const rightSide = expr.right;
1711
- if (import_typescript9.default.isCallExpression(rightSide)) {
1943
+ if (import_typescript10.default.isCallExpression(rightSide)) {
1712
1944
  const opInfo = extractChainedOperation(rightSide);
1713
1945
  if (opInfo) {
1714
1946
  if (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom") {
@@ -1746,14 +1978,14 @@ function analyzeWithVariableTracking(body, checker, options) {
1746
1978
  };
1747
1979
  }
1748
1980
  function extractChainedOperation(callExpr) {
1749
- if (import_typescript9.default.isIdentifier(callExpr.expression)) {
1981
+ if (import_typescript10.default.isIdentifier(callExpr.expression)) {
1750
1982
  const methodName2 = callExpr.expression.text;
1751
1983
  if (methodName2 === "selectFromEntity" || methodName2 === "selectFrom") {
1752
1984
  const entityArg = callExpr.arguments[0];
1753
1985
  let entityName = null;
1754
- if (import_typescript9.default.isIdentifier(entityArg)) {
1986
+ if (import_typescript10.default.isIdentifier(entityArg)) {
1755
1987
  entityName = entityArg.text;
1756
- } else if (import_typescript9.default.isPropertyAccessExpression(entityArg)) {
1988
+ } else if (import_typescript10.default.isPropertyAccessExpression(entityArg)) {
1757
1989
  entityName = entityArg.name.text;
1758
1990
  }
1759
1991
  return {
@@ -1764,7 +1996,7 @@ function extractChainedOperation(callExpr) {
1764
1996
  };
1765
1997
  }
1766
1998
  }
1767
- if (!import_typescript9.default.isPropertyAccessExpression(callExpr.expression)) {
1999
+ if (!import_typescript10.default.isPropertyAccessExpression(callExpr.expression)) {
1768
2000
  return null;
1769
2001
  }
1770
2002
  const propAccess = callExpr.expression;
@@ -1772,7 +2004,7 @@ function extractChainedOperation(callExpr) {
1772
2004
  if (methodName === "select") {
1773
2005
  const fields = [];
1774
2006
  for (const arg of callExpr.arguments) {
1775
- if (import_typescript9.default.isStringLiteral(arg)) {
2007
+ if (import_typescript10.default.isStringLiteral(arg)) {
1776
2008
  fields.push(arg.text);
1777
2009
  }
1778
2010
  }
@@ -1794,19 +2026,19 @@ function extractChainedOperation(callExpr) {
1794
2026
  return null;
1795
2027
  }
1796
2028
  function parseIncludeObjectLiteral(arg) {
1797
- if (!import_typescript9.default.isObjectLiteralExpression(arg)) {
2029
+ if (!import_typescript10.default.isObjectLiteralExpression(arg)) {
1798
2030
  return null;
1799
2031
  }
1800
2032
  const includes = {};
1801
2033
  for (const prop of arg.properties) {
1802
- if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
2034
+ if (!import_typescript10.default.isPropertyAssignment(prop) || !import_typescript10.default.isIdentifier(prop.name)) {
1803
2035
  continue;
1804
2036
  }
1805
2037
  const relationName = prop.name.text;
1806
2038
  const value = prop.initializer;
1807
- if (value.kind === import_typescript9.default.SyntaxKind.TrueKeyword) {
2039
+ if (value.kind === import_typescript10.default.SyntaxKind.TrueKeyword) {
1808
2040
  includes[relationName] = true;
1809
- } else if (import_typescript9.default.isObjectLiteralExpression(value)) {
2041
+ } else if (import_typescript10.default.isObjectLiteralExpression(value)) {
1810
2042
  const nestedSchema = parseNestedInclude(value, 0);
1811
2043
  if (nestedSchema) {
1812
2044
  includes[relationName] = nestedSchema;
@@ -1819,18 +2051,18 @@ function parseNestedInclude(obj, depth) {
1819
2051
  const selectedFields = [];
1820
2052
  const includes = {};
1821
2053
  for (const prop of obj.properties) {
1822
- if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
2054
+ if (!import_typescript10.default.isPropertyAssignment(prop) || !import_typescript10.default.isIdentifier(prop.name)) {
1823
2055
  continue;
1824
2056
  }
1825
2057
  const propName = prop.name.text;
1826
2058
  const value = prop.initializer;
1827
- if (propName === "select" && import_typescript9.default.isArrayLiteralExpression(value)) {
2059
+ if (propName === "select" && import_typescript10.default.isArrayLiteralExpression(value)) {
1828
2060
  for (const element of value.elements) {
1829
- if (import_typescript9.default.isStringLiteral(element)) {
2061
+ if (import_typescript10.default.isStringLiteral(element)) {
1830
2062
  selectedFields.push(element.text);
1831
2063
  }
1832
2064
  }
1833
- } else if (propName === "include" && import_typescript9.default.isObjectLiteralExpression(value)) {
2065
+ } else if (propName === "include" && import_typescript10.default.isObjectLiteralExpression(value)) {
1834
2066
  const nestedIncludes = parseIncludeObjectLiteral(value);
1835
2067
  if (nestedIncludes) {
1836
2068
  for (const [relName, relSchema] of Object.entries(nestedIncludes)) {
@@ -1847,10 +2079,10 @@ function parseNestedInclude(obj, depth) {
1847
2079
  };
1848
2080
  }
1849
2081
  function getMethodName(expression) {
1850
- if (import_typescript9.default.isIdentifier(expression)) {
2082
+ if (import_typescript10.default.isIdentifier(expression)) {
1851
2083
  return expression.text;
1852
2084
  }
1853
- if (import_typescript9.default.isPropertyAccessExpression(expression)) {
2085
+ if (import_typescript10.default.isPropertyAccessExpression(expression)) {
1854
2086
  return expression.name.text;
1855
2087
  }
1856
2088
  return null;
@@ -1858,7 +2090,7 @@ function getMethodName(expression) {
1858
2090
  function findReturnStatement(body) {
1859
2091
  let returnStatement = null;
1860
2092
  for (const statement of body.statements) {
1861
- if (import_typescript9.default.isReturnStatement(statement)) {
2093
+ if (import_typescript10.default.isReturnStatement(statement)) {
1862
2094
  if (returnStatement !== null) {
1863
2095
  return null;
1864
2096
  }
@@ -1871,20 +2103,20 @@ function analyzeReturnExpression(expression) {
1871
2103
  if (!expression) {
1872
2104
  return null;
1873
2105
  }
1874
- if (import_typescript9.default.isCallExpression(expression)) {
2106
+ if (import_typescript10.default.isCallExpression(expression)) {
1875
2107
  return buildCallChain(expression, null);
1876
2108
  }
1877
2109
  return null;
1878
2110
  }
1879
2111
  function buildCallChain(node, parent) {
1880
- if (import_typescript9.default.isCallExpression(node)) {
2112
+ if (import_typescript10.default.isCallExpression(node)) {
1881
2113
  const callNode = {
1882
2114
  expression: node.expression,
1883
2115
  methodName: getMethodName(node.expression),
1884
2116
  arguments: node.arguments,
1885
2117
  parent
1886
2118
  };
1887
- if (import_typescript9.default.isPropertyAccessExpression(node.expression)) {
2119
+ if (import_typescript10.default.isPropertyAccessExpression(node.expression)) {
1888
2120
  return buildCallChain(node.expression.expression, callNode);
1889
2121
  }
1890
2122
  return callNode;
@@ -1911,7 +2143,7 @@ function parseQueryBuilderChain(chain, checker, options) {
1911
2143
  const methodName = currentNode.methodName;
1912
2144
  if (methodName === "select") {
1913
2145
  for (const arg of currentNode.arguments) {
1914
- if (import_typescript9.default.isStringLiteral(arg)) {
2146
+ if (import_typescript10.default.isStringLiteral(arg)) {
1915
2147
  selectedFields.add(arg.text);
1916
2148
  }
1917
2149
  }
@@ -1946,10 +2178,10 @@ function extractEntityName(callNode, checker) {
1946
2178
  return null;
1947
2179
  }
1948
2180
  const entityArg = callNode.arguments[0];
1949
- if (import_typescript9.default.isIdentifier(entityArg)) {
2181
+ if (import_typescript10.default.isIdentifier(entityArg)) {
1950
2182
  return entityArg.text;
1951
2183
  }
1952
- if (import_typescript9.default.isPropertyAccessExpression(entityArg)) {
2184
+ if (import_typescript10.default.isPropertyAccessExpression(entityArg)) {
1953
2185
  return entityArg.name.text;
1954
2186
  }
1955
2187
  return null;
@@ -1958,16 +2190,16 @@ function parseIncludeArgument(arg, includes, checker, options, depth) {
1958
2190
  if (!arg) {
1959
2191
  return;
1960
2192
  }
1961
- if (import_typescript9.default.isObjectLiteralExpression(arg)) {
2193
+ if (import_typescript10.default.isObjectLiteralExpression(arg)) {
1962
2194
  for (const prop of arg.properties) {
1963
- if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
2195
+ if (!import_typescript10.default.isPropertyAssignment(prop) || !import_typescript10.default.isIdentifier(prop.name)) {
1964
2196
  continue;
1965
2197
  }
1966
2198
  const relationName = prop.name.text;
1967
2199
  const value = prop.initializer;
1968
- if (value.kind === import_typescript9.default.SyntaxKind.TrueKeyword) {
2200
+ if (value.kind === import_typescript10.default.SyntaxKind.TrueKeyword) {
1969
2201
  includes[relationName] = true;
1970
- } else if (import_typescript9.default.isObjectLiteralExpression(value)) {
2202
+ } else if (import_typescript10.default.isObjectLiteralExpression(value)) {
1971
2203
  const maxDepth = options.maxDepth ?? 5;
1972
2204
  if (depth < maxDepth) {
1973
2205
  const nestedSchema = parseNestedInclude(value, depth + 1);
@@ -1981,7 +2213,7 @@ function parseIncludeArgument(arg, includes, checker, options, depth) {
1981
2213
  }
1982
2214
 
1983
2215
  // src/compiler/schema/queryBuilderSchemaBuilder.ts
1984
- var import_typescript10 = require("typescript");
2216
+ var import_typescript11 = require("typescript");
1985
2217
  function wrapInPaginatedResult(schema) {
1986
2218
  return {
1987
2219
  type: "object",
@@ -2010,7 +2242,12 @@ function generateOpenAPI(controllers, checker, options = {}) {
2010
2242
  mode: "response"
2011
2243
  };
2012
2244
  const paths = {};
2013
- const { onProgress } = options;
2245
+ const { onProgress, onQueryBuilderProgress } = options;
2246
+ let totalOperations = 0;
2247
+ for (const controller of controllers) {
2248
+ totalOperations += controller.operations.length;
2249
+ }
2250
+ let currentOperation = 0;
2014
2251
  for (let i = 0; i < controllers.length; i++) {
2015
2252
  const controller = controllers[i];
2016
2253
  if (onProgress) {
@@ -2022,6 +2259,34 @@ function generateOpenAPI(controllers, checker, options = {}) {
2022
2259
  paths[fullPath] = {};
2023
2260
  }
2024
2261
  const method = operation.httpMethod.toLowerCase();
2262
+ const analysisResult = analyzeQueryBuilderWithServiceCalls(
2263
+ operation.methodDeclaration,
2264
+ checker,
2265
+ null,
2266
+ // TODO: Pass program when available
2267
+ {},
2268
+ {
2269
+ methodName: operation.operationId,
2270
+ httpMethod: operation.httpMethod,
2271
+ path: operation.path,
2272
+ operationId: operation.operationId
2273
+ }
2274
+ );
2275
+ if (onQueryBuilderProgress) {
2276
+ currentOperation++;
2277
+ onQueryBuilderProgress({
2278
+ controller: controller.className,
2279
+ operation: operation.operationId,
2280
+ method: operation.httpMethod,
2281
+ path: operation.path,
2282
+ queryBuilderDetected: analysisResult.detected,
2283
+ entityName: analysisResult.schema?.entityName,
2284
+ selectedFields: analysisResult.schema?.selectedFields,
2285
+ isPaged: analysisResult.schema?.isPaged,
2286
+ current: currentOperation,
2287
+ total: totalOperations
2288
+ });
2289
+ }
2025
2290
  paths[fullPath][method] = buildOperation(operation, ctx, controller.consumes);
2026
2291
  }
2027
2292
  }
@@ -2301,12 +2566,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
2301
2566
  const declarations = typeSymbol.getDeclarations();
2302
2567
  if (!declarations || declarations.length === 0) return schema;
2303
2568
  const classDecl = declarations[0];
2304
- if (!import_typescript11.default.isClassDeclaration(classDecl)) return schema;
2569
+ if (!import_typescript12.default.isClassDeclaration(classDecl)) return schema;
2305
2570
  const result = { ...schema };
2306
2571
  const props = { ...result.properties };
2307
2572
  for (const member of classDecl.members) {
2308
- if (!import_typescript11.default.isPropertyDeclaration(member) || !member.name) continue;
2309
- const propName = import_typescript11.default.isIdentifier(member.name) ? member.name.text : null;
2573
+ if (!import_typescript12.default.isPropertyDeclaration(member) || !member.name) continue;
2574
+ const propName = import_typescript12.default.isIdentifier(member.name) ? member.name.text : null;
2310
2575
  if (!propName) continue;
2311
2576
  if (!props[propName]) continue;
2312
2577
  const frags = extractPropertySchemaFragments(ctx.checker, member);
@@ -2319,7 +2584,7 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
2319
2584
  }
2320
2585
 
2321
2586
  // src/compiler/manifest/emit.ts
2322
- var import_typescript12 = __toESM(require("typescript"), 1);
2587
+ var import_typescript13 = __toESM(require("typescript"), 1);
2323
2588
  function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
2324
2589
  const components = /* @__PURE__ */ new Map();
2325
2590
  const ctx = {
@@ -2341,7 +2606,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
2341
2606
  generator: {
2342
2607
  name: "adorn-api",
2343
2608
  version,
2344
- typescript: import_typescript12.default.version
2609
+ typescript: import_typescript13.default.version
2345
2610
  },
2346
2611
  schemas: {
2347
2612
  kind: "openapi-3.1",
@@ -2827,7 +3092,7 @@ async function isStale(params) {
2827
3092
  // src/compiler/cache/writeCache.ts
2828
3093
  var import_node_fs4 = __toESM(require("fs"), 1);
2829
3094
  var import_node_path4 = __toESM(require("path"), 1);
2830
- var import_typescript13 = __toESM(require("typescript"), 1);
3095
+ var import_typescript14 = __toESM(require("typescript"), 1);
2831
3096
  function statMtimeMs2(p) {
2832
3097
  return import_node_fs4.default.statSync(p).mtimeMs;
2833
3098
  }
@@ -2860,7 +3125,7 @@ function writeCache(params) {
2860
3125
  generator: {
2861
3126
  name: "adorn-api",
2862
3127
  version: params.adornVersion,
2863
- typescript: import_typescript13.default.version
3128
+ typescript: import_typescript14.default.version
2864
3129
  },
2865
3130
  project: {
2866
3131
  tsconfigPath: params.tsconfigAbs,
@@ -3022,6 +3287,8 @@ var Spinner = class {
3022
3287
  current = 0;
3023
3288
  total = 0;
3024
3289
  customStatus;
3290
+ frameIndex = 0;
3291
+ lastLineLength = 0;
3025
3292
  constructor(message = "") {
3026
3293
  this.message = message;
3027
3294
  }
@@ -3029,9 +3296,8 @@ var Spinner = class {
3029
3296
  * Start the spinner.
3030
3297
  */
3031
3298
  start() {
3032
- let frameIndex = 0;
3033
3299
  this.interval = setInterval(() => {
3034
- const frame = this.frames[frameIndex];
3300
+ const frame = this.frames[this.frameIndex];
3035
3301
  let output;
3036
3302
  if (this.customStatus) {
3037
3303
  output = `\r${frame} ${this.customStatus}`;
@@ -3040,11 +3306,12 @@ var Spinner = class {
3040
3306
  } else {
3041
3307
  output = `\r${frame} ${this.message}`;
3042
3308
  }
3309
+ this.lastLineLength = output.length - 1;
3043
3310
  import_node_process.default.stdout.write(output);
3044
3311
  if (import_node_process.default.stdout.writable) {
3045
3312
  import_node_process.default.stdout.write("");
3046
3313
  }
3047
- frameIndex = (frameIndex + 1) % this.frames.length;
3314
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
3048
3315
  }, 80);
3049
3316
  }
3050
3317
  /**
@@ -3059,8 +3326,12 @@ var Spinner = class {
3059
3326
  */
3060
3327
  setStatus(status) {
3061
3328
  this.customStatus = status;
3062
- const frame = this.frames[this.current];
3063
- import_node_process.default.stdout.write(`\r${frame} ${status}`);
3329
+ const frame = this.frames[this.frameIndex];
3330
+ const output = `\r${frame} ${status}`;
3331
+ const clearLength = Math.max(this.lastLineLength, output.length - 1);
3332
+ import_node_process.default.stdout.write("\r" + " ".repeat(clearLength) + "\r");
3333
+ this.lastLineLength = output.length - 1;
3334
+ import_node_process.default.stdout.write(output);
3064
3335
  if (import_node_process.default.stdout.writable) {
3065
3336
  import_node_process.default.stdout.write("");
3066
3337
  }
@@ -3079,7 +3350,7 @@ var Spinner = class {
3079
3350
  clearInterval(this.interval);
3080
3351
  this.interval = void 0;
3081
3352
  }
3082
- import_node_process.default.stdout.write("\r" + " ".repeat(60) + "\r");
3353
+ import_node_process.default.stdout.write("\r" + " ".repeat(this.lastLineLength) + "\r");
3083
3354
  if (completedMessage) {
3084
3355
  import_node_process.default.stdout.write(completedMessage + "\n");
3085
3356
  }
@@ -3613,7 +3884,7 @@ function getEdgesByRelation(graph, relation) {
3613
3884
  }
3614
3885
 
3615
3886
  // src/compiler/graph/builder.ts
3616
- var import_typescript14 = __toESM(require("typescript"), 1);
3887
+ var import_typescript15 = __toESM(require("typescript"), 1);
3617
3888
 
3618
3889
  // src/compiler/graph/schemaGraph.ts
3619
3890
  var SchemaGraph = class {
@@ -3865,7 +4136,7 @@ var SchemaGraph = class {
3865
4136
  };
3866
4137
 
3867
4138
  // src/cli.ts
3868
- var import_typescript15 = __toESM(require("typescript"), 1);
4139
+ var import_typescript16 = __toESM(require("typescript"), 1);
3869
4140
  var import_node_process2 = __toESM(require("process"), 1);
3870
4141
  var import_meta2 = {};
3871
4142
  var ADORN_VERSION = (() => {
@@ -3944,7 +4215,7 @@ function sanitizeForJson(obj) {
3944
4215
  return result;
3945
4216
  }
3946
4217
  function buildControllerGraph(controllers) {
3947
- const graph = createGraph(import_typescript15.default.version);
4218
+ const graph = createGraph(import_typescript16.default.version);
3948
4219
  const nodeMap = /* @__PURE__ */ new Map();
3949
4220
  for (const ctrl of controllers) {
3950
4221
  const nodeId = `Controller:${ctrl.className}`;
@@ -4036,6 +4307,7 @@ async function buildCommand(args) {
4036
4307
  const verbose = args.includes("--verbose");
4037
4308
  const quiet = args.includes("--quiet");
4038
4309
  const split = args.includes("--split");
4310
+ const showQueryBuilder = args.includes("--show-query-builder");
4039
4311
  const splitStrategyIndex = args.indexOf("--split-strategy");
4040
4312
  const splitStrategy = splitStrategyIndex !== -1 ? args[splitStrategyIndex + 1] : void 0;
4041
4313
  const splitThresholdIndex = args.indexOf("--split-threshold");
@@ -4055,7 +4327,7 @@ async function buildCommand(args) {
4055
4327
  outDir: outputDir,
4056
4328
  project: projectPath,
4057
4329
  adornVersion: ADORN_VERSION,
4058
- typescriptVersion: import_typescript15.default.version
4330
+ typescriptVersion: import_typescript16.default.version
4059
4331
  });
4060
4332
  if (!stale.stale) {
4061
4333
  progress.completePhase("staleness-check");
@@ -4096,6 +4368,12 @@ async function buildCommand(args) {
4096
4368
  }
4097
4369
  }
4098
4370
  progress.startPhase("openapi", "Generating OpenAPI schema");
4371
+ const queryBuilderStats = {
4372
+ totalOperations,
4373
+ detected: 0,
4374
+ fallback: 0,
4375
+ operations: []
4376
+ };
4099
4377
  const openapiSpinner = new Spinner("Processing schemas");
4100
4378
  if (!quiet) openapiSpinner.start();
4101
4379
  const openapi = generateOpenAPI(controllers, checker, {
@@ -4105,6 +4383,31 @@ async function buildCommand(args) {
4105
4383
  if (!quiet) {
4106
4384
  openapiSpinner.setStatus(`${message} (${current}/${total})`);
4107
4385
  }
4386
+ },
4387
+ onQueryBuilderProgress: (info) => {
4388
+ if (info.queryBuilderDetected) {
4389
+ queryBuilderStats.detected++;
4390
+ } else {
4391
+ queryBuilderStats.fallback++;
4392
+ }
4393
+ queryBuilderStats.operations.push({
4394
+ operationId: info.operation,
4395
+ method: info.method,
4396
+ path: info.path,
4397
+ detected: info.queryBuilderDetected,
4398
+ entityName: info.entityName,
4399
+ selectedFields: info.selectedFields,
4400
+ isPaged: info.isPaged
4401
+ });
4402
+ if (showQueryBuilder || verbose) {
4403
+ if (info.queryBuilderDetected) {
4404
+ const fieldsStr = info.selectedFields && info.selectedFields.length > 0 ? ` [select: ${info.selectedFields.join(",")}]` : "";
4405
+ const pagedStr = info.isPaged ? " (paged)" : "";
4406
+ progress.verboseLog(` \u2713 Query builder: ${info.method} ${info.path} \u2192 ${info.entityName}${fieldsStr}${pagedStr}`);
4407
+ } else {
4408
+ progress.verboseLog(` \u25CB No query builder: ${info.method} ${info.path} \u2192 using full entity schema`);
4409
+ }
4410
+ }
4108
4411
  }
4109
4412
  });
4110
4413
  if (!quiet) {
@@ -4163,6 +4466,17 @@ async function buildCommand(args) {
4163
4466
  }
4164
4467
  }
4165
4468
  progress.completePhase("openapi", `Generated ${schemaCount} schema(s)${splitEnabled ? " (split into groups)" : ""}`);
4469
+ if (showQueryBuilder && totalOperations > 0) {
4470
+ log("");
4471
+ log("Query Builder Analysis:");
4472
+ log(` Operations analyzed: ${totalOperations}`);
4473
+ log(` Patterns detected: ${queryBuilderStats.detected} (${Math.round(queryBuilderStats.detected / totalOperations * 100)}%)`);
4474
+ log(` Full schemas used: ${queryBuilderStats.fallback} (${Math.round(queryBuilderStats.fallback / totalOperations * 100)}%)`);
4475
+ if (queryBuilderStats.detected > 0) {
4476
+ const totalFields = queryBuilderStats.operations.filter((op) => op.detected && op.selectedFields).reduce((sum, op) => sum + (op.selectedFields?.length || 0), 0);
4477
+ log(` Fields selected: ${totalFields} total (avg ${Math.round(totalFields / queryBuilderStats.detected)} per query)`);
4478
+ }
4479
+ }
4166
4480
  progress.startPhase("manifest", "Generating manifest");
4167
4481
  const manifest = generateManifest(controllers, checker, ADORN_VERSION, validationMode);
4168
4482
  progress.completePhase("manifest");
@@ -4244,7 +4558,12 @@ async function buildCommand(args) {
4244
4558
  schemas: schemaCount,
4245
4559
  sourceFiles: projectSourceFiles.length,
4246
4560
  artifactsWritten: artifacts.map((a) => a.name),
4247
- splitEnabled
4561
+ splitEnabled,
4562
+ queryBuilder: {
4563
+ detected: queryBuilderStats.detected,
4564
+ fallback: queryBuilderStats.fallback,
4565
+ total: totalOperations
4566
+ }
4248
4567
  };
4249
4568
  progress.printSummary(stats);
4250
4569
  progress.printArtifacts(artifacts);
@@ -4272,30 +4591,32 @@ if (command === "build") {
4272
4591
  console.log(`
4273
4592
  adorn-api CLI v${ADORN_VERSION}
4274
4593
 
4275
- Commands:
4276
- build Generate OpenAPI and manifest from TypeScript source
4277
- clean Remove generated artifacts
4594
+ Commands:
4595
+ build Generate OpenAPI and manifest from TypeScript source
4596
+ clean Remove generated artifacts
4278
4597
 
4279
- Options:
4280
- -p <path> Path to tsconfig.json (default: ./tsconfig.json)
4281
- --output <dir> Output directory (default: .adorn)
4282
- --if-stale Only rebuild if artifacts are stale
4283
- --validation-mode <mode> Validation mode: none, ajv-runtime, precompiled (default: ajv-runtime)
4284
- --split Enable automatic schema splitting (default: disabled)
4285
- --split-strategy <mode> Override splitting strategy: controller, dependency, size, auto (default: auto)
4286
- --split-threshold <num> Schema count threshold for auto-split (default: 50)
4287
- --verbose Show detailed progress information
4288
- --quiet Suppress non-essential output
4598
+ Options:
4599
+ -p <path> Path to tsconfig.json (default: ./tsconfig.json)
4600
+ --output <dir> Output directory (default: .adorn)
4601
+ --if-stale Only rebuild if artifacts are stale
4602
+ --validation-mode <mode> Validation mode: none, ajv-runtime, precompiled (default: ajv-runtime)
4603
+ --split Enable automatic schema splitting (default: disabled)
4604
+ --split-strategy <mode> Override splitting strategy: controller, dependency, size, auto (default: auto)
4605
+ --split-threshold <num> Schema count threshold for auto-split (default: 50)
4606
+ --verbose Show detailed progress information
4607
+ --quiet Suppress non-essential output
4608
+ --show-query-builder Show query builder inspection details and statistics
4289
4609
 
4290
- Examples:
4291
- adorn-api build -p ./tsconfig.json --output .adorn
4292
- adorn-api build --if-stale
4293
- adorn-api build --validation-mode precompiled
4294
- adorn-api build --verbose
4295
- adorn-api build --split # Enable split mode
4296
- adorn-api build --split-strategy controller # Force controller-based splitting
4297
- adorn-api build --split-threshold 100 # Increase threshold to 100
4298
- adorn-api clean
4299
- `);
4610
+ Examples:
4611
+ adorn-api build -p ./tsconfig.json --output .adorn
4612
+ adorn-api build --if-stale
4613
+ adorn-api build --validation-mode precompiled
4614
+ adorn-api build --verbose
4615
+ adorn-api build --show-query-builder # Show query builder analysis details
4616
+ adorn-api build --split # Enable split mode
4617
+ adorn-api build --split-strategy controller # Force controller-based splitting
4618
+ adorn-api build --split-threshold 100 # Increase threshold to 100
4619
+ adorn-api clean
4620
+ `);
4300
4621
  }
4301
4622
  //# sourceMappingURL=cli.cjs.map