adorn-api 1.0.20 → 1.0.22
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 +643 -42
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +643 -42
- package/dist/cli.js.map +1 -1
- package/dist/compiler/schema/objectHandler.d.ts +40 -0
- package/dist/compiler/schema/objectHandler.d.ts.map +1 -1
- package/dist/compiler/schema/openapi.d.ts +29 -0
- package/dist/compiler/schema/openapi.d.ts.map +1 -1
- package/dist/compiler/schema/queryBuilderAnalyzer.d.ts +76 -0
- package/dist/compiler/schema/queryBuilderAnalyzer.d.ts.map +1 -0
- package/dist/compiler/schema/queryBuilderSchemaBuilder.d.ts +13 -0
- package/dist/compiler/schema/queryBuilderSchemaBuilder.d.ts.map +1 -0
- package/dist/compiler/schema/types.d.ts +1 -0
- package/dist/compiler/schema/types.d.ts.map +1 -1
- package/dist/metal/applyListQuery.d.ts +1 -1
- package/dist/metal/applyListQuery.d.ts.map +1 -1
- package/dist/metal/index.cjs.map +1 -1
- package/dist/metal/index.js.map +1 -1
- package/package.json +2 -2
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,384 @@ 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 analyzeQueryBuilderWithDetails(methodDeclaration, checker, options = {}, operationInfo) {
|
|
1636
|
+
const schema = analyzeQueryBuilderForSchema(methodDeclaration, checker, options);
|
|
1637
|
+
return {
|
|
1638
|
+
detected: schema !== null,
|
|
1639
|
+
schema,
|
|
1640
|
+
...operationInfo
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
function analyzeWithVariableTracking(body, checker, options) {
|
|
1644
|
+
let queryBuilderVar = null;
|
|
1645
|
+
let entityName = null;
|
|
1646
|
+
const selectedFields = /* @__PURE__ */ new Set();
|
|
1647
|
+
const includes = {};
|
|
1648
|
+
let isPaged = false;
|
|
1649
|
+
let hasReturn = false;
|
|
1650
|
+
for (const statement of body.statements) {
|
|
1651
|
+
if (ts9.isReturnStatement(statement)) {
|
|
1652
|
+
hasReturn = true;
|
|
1653
|
+
const returnExpr = statement.expression;
|
|
1654
|
+
if (returnExpr && ts9.isCallExpression(returnExpr)) {
|
|
1655
|
+
const callExpr = returnExpr;
|
|
1656
|
+
if (ts9.isIdentifier(callExpr.expression) && queryBuilderVar) {
|
|
1657
|
+
const varName = callExpr.expression.text;
|
|
1658
|
+
if (varName === queryBuilderVar) {
|
|
1659
|
+
const methodName = callExpr.expression.text;
|
|
1660
|
+
if (methodName === "executePaged") {
|
|
1661
|
+
isPaged = true;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
if (ts9.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
|
|
1666
|
+
const propAccess = callExpr.expression;
|
|
1667
|
+
if (ts9.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
|
|
1668
|
+
const methodName = propAccess.name.text;
|
|
1669
|
+
if (methodName === "executePaged") {
|
|
1670
|
+
isPaged = true;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
continue;
|
|
1676
|
+
}
|
|
1677
|
+
if (!ts9.isExpressionStatement(statement)) {
|
|
1678
|
+
if (ts9.isVariableStatement(statement)) {
|
|
1679
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1680
|
+
if (!ts9.isIdentifier(declaration.name)) continue;
|
|
1681
|
+
const varName = declaration.name.text;
|
|
1682
|
+
const initializer = declaration.initializer;
|
|
1683
|
+
if (!initializer || !ts9.isCallExpression(initializer)) continue;
|
|
1684
|
+
const opInfo = extractChainedOperation(initializer);
|
|
1685
|
+
if (opInfo && (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom")) {
|
|
1686
|
+
queryBuilderVar = varName;
|
|
1687
|
+
if (opInfo.entityName) {
|
|
1688
|
+
entityName = opInfo.entityName;
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
continue;
|
|
1694
|
+
}
|
|
1695
|
+
const expr = statement.expression;
|
|
1696
|
+
if (ts9.isBinaryExpression(expr) && expr.operatorToken.kind === ts9.SyntaxKind.EqualsToken) {
|
|
1697
|
+
if (!ts9.isIdentifier(expr.left)) {
|
|
1698
|
+
continue;
|
|
1699
|
+
}
|
|
1700
|
+
const varName = expr.left.text;
|
|
1701
|
+
const rightSide = expr.right;
|
|
1702
|
+
if (ts9.isCallExpression(rightSide)) {
|
|
1703
|
+
const opInfo = extractChainedOperation(rightSide);
|
|
1704
|
+
if (opInfo) {
|
|
1705
|
+
if (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom") {
|
|
1706
|
+
queryBuilderVar = varName;
|
|
1707
|
+
if (opInfo.entityName) {
|
|
1708
|
+
entityName = opInfo.entityName;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
if ((opInfo.operation === "select" || opInfo.operation === "include") && queryBuilderVar === varName) {
|
|
1712
|
+
if (opInfo.operation === "select") {
|
|
1713
|
+
for (const field of opInfo.fields || []) {
|
|
1714
|
+
selectedFields.add(field);
|
|
1715
|
+
}
|
|
1716
|
+
} else if (opInfo.operation === "include" && opInfo.includeArg) {
|
|
1717
|
+
const parsedIncludes = parseIncludeObjectLiteral(opInfo.includeArg);
|
|
1718
|
+
if (parsedIncludes) {
|
|
1719
|
+
for (const [relName, relSchema] of Object.entries(parsedIncludes)) {
|
|
1720
|
+
includes[relName] = relSchema;
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if (!hasReturn || !queryBuilderVar || !entityName) {
|
|
1730
|
+
return null;
|
|
1731
|
+
}
|
|
1732
|
+
return {
|
|
1733
|
+
entityName,
|
|
1734
|
+
selectedFields: Array.from(selectedFields),
|
|
1735
|
+
includes,
|
|
1736
|
+
isPaged
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
function extractChainedOperation(callExpr) {
|
|
1740
|
+
if (ts9.isIdentifier(callExpr.expression)) {
|
|
1741
|
+
const methodName2 = callExpr.expression.text;
|
|
1742
|
+
if (methodName2 === "selectFromEntity" || methodName2 === "selectFrom") {
|
|
1743
|
+
const entityArg = callExpr.arguments[0];
|
|
1744
|
+
let entityName = null;
|
|
1745
|
+
if (ts9.isIdentifier(entityArg)) {
|
|
1746
|
+
entityName = entityArg.text;
|
|
1747
|
+
} else if (ts9.isPropertyAccessExpression(entityArg)) {
|
|
1748
|
+
entityName = entityArg.name.text;
|
|
1749
|
+
}
|
|
1750
|
+
return {
|
|
1751
|
+
operation: methodName2 === "selectFromEntity" ? "selectFromEntity" : "selectFrom",
|
|
1752
|
+
fields: null,
|
|
1753
|
+
includeArg: null,
|
|
1754
|
+
entityName
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
if (!ts9.isPropertyAccessExpression(callExpr.expression)) {
|
|
1759
|
+
return null;
|
|
1760
|
+
}
|
|
1761
|
+
const propAccess = callExpr.expression;
|
|
1762
|
+
const methodName = propAccess.name.text;
|
|
1763
|
+
if (methodName === "select") {
|
|
1764
|
+
const fields = [];
|
|
1765
|
+
for (const arg of callExpr.arguments) {
|
|
1766
|
+
if (ts9.isStringLiteral(arg)) {
|
|
1767
|
+
fields.push(arg.text);
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
return {
|
|
1771
|
+
operation: "select",
|
|
1772
|
+
fields,
|
|
1773
|
+
includeArg: null,
|
|
1774
|
+
entityName: null
|
|
1775
|
+
};
|
|
1776
|
+
}
|
|
1777
|
+
if (methodName === "include") {
|
|
1778
|
+
return {
|
|
1779
|
+
operation: "include",
|
|
1780
|
+
fields: null,
|
|
1781
|
+
includeArg: callExpr.arguments[0] || null,
|
|
1782
|
+
entityName: null
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
return null;
|
|
1786
|
+
}
|
|
1787
|
+
function parseIncludeObjectLiteral(arg) {
|
|
1788
|
+
if (!ts9.isObjectLiteralExpression(arg)) {
|
|
1789
|
+
return null;
|
|
1790
|
+
}
|
|
1791
|
+
const includes = {};
|
|
1792
|
+
for (const prop of arg.properties) {
|
|
1793
|
+
if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
const relationName = prop.name.text;
|
|
1797
|
+
const value = prop.initializer;
|
|
1798
|
+
if (value.kind === ts9.SyntaxKind.TrueKeyword) {
|
|
1799
|
+
includes[relationName] = true;
|
|
1800
|
+
} else if (ts9.isObjectLiteralExpression(value)) {
|
|
1801
|
+
const nestedSchema = parseNestedInclude(value, 0);
|
|
1802
|
+
if (nestedSchema) {
|
|
1803
|
+
includes[relationName] = nestedSchema;
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
return includes;
|
|
1808
|
+
}
|
|
1809
|
+
function parseNestedInclude(obj, depth) {
|
|
1810
|
+
const selectedFields = [];
|
|
1811
|
+
const includes = {};
|
|
1812
|
+
for (const prop of obj.properties) {
|
|
1813
|
+
if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
|
|
1814
|
+
continue;
|
|
1815
|
+
}
|
|
1816
|
+
const propName = prop.name.text;
|
|
1817
|
+
const value = prop.initializer;
|
|
1818
|
+
if (propName === "select" && ts9.isArrayLiteralExpression(value)) {
|
|
1819
|
+
for (const element of value.elements) {
|
|
1820
|
+
if (ts9.isStringLiteral(element)) {
|
|
1821
|
+
selectedFields.push(element.text);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
} else if (propName === "include" && ts9.isObjectLiteralExpression(value)) {
|
|
1825
|
+
const nestedIncludes = parseIncludeObjectLiteral(value);
|
|
1826
|
+
if (nestedIncludes) {
|
|
1827
|
+
for (const [relName, relSchema] of Object.entries(nestedIncludes)) {
|
|
1828
|
+
includes[relName] = relSchema;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
return {
|
|
1834
|
+
entityName: "",
|
|
1835
|
+
selectedFields,
|
|
1836
|
+
includes,
|
|
1837
|
+
isPaged: false
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
function getMethodName(expression) {
|
|
1841
|
+
if (ts9.isIdentifier(expression)) {
|
|
1842
|
+
return expression.text;
|
|
1843
|
+
}
|
|
1844
|
+
if (ts9.isPropertyAccessExpression(expression)) {
|
|
1845
|
+
return expression.name.text;
|
|
1846
|
+
}
|
|
1847
|
+
return null;
|
|
1848
|
+
}
|
|
1849
|
+
function findReturnStatement(body) {
|
|
1850
|
+
let returnStatement = null;
|
|
1851
|
+
for (const statement of body.statements) {
|
|
1852
|
+
if (ts9.isReturnStatement(statement)) {
|
|
1853
|
+
if (returnStatement !== null) {
|
|
1854
|
+
return null;
|
|
1855
|
+
}
|
|
1856
|
+
returnStatement = statement;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return returnStatement;
|
|
1860
|
+
}
|
|
1861
|
+
function analyzeReturnExpression(expression) {
|
|
1862
|
+
if (!expression) {
|
|
1863
|
+
return null;
|
|
1864
|
+
}
|
|
1865
|
+
if (ts9.isCallExpression(expression)) {
|
|
1866
|
+
return buildCallChain(expression, null);
|
|
1867
|
+
}
|
|
1868
|
+
return null;
|
|
1869
|
+
}
|
|
1870
|
+
function buildCallChain(node, parent) {
|
|
1871
|
+
if (ts9.isCallExpression(node)) {
|
|
1872
|
+
const callNode = {
|
|
1873
|
+
expression: node.expression,
|
|
1874
|
+
methodName: getMethodName(node.expression),
|
|
1875
|
+
arguments: node.arguments,
|
|
1876
|
+
parent
|
|
1877
|
+
};
|
|
1878
|
+
if (ts9.isPropertyAccessExpression(node.expression)) {
|
|
1879
|
+
return buildCallChain(node.expression.expression, callNode);
|
|
1880
|
+
}
|
|
1881
|
+
return callNode;
|
|
1882
|
+
}
|
|
1883
|
+
return parent;
|
|
1884
|
+
}
|
|
1885
|
+
function parseQueryBuilderChain(chain, checker, options) {
|
|
1886
|
+
if (!chain) {
|
|
1887
|
+
return null;
|
|
1888
|
+
}
|
|
1889
|
+
const rootNode = findSelectFromEntityCall(chain);
|
|
1890
|
+
if (!rootNode) {
|
|
1891
|
+
return null;
|
|
1892
|
+
}
|
|
1893
|
+
const entityName = extractEntityName(rootNode, checker);
|
|
1894
|
+
if (!entityName) {
|
|
1895
|
+
return null;
|
|
1896
|
+
}
|
|
1897
|
+
const selectedFields = /* @__PURE__ */ new Set();
|
|
1898
|
+
const includes = {};
|
|
1899
|
+
let isPaged = false;
|
|
1900
|
+
let currentNode = chain;
|
|
1901
|
+
while (currentNode) {
|
|
1902
|
+
const methodName = currentNode.methodName;
|
|
1903
|
+
if (methodName === "select") {
|
|
1904
|
+
for (const arg of currentNode.arguments) {
|
|
1905
|
+
if (ts9.isStringLiteral(arg)) {
|
|
1906
|
+
selectedFields.add(arg.text);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
} else if (methodName === "include") {
|
|
1910
|
+
parseIncludeArgument(currentNode.arguments[0], includes, checker, options, 0);
|
|
1911
|
+
} else if (methodName === "executePaged") {
|
|
1912
|
+
isPaged = true;
|
|
1913
|
+
}
|
|
1914
|
+
currentNode = currentNode.parent;
|
|
1915
|
+
}
|
|
1916
|
+
return {
|
|
1917
|
+
entityName,
|
|
1918
|
+
selectedFields: Array.from(selectedFields),
|
|
1919
|
+
includes,
|
|
1920
|
+
isPaged
|
|
1921
|
+
};
|
|
1922
|
+
}
|
|
1923
|
+
function findSelectFromEntityCall(chain) {
|
|
1924
|
+
let currentNode = chain;
|
|
1925
|
+
let lastNode = null;
|
|
1926
|
+
while (currentNode) {
|
|
1927
|
+
if (currentNode.methodName === "selectFromEntity" || currentNode.methodName === "selectFrom") {
|
|
1928
|
+
return currentNode;
|
|
1929
|
+
}
|
|
1930
|
+
lastNode = currentNode;
|
|
1931
|
+
currentNode = currentNode.parent;
|
|
1932
|
+
}
|
|
1933
|
+
return lastNode;
|
|
1934
|
+
}
|
|
1935
|
+
function extractEntityName(callNode, checker) {
|
|
1936
|
+
if (callNode.arguments.length === 0) {
|
|
1937
|
+
return null;
|
|
1938
|
+
}
|
|
1939
|
+
const entityArg = callNode.arguments[0];
|
|
1940
|
+
if (ts9.isIdentifier(entityArg)) {
|
|
1941
|
+
return entityArg.text;
|
|
1942
|
+
}
|
|
1943
|
+
if (ts9.isPropertyAccessExpression(entityArg)) {
|
|
1944
|
+
return entityArg.name.text;
|
|
1945
|
+
}
|
|
1946
|
+
return null;
|
|
1947
|
+
}
|
|
1948
|
+
function parseIncludeArgument(arg, includes, checker, options, depth) {
|
|
1949
|
+
if (!arg) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
if (ts9.isObjectLiteralExpression(arg)) {
|
|
1953
|
+
for (const prop of arg.properties) {
|
|
1954
|
+
if (!ts9.isPropertyAssignment(prop) || !ts9.isIdentifier(prop.name)) {
|
|
1955
|
+
continue;
|
|
1956
|
+
}
|
|
1957
|
+
const relationName = prop.name.text;
|
|
1958
|
+
const value = prop.initializer;
|
|
1959
|
+
if (value.kind === ts9.SyntaxKind.TrueKeyword) {
|
|
1960
|
+
includes[relationName] = true;
|
|
1961
|
+
} else if (ts9.isObjectLiteralExpression(value)) {
|
|
1962
|
+
const maxDepth = options.maxDepth ?? 5;
|
|
1963
|
+
if (depth < maxDepth) {
|
|
1964
|
+
const nestedSchema = parseNestedInclude(value, depth + 1);
|
|
1965
|
+
if (nestedSchema) {
|
|
1966
|
+
includes[relationName] = nestedSchema;
|
|
1967
|
+
}
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// src/compiler/schema/queryBuilderSchemaBuilder.ts
|
|
1975
|
+
import "typescript";
|
|
1976
|
+
function wrapInPaginatedResult(schema) {
|
|
1977
|
+
return {
|
|
1978
|
+
type: "object",
|
|
1979
|
+
properties: {
|
|
1980
|
+
items: {
|
|
1981
|
+
type: "array",
|
|
1982
|
+
items: schema
|
|
1983
|
+
},
|
|
1984
|
+
page: { type: "integer" },
|
|
1985
|
+
pageSize: { type: "integer" },
|
|
1986
|
+
totalItems: { type: "integer" }
|
|
1987
|
+
},
|
|
1988
|
+
required: ["items", "page", "pageSize", "totalItems"]
|
|
1989
|
+
};
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1565
1992
|
// src/compiler/schema/openapi.ts
|
|
1566
1993
|
var METAL_ORM_WRAPPER_NAMES2 = ["BelongsToReference", "HasOneReference", "HasManyCollection", "ManyToManyCollection"];
|
|
1567
1994
|
function generateOpenAPI(controllers, checker, options = {}) {
|
|
@@ -1574,7 +2001,12 @@ function generateOpenAPI(controllers, checker, options = {}) {
|
|
|
1574
2001
|
mode: "response"
|
|
1575
2002
|
};
|
|
1576
2003
|
const paths = {};
|
|
1577
|
-
const { onProgress } = options;
|
|
2004
|
+
const { onProgress, onQueryBuilderProgress } = options;
|
|
2005
|
+
let totalOperations = 0;
|
|
2006
|
+
for (const controller of controllers) {
|
|
2007
|
+
totalOperations += controller.operations.length;
|
|
2008
|
+
}
|
|
2009
|
+
let currentOperation = 0;
|
|
1578
2010
|
for (let i = 0; i < controllers.length; i++) {
|
|
1579
2011
|
const controller = controllers[i];
|
|
1580
2012
|
if (onProgress) {
|
|
@@ -1586,6 +2018,32 @@ function generateOpenAPI(controllers, checker, options = {}) {
|
|
|
1586
2018
|
paths[fullPath] = {};
|
|
1587
2019
|
}
|
|
1588
2020
|
const method = operation.httpMethod.toLowerCase();
|
|
2021
|
+
const analysisResult = analyzeQueryBuilderWithDetails(
|
|
2022
|
+
operation.methodDeclaration,
|
|
2023
|
+
checker,
|
|
2024
|
+
{},
|
|
2025
|
+
{
|
|
2026
|
+
methodName: operation.operationId,
|
|
2027
|
+
httpMethod: operation.httpMethod,
|
|
2028
|
+
path: operation.path,
|
|
2029
|
+
operationId: operation.operationId
|
|
2030
|
+
}
|
|
2031
|
+
);
|
|
2032
|
+
if (onQueryBuilderProgress) {
|
|
2033
|
+
currentOperation++;
|
|
2034
|
+
onQueryBuilderProgress({
|
|
2035
|
+
controller: controller.className,
|
|
2036
|
+
operation: operation.operationId,
|
|
2037
|
+
method: operation.httpMethod,
|
|
2038
|
+
path: operation.path,
|
|
2039
|
+
queryBuilderDetected: analysisResult.detected,
|
|
2040
|
+
entityName: analysisResult.schema?.entityName,
|
|
2041
|
+
selectedFields: analysisResult.schema?.selectedFields,
|
|
2042
|
+
isPaged: analysisResult.schema?.isPaged,
|
|
2043
|
+
current: currentOperation,
|
|
2044
|
+
total: totalOperations
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
1589
2047
|
paths[fullPath][method] = buildOperation(operation, ctx, controller.consumes);
|
|
1590
2048
|
}
|
|
1591
2049
|
}
|
|
@@ -1716,6 +2174,88 @@ function convertToOpenApiPath(basePath, path4) {
|
|
|
1716
2174
|
}
|
|
1717
2175
|
return fullPath;
|
|
1718
2176
|
}
|
|
2177
|
+
function tryInferQueryBuilderSchema(operation, checker) {
|
|
2178
|
+
return analyzeQueryBuilderForSchema(operation.methodDeclaration, checker) ?? null;
|
|
2179
|
+
}
|
|
2180
|
+
function getEntityTypeFromReturnType(operation, checker) {
|
|
2181
|
+
const returnType = operation.returnType;
|
|
2182
|
+
const unwrapPromise2 = (type) => {
|
|
2183
|
+
const symbol2 = type.getSymbol();
|
|
2184
|
+
if (symbol2?.getName() === "Promise") {
|
|
2185
|
+
const typeArgs = type.typeArguments;
|
|
2186
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
2187
|
+
return typeArgs[0];
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
return type;
|
|
2191
|
+
};
|
|
2192
|
+
const innerType = unwrapPromise2(returnType);
|
|
2193
|
+
const symbol = innerType.getSymbol();
|
|
2194
|
+
if (symbol?.getName() === "PaginatedResult") {
|
|
2195
|
+
const typeArgs = innerType.typeArguments;
|
|
2196
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
2197
|
+
return typeArgs[0];
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
return null;
|
|
2201
|
+
}
|
|
2202
|
+
function filterSchemaByQueryBuilder(querySchema, operation, ctx) {
|
|
2203
|
+
const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
|
|
2204
|
+
if (!entityType) {
|
|
2205
|
+
return {};
|
|
2206
|
+
}
|
|
2207
|
+
const entitySchema = typeToJsonSchema(entityType, ctx);
|
|
2208
|
+
let baseSchema = entitySchema;
|
|
2209
|
+
if (entitySchema.$ref && entitySchema.$ref.startsWith("#/components/schemas/")) {
|
|
2210
|
+
const schemaName = entitySchema.$ref.replace("#/components/schemas/", "");
|
|
2211
|
+
const componentSchema = ctx.components.get(schemaName);
|
|
2212
|
+
if (componentSchema) {
|
|
2213
|
+
baseSchema = componentSchema;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
if (!baseSchema.properties || Object.keys(baseSchema.properties).length === 0) {
|
|
2217
|
+
return {};
|
|
2218
|
+
}
|
|
2219
|
+
const filteredSchema = buildFilteredSchema(querySchema, baseSchema);
|
|
2220
|
+
if (querySchema.isPaged) {
|
|
2221
|
+
return wrapInPaginatedResult(filteredSchema);
|
|
2222
|
+
}
|
|
2223
|
+
return filteredSchema;
|
|
2224
|
+
}
|
|
2225
|
+
function buildFilteredSchema(querySchema, entitySchema) {
|
|
2226
|
+
const properties = {};
|
|
2227
|
+
const required = [];
|
|
2228
|
+
for (const field of querySchema.selectedFields) {
|
|
2229
|
+
if (entitySchema.properties?.[field]) {
|
|
2230
|
+
properties[field] = entitySchema.properties[field];
|
|
2231
|
+
if (entitySchema.required && entitySchema.required.includes(field)) {
|
|
2232
|
+
required.push(field);
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
for (const [relationName, includeSpec] of Object.entries(querySchema.includes)) {
|
|
2237
|
+
if (entitySchema.properties?.[relationName]) {
|
|
2238
|
+
properties[relationName] = {
|
|
2239
|
+
type: "object",
|
|
2240
|
+
properties: {
|
|
2241
|
+
id: { type: "integer" }
|
|
2242
|
+
},
|
|
2243
|
+
required: ["id"]
|
|
2244
|
+
};
|
|
2245
|
+
if (entitySchema.required && entitySchema.required.includes(relationName)) {
|
|
2246
|
+
required.push(relationName);
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
const schema = {
|
|
2251
|
+
type: "object",
|
|
2252
|
+
properties
|
|
2253
|
+
};
|
|
2254
|
+
if (required.length > 0) {
|
|
2255
|
+
schema.required = required;
|
|
2256
|
+
}
|
|
2257
|
+
return schema;
|
|
2258
|
+
}
|
|
1719
2259
|
function buildOperation(operation, ctx, controllerConsumes) {
|
|
1720
2260
|
const op = {
|
|
1721
2261
|
operationId: operation.operationId,
|
|
@@ -1730,7 +2270,18 @@ function buildOperation(operation, ctx, controllerConsumes) {
|
|
|
1730
2270
|
op.parameters = parameters;
|
|
1731
2271
|
}
|
|
1732
2272
|
const responseCtx = { ...ctx, mode: "response" };
|
|
1733
|
-
|
|
2273
|
+
let responseSchema;
|
|
2274
|
+
const querySchema = tryInferQueryBuilderSchema(operation, ctx.checker);
|
|
2275
|
+
if (querySchema) {
|
|
2276
|
+
const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
|
|
2277
|
+
if (entityType) {
|
|
2278
|
+
responseSchema = filterSchemaByQueryBuilder(querySchema, operation, responseCtx);
|
|
2279
|
+
} else {
|
|
2280
|
+
responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
|
|
2281
|
+
}
|
|
2282
|
+
} else {
|
|
2283
|
+
responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
|
|
2284
|
+
}
|
|
1734
2285
|
const status = operation.httpMethod === "POST" ? 201 : 200;
|
|
1735
2286
|
op.responses[status] = {
|
|
1736
2287
|
description: status === 201 ? "Created" : "OK",
|
|
@@ -1772,12 +2323,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
|
|
|
1772
2323
|
const declarations = typeSymbol.getDeclarations();
|
|
1773
2324
|
if (!declarations || declarations.length === 0) return schema;
|
|
1774
2325
|
const classDecl = declarations[0];
|
|
1775
|
-
if (!
|
|
2326
|
+
if (!ts11.isClassDeclaration(classDecl)) return schema;
|
|
1776
2327
|
const result = { ...schema };
|
|
1777
2328
|
const props = { ...result.properties };
|
|
1778
2329
|
for (const member of classDecl.members) {
|
|
1779
|
-
if (!
|
|
1780
|
-
const propName =
|
|
2330
|
+
if (!ts11.isPropertyDeclaration(member) || !member.name) continue;
|
|
2331
|
+
const propName = ts11.isIdentifier(member.name) ? member.name.text : null;
|
|
1781
2332
|
if (!propName) continue;
|
|
1782
2333
|
if (!props[propName]) continue;
|
|
1783
2334
|
const frags = extractPropertySchemaFragments(ctx.checker, member);
|
|
@@ -1790,7 +2341,7 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
|
|
|
1790
2341
|
}
|
|
1791
2342
|
|
|
1792
2343
|
// src/compiler/manifest/emit.ts
|
|
1793
|
-
import
|
|
2344
|
+
import ts12 from "typescript";
|
|
1794
2345
|
function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
|
|
1795
2346
|
const components = /* @__PURE__ */ new Map();
|
|
1796
2347
|
const ctx = {
|
|
@@ -1812,7 +2363,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
|
|
|
1812
2363
|
generator: {
|
|
1813
2364
|
name: "adorn-api",
|
|
1814
2365
|
version,
|
|
1815
|
-
typescript:
|
|
2366
|
+
typescript: ts12.version
|
|
1816
2367
|
},
|
|
1817
2368
|
schemas: {
|
|
1818
2369
|
kind: "openapi-3.1",
|
|
@@ -2297,7 +2848,7 @@ async function isStale(params) {
|
|
|
2297
2848
|
// src/compiler/cache/writeCache.ts
|
|
2298
2849
|
import fs3 from "fs";
|
|
2299
2850
|
import path3 from "path";
|
|
2300
|
-
import
|
|
2851
|
+
import ts13 from "typescript";
|
|
2301
2852
|
function statMtimeMs2(p) {
|
|
2302
2853
|
return fs3.statSync(p).mtimeMs;
|
|
2303
2854
|
}
|
|
@@ -2330,7 +2881,7 @@ function writeCache(params) {
|
|
|
2330
2881
|
generator: {
|
|
2331
2882
|
name: "adorn-api",
|
|
2332
2883
|
version: params.adornVersion,
|
|
2333
|
-
typescript:
|
|
2884
|
+
typescript: ts13.version
|
|
2334
2885
|
},
|
|
2335
2886
|
project: {
|
|
2336
2887
|
tsconfigPath: params.tsconfigAbs,
|
|
@@ -3083,7 +3634,7 @@ function getEdgesByRelation(graph, relation) {
|
|
|
3083
3634
|
}
|
|
3084
3635
|
|
|
3085
3636
|
// src/compiler/graph/builder.ts
|
|
3086
|
-
import
|
|
3637
|
+
import ts14 from "typescript";
|
|
3087
3638
|
|
|
3088
3639
|
// src/compiler/graph/schemaGraph.ts
|
|
3089
3640
|
var SchemaGraph = class {
|
|
@@ -3335,7 +3886,7 @@ var SchemaGraph = class {
|
|
|
3335
3886
|
};
|
|
3336
3887
|
|
|
3337
3888
|
// src/cli.ts
|
|
3338
|
-
import
|
|
3889
|
+
import ts15 from "typescript";
|
|
3339
3890
|
import process2 from "process";
|
|
3340
3891
|
var ADORN_VERSION = (() => {
|
|
3341
3892
|
const tryReadPackageJson = (filePath) => {
|
|
@@ -3413,7 +3964,7 @@ function sanitizeForJson(obj) {
|
|
|
3413
3964
|
return result;
|
|
3414
3965
|
}
|
|
3415
3966
|
function buildControllerGraph(controllers) {
|
|
3416
|
-
const graph = createGraph(
|
|
3967
|
+
const graph = createGraph(ts15.version);
|
|
3417
3968
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
3418
3969
|
for (const ctrl of controllers) {
|
|
3419
3970
|
const nodeId = `Controller:${ctrl.className}`;
|
|
@@ -3505,6 +4056,7 @@ async function buildCommand(args) {
|
|
|
3505
4056
|
const verbose = args.includes("--verbose");
|
|
3506
4057
|
const quiet = args.includes("--quiet");
|
|
3507
4058
|
const split = args.includes("--split");
|
|
4059
|
+
const showQueryBuilder = args.includes("--show-query-builder");
|
|
3508
4060
|
const splitStrategyIndex = args.indexOf("--split-strategy");
|
|
3509
4061
|
const splitStrategy = splitStrategyIndex !== -1 ? args[splitStrategyIndex + 1] : void 0;
|
|
3510
4062
|
const splitThresholdIndex = args.indexOf("--split-threshold");
|
|
@@ -3524,7 +4076,7 @@ async function buildCommand(args) {
|
|
|
3524
4076
|
outDir: outputDir,
|
|
3525
4077
|
project: projectPath,
|
|
3526
4078
|
adornVersion: ADORN_VERSION,
|
|
3527
|
-
typescriptVersion:
|
|
4079
|
+
typescriptVersion: ts15.version
|
|
3528
4080
|
});
|
|
3529
4081
|
if (!stale.stale) {
|
|
3530
4082
|
progress.completePhase("staleness-check");
|
|
@@ -3565,6 +4117,12 @@ async function buildCommand(args) {
|
|
|
3565
4117
|
}
|
|
3566
4118
|
}
|
|
3567
4119
|
progress.startPhase("openapi", "Generating OpenAPI schema");
|
|
4120
|
+
const queryBuilderStats = {
|
|
4121
|
+
totalOperations,
|
|
4122
|
+
detected: 0,
|
|
4123
|
+
fallback: 0,
|
|
4124
|
+
operations: []
|
|
4125
|
+
};
|
|
3568
4126
|
const openapiSpinner = new Spinner("Processing schemas");
|
|
3569
4127
|
if (!quiet) openapiSpinner.start();
|
|
3570
4128
|
const openapi = generateOpenAPI(controllers, checker, {
|
|
@@ -3574,6 +4132,31 @@ async function buildCommand(args) {
|
|
|
3574
4132
|
if (!quiet) {
|
|
3575
4133
|
openapiSpinner.setStatus(`${message} (${current}/${total})`);
|
|
3576
4134
|
}
|
|
4135
|
+
},
|
|
4136
|
+
onQueryBuilderProgress: (info) => {
|
|
4137
|
+
if (info.queryBuilderDetected) {
|
|
4138
|
+
queryBuilderStats.detected++;
|
|
4139
|
+
} else {
|
|
4140
|
+
queryBuilderStats.fallback++;
|
|
4141
|
+
}
|
|
4142
|
+
queryBuilderStats.operations.push({
|
|
4143
|
+
operationId: info.operation,
|
|
4144
|
+
method: info.method,
|
|
4145
|
+
path: info.path,
|
|
4146
|
+
detected: info.queryBuilderDetected,
|
|
4147
|
+
entityName: info.entityName,
|
|
4148
|
+
selectedFields: info.selectedFields,
|
|
4149
|
+
isPaged: info.isPaged
|
|
4150
|
+
});
|
|
4151
|
+
if (showQueryBuilder || verbose) {
|
|
4152
|
+
if (info.queryBuilderDetected) {
|
|
4153
|
+
const fieldsStr = info.selectedFields && info.selectedFields.length > 0 ? ` [select: ${info.selectedFields.join(",")}]` : "";
|
|
4154
|
+
const pagedStr = info.isPaged ? " (paged)" : "";
|
|
4155
|
+
progress.verboseLog(` \u2713 Query builder: ${info.method} ${info.path} \u2192 ${info.entityName}${fieldsStr}${pagedStr}`);
|
|
4156
|
+
} else {
|
|
4157
|
+
progress.verboseLog(` \u25CB No query builder: ${info.method} ${info.path} \u2192 using full entity schema`);
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
3577
4160
|
}
|
|
3578
4161
|
});
|
|
3579
4162
|
if (!quiet) {
|
|
@@ -3632,6 +4215,17 @@ async function buildCommand(args) {
|
|
|
3632
4215
|
}
|
|
3633
4216
|
}
|
|
3634
4217
|
progress.completePhase("openapi", `Generated ${schemaCount} schema(s)${splitEnabled ? " (split into groups)" : ""}`);
|
|
4218
|
+
if (showQueryBuilder && totalOperations > 0) {
|
|
4219
|
+
log("");
|
|
4220
|
+
log("Query Builder Analysis:");
|
|
4221
|
+
log(` Operations analyzed: ${totalOperations}`);
|
|
4222
|
+
log(` Patterns detected: ${queryBuilderStats.detected} (${Math.round(queryBuilderStats.detected / totalOperations * 100)}%)`);
|
|
4223
|
+
log(` Full schemas used: ${queryBuilderStats.fallback} (${Math.round(queryBuilderStats.fallback / totalOperations * 100)}%)`);
|
|
4224
|
+
if (queryBuilderStats.detected > 0) {
|
|
4225
|
+
const totalFields = queryBuilderStats.operations.filter((op) => op.detected && op.selectedFields).reduce((sum, op) => sum + (op.selectedFields?.length || 0), 0);
|
|
4226
|
+
log(` Fields selected: ${totalFields} total (avg ${Math.round(totalFields / queryBuilderStats.detected)} per query)`);
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
3635
4229
|
progress.startPhase("manifest", "Generating manifest");
|
|
3636
4230
|
const manifest = generateManifest(controllers, checker, ADORN_VERSION, validationMode);
|
|
3637
4231
|
progress.completePhase("manifest");
|
|
@@ -3713,7 +4307,12 @@ async function buildCommand(args) {
|
|
|
3713
4307
|
schemas: schemaCount,
|
|
3714
4308
|
sourceFiles: projectSourceFiles.length,
|
|
3715
4309
|
artifactsWritten: artifacts.map((a) => a.name),
|
|
3716
|
-
splitEnabled
|
|
4310
|
+
splitEnabled,
|
|
4311
|
+
queryBuilder: {
|
|
4312
|
+
detected: queryBuilderStats.detected,
|
|
4313
|
+
fallback: queryBuilderStats.fallback,
|
|
4314
|
+
total: totalOperations
|
|
4315
|
+
}
|
|
3717
4316
|
};
|
|
3718
4317
|
progress.printSummary(stats);
|
|
3719
4318
|
progress.printArtifacts(artifacts);
|
|
@@ -3741,30 +4340,32 @@ if (command === "build") {
|
|
|
3741
4340
|
console.log(`
|
|
3742
4341
|
adorn-api CLI v${ADORN_VERSION}
|
|
3743
4342
|
|
|
3744
|
-
Commands:
|
|
3745
|
-
|
|
3746
|
-
|
|
4343
|
+
Commands:
|
|
4344
|
+
build Generate OpenAPI and manifest from TypeScript source
|
|
4345
|
+
clean Remove generated artifacts
|
|
3747
4346
|
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
4347
|
+
Options:
|
|
4348
|
+
-p <path> Path to tsconfig.json (default: ./tsconfig.json)
|
|
4349
|
+
--output <dir> Output directory (default: .adorn)
|
|
4350
|
+
--if-stale Only rebuild if artifacts are stale
|
|
4351
|
+
--validation-mode <mode> Validation mode: none, ajv-runtime, precompiled (default: ajv-runtime)
|
|
4352
|
+
--split Enable automatic schema splitting (default: disabled)
|
|
4353
|
+
--split-strategy <mode> Override splitting strategy: controller, dependency, size, auto (default: auto)
|
|
4354
|
+
--split-threshold <num> Schema count threshold for auto-split (default: 50)
|
|
4355
|
+
--verbose Show detailed progress information
|
|
4356
|
+
--quiet Suppress non-essential output
|
|
4357
|
+
--show-query-builder Show query builder inspection details and statistics
|
|
3758
4358
|
|
|
3759
|
-
Examples:
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
4359
|
+
Examples:
|
|
4360
|
+
adorn-api build -p ./tsconfig.json --output .adorn
|
|
4361
|
+
adorn-api build --if-stale
|
|
4362
|
+
adorn-api build --validation-mode precompiled
|
|
4363
|
+
adorn-api build --verbose
|
|
4364
|
+
adorn-api build --show-query-builder # Show query builder analysis details
|
|
4365
|
+
adorn-api build --split # Enable split mode
|
|
4366
|
+
adorn-api build --split-strategy controller # Force controller-based splitting
|
|
4367
|
+
adorn-api build --split-threshold 100 # Increase threshold to 100
|
|
4368
|
+
adorn-api clean
|
|
4369
|
+
`);
|
|
3769
4370
|
}
|
|
3770
4371
|
//# sourceMappingURL=cli.js.map
|