adorn-api 1.0.20 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +529 -17
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +529 -17
- 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.map +1 -1
- package/dist/compiler/schema/queryBuilderAnalyzer.d.ts +43 -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.cjs
CHANGED
|
@@ -323,7 +323,7 @@ function unwrapPromiseTypeNode(typeNode) {
|
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
// src/compiler/schema/openapi.ts
|
|
326
|
-
var
|
|
326
|
+
var import_typescript11 = __toESM(require("typescript"), 1);
|
|
327
327
|
|
|
328
328
|
// src/compiler/schema/typeToJsonSchema.ts
|
|
329
329
|
var import_typescript7 = __toESM(require("typescript"), 1);
|
|
@@ -718,6 +718,48 @@ function getExplicitTypeNameFromNode3(typeNode) {
|
|
|
718
718
|
|
|
719
719
|
// src/compiler/schema/objectHandler.ts
|
|
720
720
|
var import_typescript6 = __toESM(require("typescript"), 1);
|
|
721
|
+
function getTypeParameterName(type) {
|
|
722
|
+
if (type.flags & import_typescript6.default.TypeFlags.TypeParameter) {
|
|
723
|
+
const typeParam = type;
|
|
724
|
+
return typeParam.symbol?.getName() ?? null;
|
|
725
|
+
}
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
function getTypeArguments(type) {
|
|
729
|
+
const typeRef = type;
|
|
730
|
+
const args = typeRef.typeArguments;
|
|
731
|
+
if (!args) return void 0;
|
|
732
|
+
return Array.from(args);
|
|
733
|
+
}
|
|
734
|
+
function createTypeParameterSubstitutions(type, typeNode, checker) {
|
|
735
|
+
const typeArgs = getTypeArguments(type);
|
|
736
|
+
if (!typeArgs || typeArgs.length === 0) {
|
|
737
|
+
return void 0;
|
|
738
|
+
}
|
|
739
|
+
if (!typeNode || !import_typescript6.default.isTypeReferenceNode(typeNode)) {
|
|
740
|
+
return void 0;
|
|
741
|
+
}
|
|
742
|
+
const typeParams = typeNode.typeArguments;
|
|
743
|
+
if (!typeParams || typeParams.length !== typeArgs.length) {
|
|
744
|
+
return void 0;
|
|
745
|
+
}
|
|
746
|
+
const substitutions = /* @__PURE__ */ new Map();
|
|
747
|
+
for (let i = 0; i < typeParams.length; i++) {
|
|
748
|
+
const typeParamNode = typeParams[i];
|
|
749
|
+
const typeArg = typeArgs[i];
|
|
750
|
+
if (import_typescript6.default.isIdentifier(typeParamNode)) {
|
|
751
|
+
substitutions.set(typeParamNode.text, typeArg);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return substitutions.size > 0 ? substitutions : void 0;
|
|
755
|
+
}
|
|
756
|
+
function resolveTypeParameter(type, substitutions, _checker) {
|
|
757
|
+
if (!substitutions) return null;
|
|
758
|
+
const paramName = getTypeParameterName(type);
|
|
759
|
+
if (!paramName) return null;
|
|
760
|
+
const resolved = substitutions.get(paramName);
|
|
761
|
+
return resolved ?? null;
|
|
762
|
+
}
|
|
721
763
|
function handleObjectType(type, ctx, typeNode) {
|
|
722
764
|
const { checker, components, typeStack } = ctx;
|
|
723
765
|
const symbol = type.getSymbol();
|
|
@@ -737,7 +779,9 @@ function handleObjectType(type, ctx, typeNode) {
|
|
|
737
779
|
}
|
|
738
780
|
typeStack.add(type);
|
|
739
781
|
}
|
|
740
|
-
const
|
|
782
|
+
const typeParamSubstitutions = createTypeParameterSubstitutions(type, typeNode, checker);
|
|
783
|
+
const buildCtx = typeParamSubstitutions ? { ...ctx, typeParameterSubstitutions: typeParamSubstitutions } : ctx;
|
|
784
|
+
const schema = buildObjectSchema(type, buildCtx, typeNode);
|
|
741
785
|
if (typeName && typeName !== "__type") {
|
|
742
786
|
typeStack.delete(type);
|
|
743
787
|
const existing = components.get(typeName);
|
|
@@ -755,7 +799,7 @@ function handleObjectType(type, ctx, typeNode) {
|
|
|
755
799
|
return schema;
|
|
756
800
|
}
|
|
757
801
|
function buildObjectSchema(type, ctx, _typeNode) {
|
|
758
|
-
const { checker, mode } = ctx;
|
|
802
|
+
const { checker, mode, typeParameterSubstitutions } = ctx;
|
|
759
803
|
const properties = {};
|
|
760
804
|
const required = [];
|
|
761
805
|
const props = checker.getPropertiesOfType(type);
|
|
@@ -764,10 +808,14 @@ function buildObjectSchema(type, ctx, _typeNode) {
|
|
|
764
808
|
if (isIteratorOrSymbolProperty(propName)) {
|
|
765
809
|
continue;
|
|
766
810
|
}
|
|
767
|
-
|
|
811
|
+
let propType = checker.getTypeOfSymbol(prop);
|
|
768
812
|
if (isMethodLike(propType)) {
|
|
769
813
|
continue;
|
|
770
814
|
}
|
|
815
|
+
const resolvedType = resolveTypeParameter(propType, typeParameterSubstitutions, checker);
|
|
816
|
+
if (resolvedType) {
|
|
817
|
+
propType = resolvedType;
|
|
818
|
+
}
|
|
771
819
|
const isOptional = !!(prop.flags & import_typescript6.default.SymbolFlags.Optional);
|
|
772
820
|
const isRelation = isMetalOrmWrapperType(propType, checker);
|
|
773
821
|
const propCtx = { ...ctx, propertyName: propName };
|
|
@@ -787,7 +835,8 @@ function buildObjectSchema(type, ctx, _typeNode) {
|
|
|
787
835
|
if (isRecordType(type, checker)) {
|
|
788
836
|
const valueType = getRecordValueType(type, checker);
|
|
789
837
|
if (valueType) {
|
|
790
|
-
|
|
838
|
+
const resolvedValueType = resolveTypeParameter(valueType, typeParameterSubstitutions, checker);
|
|
839
|
+
schema.additionalProperties = typeToJsonSchema(resolvedValueType ?? valueType, ctx);
|
|
791
840
|
}
|
|
792
841
|
}
|
|
793
842
|
return schema;
|
|
@@ -1579,6 +1628,376 @@ function resolveAndCollectObjectProps(schema, components) {
|
|
|
1579
1628
|
return { properties, required };
|
|
1580
1629
|
}
|
|
1581
1630
|
|
|
1631
|
+
// src/compiler/schema/queryBuilderAnalyzer.ts
|
|
1632
|
+
var import_typescript9 = __toESM(require("typescript"), 1);
|
|
1633
|
+
function analyzeQueryBuilderForSchema(methodDeclaration, checker, options = {}) {
|
|
1634
|
+
const body = methodDeclaration.body;
|
|
1635
|
+
if (!body) {
|
|
1636
|
+
return null;
|
|
1637
|
+
}
|
|
1638
|
+
const trackedSchema = analyzeWithVariableTracking(body, checker, options);
|
|
1639
|
+
if (trackedSchema) {
|
|
1640
|
+
return trackedSchema;
|
|
1641
|
+
}
|
|
1642
|
+
const returnStatement = findReturnStatement(body);
|
|
1643
|
+
if (!returnStatement) {
|
|
1644
|
+
return null;
|
|
1645
|
+
}
|
|
1646
|
+
const callChain = analyzeReturnExpression(returnStatement.expression);
|
|
1647
|
+
if (!callChain) {
|
|
1648
|
+
return null;
|
|
1649
|
+
}
|
|
1650
|
+
return parseQueryBuilderChain(callChain, checker, options);
|
|
1651
|
+
}
|
|
1652
|
+
function analyzeWithVariableTracking(body, checker, options) {
|
|
1653
|
+
let queryBuilderVar = null;
|
|
1654
|
+
let entityName = null;
|
|
1655
|
+
const selectedFields = /* @__PURE__ */ new Set();
|
|
1656
|
+
const includes = {};
|
|
1657
|
+
let isPaged = false;
|
|
1658
|
+
let hasReturn = false;
|
|
1659
|
+
for (const statement of body.statements) {
|
|
1660
|
+
if (import_typescript9.default.isReturnStatement(statement)) {
|
|
1661
|
+
hasReturn = true;
|
|
1662
|
+
const returnExpr = statement.expression;
|
|
1663
|
+
if (returnExpr && import_typescript9.default.isCallExpression(returnExpr)) {
|
|
1664
|
+
const callExpr = returnExpr;
|
|
1665
|
+
if (import_typescript9.default.isIdentifier(callExpr.expression) && queryBuilderVar) {
|
|
1666
|
+
const varName = callExpr.expression.text;
|
|
1667
|
+
if (varName === queryBuilderVar) {
|
|
1668
|
+
const methodName = callExpr.expression.text;
|
|
1669
|
+
if (methodName === "executePaged") {
|
|
1670
|
+
isPaged = true;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
if (import_typescript9.default.isPropertyAccessExpression(callExpr.expression) && queryBuilderVar) {
|
|
1675
|
+
const propAccess = callExpr.expression;
|
|
1676
|
+
if (import_typescript9.default.isIdentifier(propAccess.expression) && propAccess.expression.text === queryBuilderVar) {
|
|
1677
|
+
const methodName = propAccess.name.text;
|
|
1678
|
+
if (methodName === "executePaged") {
|
|
1679
|
+
isPaged = true;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
if (!import_typescript9.default.isExpressionStatement(statement)) {
|
|
1687
|
+
if (import_typescript9.default.isVariableStatement(statement)) {
|
|
1688
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
1689
|
+
if (!import_typescript9.default.isIdentifier(declaration.name)) continue;
|
|
1690
|
+
const varName = declaration.name.text;
|
|
1691
|
+
const initializer = declaration.initializer;
|
|
1692
|
+
if (!initializer || !import_typescript9.default.isCallExpression(initializer)) continue;
|
|
1693
|
+
const opInfo = extractChainedOperation(initializer);
|
|
1694
|
+
if (opInfo && (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom")) {
|
|
1695
|
+
queryBuilderVar = varName;
|
|
1696
|
+
if (opInfo.entityName) {
|
|
1697
|
+
entityName = opInfo.entityName;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
continue;
|
|
1703
|
+
}
|
|
1704
|
+
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)) {
|
|
1707
|
+
continue;
|
|
1708
|
+
}
|
|
1709
|
+
const varName = expr.left.text;
|
|
1710
|
+
const rightSide = expr.right;
|
|
1711
|
+
if (import_typescript9.default.isCallExpression(rightSide)) {
|
|
1712
|
+
const opInfo = extractChainedOperation(rightSide);
|
|
1713
|
+
if (opInfo) {
|
|
1714
|
+
if (opInfo.operation === "selectFromEntity" || opInfo.operation === "selectFrom") {
|
|
1715
|
+
queryBuilderVar = varName;
|
|
1716
|
+
if (opInfo.entityName) {
|
|
1717
|
+
entityName = opInfo.entityName;
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
if ((opInfo.operation === "select" || opInfo.operation === "include") && queryBuilderVar === varName) {
|
|
1721
|
+
if (opInfo.operation === "select") {
|
|
1722
|
+
for (const field of opInfo.fields || []) {
|
|
1723
|
+
selectedFields.add(field);
|
|
1724
|
+
}
|
|
1725
|
+
} else if (opInfo.operation === "include" && opInfo.includeArg) {
|
|
1726
|
+
const parsedIncludes = parseIncludeObjectLiteral(opInfo.includeArg);
|
|
1727
|
+
if (parsedIncludes) {
|
|
1728
|
+
for (const [relName, relSchema] of Object.entries(parsedIncludes)) {
|
|
1729
|
+
includes[relName] = relSchema;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
if (!hasReturn || !queryBuilderVar || !entityName) {
|
|
1739
|
+
return null;
|
|
1740
|
+
}
|
|
1741
|
+
return {
|
|
1742
|
+
entityName,
|
|
1743
|
+
selectedFields: Array.from(selectedFields),
|
|
1744
|
+
includes,
|
|
1745
|
+
isPaged
|
|
1746
|
+
};
|
|
1747
|
+
}
|
|
1748
|
+
function extractChainedOperation(callExpr) {
|
|
1749
|
+
if (import_typescript9.default.isIdentifier(callExpr.expression)) {
|
|
1750
|
+
const methodName2 = callExpr.expression.text;
|
|
1751
|
+
if (methodName2 === "selectFromEntity" || methodName2 === "selectFrom") {
|
|
1752
|
+
const entityArg = callExpr.arguments[0];
|
|
1753
|
+
let entityName = null;
|
|
1754
|
+
if (import_typescript9.default.isIdentifier(entityArg)) {
|
|
1755
|
+
entityName = entityArg.text;
|
|
1756
|
+
} else if (import_typescript9.default.isPropertyAccessExpression(entityArg)) {
|
|
1757
|
+
entityName = entityArg.name.text;
|
|
1758
|
+
}
|
|
1759
|
+
return {
|
|
1760
|
+
operation: methodName2 === "selectFromEntity" ? "selectFromEntity" : "selectFrom",
|
|
1761
|
+
fields: null,
|
|
1762
|
+
includeArg: null,
|
|
1763
|
+
entityName
|
|
1764
|
+
};
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
if (!import_typescript9.default.isPropertyAccessExpression(callExpr.expression)) {
|
|
1768
|
+
return null;
|
|
1769
|
+
}
|
|
1770
|
+
const propAccess = callExpr.expression;
|
|
1771
|
+
const methodName = propAccess.name.text;
|
|
1772
|
+
if (methodName === "select") {
|
|
1773
|
+
const fields = [];
|
|
1774
|
+
for (const arg of callExpr.arguments) {
|
|
1775
|
+
if (import_typescript9.default.isStringLiteral(arg)) {
|
|
1776
|
+
fields.push(arg.text);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
return {
|
|
1780
|
+
operation: "select",
|
|
1781
|
+
fields,
|
|
1782
|
+
includeArg: null,
|
|
1783
|
+
entityName: null
|
|
1784
|
+
};
|
|
1785
|
+
}
|
|
1786
|
+
if (methodName === "include") {
|
|
1787
|
+
return {
|
|
1788
|
+
operation: "include",
|
|
1789
|
+
fields: null,
|
|
1790
|
+
includeArg: callExpr.arguments[0] || null,
|
|
1791
|
+
entityName: null
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
return null;
|
|
1795
|
+
}
|
|
1796
|
+
function parseIncludeObjectLiteral(arg) {
|
|
1797
|
+
if (!import_typescript9.default.isObjectLiteralExpression(arg)) {
|
|
1798
|
+
return null;
|
|
1799
|
+
}
|
|
1800
|
+
const includes = {};
|
|
1801
|
+
for (const prop of arg.properties) {
|
|
1802
|
+
if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
|
|
1803
|
+
continue;
|
|
1804
|
+
}
|
|
1805
|
+
const relationName = prop.name.text;
|
|
1806
|
+
const value = prop.initializer;
|
|
1807
|
+
if (value.kind === import_typescript9.default.SyntaxKind.TrueKeyword) {
|
|
1808
|
+
includes[relationName] = true;
|
|
1809
|
+
} else if (import_typescript9.default.isObjectLiteralExpression(value)) {
|
|
1810
|
+
const nestedSchema = parseNestedInclude(value, 0);
|
|
1811
|
+
if (nestedSchema) {
|
|
1812
|
+
includes[relationName] = nestedSchema;
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
return includes;
|
|
1817
|
+
}
|
|
1818
|
+
function parseNestedInclude(obj, depth) {
|
|
1819
|
+
const selectedFields = [];
|
|
1820
|
+
const includes = {};
|
|
1821
|
+
for (const prop of obj.properties) {
|
|
1822
|
+
if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
|
|
1823
|
+
continue;
|
|
1824
|
+
}
|
|
1825
|
+
const propName = prop.name.text;
|
|
1826
|
+
const value = prop.initializer;
|
|
1827
|
+
if (propName === "select" && import_typescript9.default.isArrayLiteralExpression(value)) {
|
|
1828
|
+
for (const element of value.elements) {
|
|
1829
|
+
if (import_typescript9.default.isStringLiteral(element)) {
|
|
1830
|
+
selectedFields.push(element.text);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
} else if (propName === "include" && import_typescript9.default.isObjectLiteralExpression(value)) {
|
|
1834
|
+
const nestedIncludes = parseIncludeObjectLiteral(value);
|
|
1835
|
+
if (nestedIncludes) {
|
|
1836
|
+
for (const [relName, relSchema] of Object.entries(nestedIncludes)) {
|
|
1837
|
+
includes[relName] = relSchema;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
return {
|
|
1843
|
+
entityName: "",
|
|
1844
|
+
selectedFields,
|
|
1845
|
+
includes,
|
|
1846
|
+
isPaged: false
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
function getMethodName(expression) {
|
|
1850
|
+
if (import_typescript9.default.isIdentifier(expression)) {
|
|
1851
|
+
return expression.text;
|
|
1852
|
+
}
|
|
1853
|
+
if (import_typescript9.default.isPropertyAccessExpression(expression)) {
|
|
1854
|
+
return expression.name.text;
|
|
1855
|
+
}
|
|
1856
|
+
return null;
|
|
1857
|
+
}
|
|
1858
|
+
function findReturnStatement(body) {
|
|
1859
|
+
let returnStatement = null;
|
|
1860
|
+
for (const statement of body.statements) {
|
|
1861
|
+
if (import_typescript9.default.isReturnStatement(statement)) {
|
|
1862
|
+
if (returnStatement !== null) {
|
|
1863
|
+
return null;
|
|
1864
|
+
}
|
|
1865
|
+
returnStatement = statement;
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
return returnStatement;
|
|
1869
|
+
}
|
|
1870
|
+
function analyzeReturnExpression(expression) {
|
|
1871
|
+
if (!expression) {
|
|
1872
|
+
return null;
|
|
1873
|
+
}
|
|
1874
|
+
if (import_typescript9.default.isCallExpression(expression)) {
|
|
1875
|
+
return buildCallChain(expression, null);
|
|
1876
|
+
}
|
|
1877
|
+
return null;
|
|
1878
|
+
}
|
|
1879
|
+
function buildCallChain(node, parent) {
|
|
1880
|
+
if (import_typescript9.default.isCallExpression(node)) {
|
|
1881
|
+
const callNode = {
|
|
1882
|
+
expression: node.expression,
|
|
1883
|
+
methodName: getMethodName(node.expression),
|
|
1884
|
+
arguments: node.arguments,
|
|
1885
|
+
parent
|
|
1886
|
+
};
|
|
1887
|
+
if (import_typescript9.default.isPropertyAccessExpression(node.expression)) {
|
|
1888
|
+
return buildCallChain(node.expression.expression, callNode);
|
|
1889
|
+
}
|
|
1890
|
+
return callNode;
|
|
1891
|
+
}
|
|
1892
|
+
return parent;
|
|
1893
|
+
}
|
|
1894
|
+
function parseQueryBuilderChain(chain, checker, options) {
|
|
1895
|
+
if (!chain) {
|
|
1896
|
+
return null;
|
|
1897
|
+
}
|
|
1898
|
+
const rootNode = findSelectFromEntityCall(chain);
|
|
1899
|
+
if (!rootNode) {
|
|
1900
|
+
return null;
|
|
1901
|
+
}
|
|
1902
|
+
const entityName = extractEntityName(rootNode, checker);
|
|
1903
|
+
if (!entityName) {
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1906
|
+
const selectedFields = /* @__PURE__ */ new Set();
|
|
1907
|
+
const includes = {};
|
|
1908
|
+
let isPaged = false;
|
|
1909
|
+
let currentNode = chain;
|
|
1910
|
+
while (currentNode) {
|
|
1911
|
+
const methodName = currentNode.methodName;
|
|
1912
|
+
if (methodName === "select") {
|
|
1913
|
+
for (const arg of currentNode.arguments) {
|
|
1914
|
+
if (import_typescript9.default.isStringLiteral(arg)) {
|
|
1915
|
+
selectedFields.add(arg.text);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
} else if (methodName === "include") {
|
|
1919
|
+
parseIncludeArgument(currentNode.arguments[0], includes, checker, options, 0);
|
|
1920
|
+
} else if (methodName === "executePaged") {
|
|
1921
|
+
isPaged = true;
|
|
1922
|
+
}
|
|
1923
|
+
currentNode = currentNode.parent;
|
|
1924
|
+
}
|
|
1925
|
+
return {
|
|
1926
|
+
entityName,
|
|
1927
|
+
selectedFields: Array.from(selectedFields),
|
|
1928
|
+
includes,
|
|
1929
|
+
isPaged
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function findSelectFromEntityCall(chain) {
|
|
1933
|
+
let currentNode = chain;
|
|
1934
|
+
let lastNode = null;
|
|
1935
|
+
while (currentNode) {
|
|
1936
|
+
if (currentNode.methodName === "selectFromEntity" || currentNode.methodName === "selectFrom") {
|
|
1937
|
+
return currentNode;
|
|
1938
|
+
}
|
|
1939
|
+
lastNode = currentNode;
|
|
1940
|
+
currentNode = currentNode.parent;
|
|
1941
|
+
}
|
|
1942
|
+
return lastNode;
|
|
1943
|
+
}
|
|
1944
|
+
function extractEntityName(callNode, checker) {
|
|
1945
|
+
if (callNode.arguments.length === 0) {
|
|
1946
|
+
return null;
|
|
1947
|
+
}
|
|
1948
|
+
const entityArg = callNode.arguments[0];
|
|
1949
|
+
if (import_typescript9.default.isIdentifier(entityArg)) {
|
|
1950
|
+
return entityArg.text;
|
|
1951
|
+
}
|
|
1952
|
+
if (import_typescript9.default.isPropertyAccessExpression(entityArg)) {
|
|
1953
|
+
return entityArg.name.text;
|
|
1954
|
+
}
|
|
1955
|
+
return null;
|
|
1956
|
+
}
|
|
1957
|
+
function parseIncludeArgument(arg, includes, checker, options, depth) {
|
|
1958
|
+
if (!arg) {
|
|
1959
|
+
return;
|
|
1960
|
+
}
|
|
1961
|
+
if (import_typescript9.default.isObjectLiteralExpression(arg)) {
|
|
1962
|
+
for (const prop of arg.properties) {
|
|
1963
|
+
if (!import_typescript9.default.isPropertyAssignment(prop) || !import_typescript9.default.isIdentifier(prop.name)) {
|
|
1964
|
+
continue;
|
|
1965
|
+
}
|
|
1966
|
+
const relationName = prop.name.text;
|
|
1967
|
+
const value = prop.initializer;
|
|
1968
|
+
if (value.kind === import_typescript9.default.SyntaxKind.TrueKeyword) {
|
|
1969
|
+
includes[relationName] = true;
|
|
1970
|
+
} else if (import_typescript9.default.isObjectLiteralExpression(value)) {
|
|
1971
|
+
const maxDepth = options.maxDepth ?? 5;
|
|
1972
|
+
if (depth < maxDepth) {
|
|
1973
|
+
const nestedSchema = parseNestedInclude(value, depth + 1);
|
|
1974
|
+
if (nestedSchema) {
|
|
1975
|
+
includes[relationName] = nestedSchema;
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// src/compiler/schema/queryBuilderSchemaBuilder.ts
|
|
1984
|
+
var import_typescript10 = require("typescript");
|
|
1985
|
+
function wrapInPaginatedResult(schema) {
|
|
1986
|
+
return {
|
|
1987
|
+
type: "object",
|
|
1988
|
+
properties: {
|
|
1989
|
+
items: {
|
|
1990
|
+
type: "array",
|
|
1991
|
+
items: schema
|
|
1992
|
+
},
|
|
1993
|
+
page: { type: "integer" },
|
|
1994
|
+
pageSize: { type: "integer" },
|
|
1995
|
+
totalItems: { type: "integer" }
|
|
1996
|
+
},
|
|
1997
|
+
required: ["items", "page", "pageSize", "totalItems"]
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
|
|
1582
2001
|
// src/compiler/schema/openapi.ts
|
|
1583
2002
|
var METAL_ORM_WRAPPER_NAMES2 = ["BelongsToReference", "HasOneReference", "HasManyCollection", "ManyToManyCollection"];
|
|
1584
2003
|
function generateOpenAPI(controllers, checker, options = {}) {
|
|
@@ -1733,6 +2152,88 @@ function convertToOpenApiPath(basePath, path4) {
|
|
|
1733
2152
|
}
|
|
1734
2153
|
return fullPath;
|
|
1735
2154
|
}
|
|
2155
|
+
function tryInferQueryBuilderSchema(operation, checker) {
|
|
2156
|
+
return analyzeQueryBuilderForSchema(operation.methodDeclaration, checker) ?? null;
|
|
2157
|
+
}
|
|
2158
|
+
function getEntityTypeFromReturnType(operation, checker) {
|
|
2159
|
+
const returnType = operation.returnType;
|
|
2160
|
+
const unwrapPromise2 = (type) => {
|
|
2161
|
+
const symbol2 = type.getSymbol();
|
|
2162
|
+
if (symbol2?.getName() === "Promise") {
|
|
2163
|
+
const typeArgs = type.typeArguments;
|
|
2164
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
2165
|
+
return typeArgs[0];
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
return type;
|
|
2169
|
+
};
|
|
2170
|
+
const innerType = unwrapPromise2(returnType);
|
|
2171
|
+
const symbol = innerType.getSymbol();
|
|
2172
|
+
if (symbol?.getName() === "PaginatedResult") {
|
|
2173
|
+
const typeArgs = innerType.typeArguments;
|
|
2174
|
+
if (typeArgs && typeArgs.length > 0) {
|
|
2175
|
+
return typeArgs[0];
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
return null;
|
|
2179
|
+
}
|
|
2180
|
+
function filterSchemaByQueryBuilder(querySchema, operation, ctx) {
|
|
2181
|
+
const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
|
|
2182
|
+
if (!entityType) {
|
|
2183
|
+
return {};
|
|
2184
|
+
}
|
|
2185
|
+
const entitySchema = typeToJsonSchema(entityType, ctx);
|
|
2186
|
+
let baseSchema = entitySchema;
|
|
2187
|
+
if (entitySchema.$ref && entitySchema.$ref.startsWith("#/components/schemas/")) {
|
|
2188
|
+
const schemaName = entitySchema.$ref.replace("#/components/schemas/", "");
|
|
2189
|
+
const componentSchema = ctx.components.get(schemaName);
|
|
2190
|
+
if (componentSchema) {
|
|
2191
|
+
baseSchema = componentSchema;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
if (!baseSchema.properties || Object.keys(baseSchema.properties).length === 0) {
|
|
2195
|
+
return {};
|
|
2196
|
+
}
|
|
2197
|
+
const filteredSchema = buildFilteredSchema(querySchema, baseSchema);
|
|
2198
|
+
if (querySchema.isPaged) {
|
|
2199
|
+
return wrapInPaginatedResult(filteredSchema);
|
|
2200
|
+
}
|
|
2201
|
+
return filteredSchema;
|
|
2202
|
+
}
|
|
2203
|
+
function buildFilteredSchema(querySchema, entitySchema) {
|
|
2204
|
+
const properties = {};
|
|
2205
|
+
const required = [];
|
|
2206
|
+
for (const field of querySchema.selectedFields) {
|
|
2207
|
+
if (entitySchema.properties?.[field]) {
|
|
2208
|
+
properties[field] = entitySchema.properties[field];
|
|
2209
|
+
if (entitySchema.required && entitySchema.required.includes(field)) {
|
|
2210
|
+
required.push(field);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
for (const [relationName, includeSpec] of Object.entries(querySchema.includes)) {
|
|
2215
|
+
if (entitySchema.properties?.[relationName]) {
|
|
2216
|
+
properties[relationName] = {
|
|
2217
|
+
type: "object",
|
|
2218
|
+
properties: {
|
|
2219
|
+
id: { type: "integer" }
|
|
2220
|
+
},
|
|
2221
|
+
required: ["id"]
|
|
2222
|
+
};
|
|
2223
|
+
if (entitySchema.required && entitySchema.required.includes(relationName)) {
|
|
2224
|
+
required.push(relationName);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
const schema = {
|
|
2229
|
+
type: "object",
|
|
2230
|
+
properties
|
|
2231
|
+
};
|
|
2232
|
+
if (required.length > 0) {
|
|
2233
|
+
schema.required = required;
|
|
2234
|
+
}
|
|
2235
|
+
return schema;
|
|
2236
|
+
}
|
|
1736
2237
|
function buildOperation(operation, ctx, controllerConsumes) {
|
|
1737
2238
|
const op = {
|
|
1738
2239
|
operationId: operation.operationId,
|
|
@@ -1747,7 +2248,18 @@ function buildOperation(operation, ctx, controllerConsumes) {
|
|
|
1747
2248
|
op.parameters = parameters;
|
|
1748
2249
|
}
|
|
1749
2250
|
const responseCtx = { ...ctx, mode: "response" };
|
|
1750
|
-
|
|
2251
|
+
let responseSchema;
|
|
2252
|
+
const querySchema = tryInferQueryBuilderSchema(operation, ctx.checker);
|
|
2253
|
+
if (querySchema) {
|
|
2254
|
+
const entityType = getEntityTypeFromReturnType(operation, ctx.checker);
|
|
2255
|
+
if (entityType) {
|
|
2256
|
+
responseSchema = filterSchemaByQueryBuilder(querySchema, operation, responseCtx);
|
|
2257
|
+
} else {
|
|
2258
|
+
responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
|
|
2259
|
+
}
|
|
2260
|
+
} else {
|
|
2261
|
+
responseSchema = typeToJsonSchema(operation.returnType, responseCtx, operation.returnTypeNode);
|
|
2262
|
+
}
|
|
1751
2263
|
const status = operation.httpMethod === "POST" ? 201 : 200;
|
|
1752
2264
|
op.responses[status] = {
|
|
1753
2265
|
description: status === 201 ? "Created" : "OK",
|
|
@@ -1789,12 +2301,12 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
|
|
|
1789
2301
|
const declarations = typeSymbol.getDeclarations();
|
|
1790
2302
|
if (!declarations || declarations.length === 0) return schema;
|
|
1791
2303
|
const classDecl = declarations[0];
|
|
1792
|
-
if (!
|
|
2304
|
+
if (!import_typescript11.default.isClassDeclaration(classDecl)) return schema;
|
|
1793
2305
|
const result = { ...schema };
|
|
1794
2306
|
const props = { ...result.properties };
|
|
1795
2307
|
for (const member of classDecl.members) {
|
|
1796
|
-
if (!
|
|
1797
|
-
const propName =
|
|
2308
|
+
if (!import_typescript11.default.isPropertyDeclaration(member) || !member.name) continue;
|
|
2309
|
+
const propName = import_typescript11.default.isIdentifier(member.name) ? member.name.text : null;
|
|
1798
2310
|
if (!propName) continue;
|
|
1799
2311
|
if (!props[propName]) continue;
|
|
1800
2312
|
const frags = extractPropertySchemaFragments(ctx.checker, member);
|
|
@@ -1807,7 +2319,7 @@ function mergeBodySchemaAnnotations(bodyParam, ctx, schema) {
|
|
|
1807
2319
|
}
|
|
1808
2320
|
|
|
1809
2321
|
// src/compiler/manifest/emit.ts
|
|
1810
|
-
var
|
|
2322
|
+
var import_typescript12 = __toESM(require("typescript"), 1);
|
|
1811
2323
|
function generateManifest(controllers, checker, version, validationMode = "ajv-runtime") {
|
|
1812
2324
|
const components = /* @__PURE__ */ new Map();
|
|
1813
2325
|
const ctx = {
|
|
@@ -1829,7 +2341,7 @@ function generateManifest(controllers, checker, version, validationMode = "ajv-r
|
|
|
1829
2341
|
generator: {
|
|
1830
2342
|
name: "adorn-api",
|
|
1831
2343
|
version,
|
|
1832
|
-
typescript:
|
|
2344
|
+
typescript: import_typescript12.default.version
|
|
1833
2345
|
},
|
|
1834
2346
|
schemas: {
|
|
1835
2347
|
kind: "openapi-3.1",
|
|
@@ -2315,7 +2827,7 @@ async function isStale(params) {
|
|
|
2315
2827
|
// src/compiler/cache/writeCache.ts
|
|
2316
2828
|
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
2317
2829
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
2318
|
-
var
|
|
2830
|
+
var import_typescript13 = __toESM(require("typescript"), 1);
|
|
2319
2831
|
function statMtimeMs2(p) {
|
|
2320
2832
|
return import_node_fs4.default.statSync(p).mtimeMs;
|
|
2321
2833
|
}
|
|
@@ -2348,7 +2860,7 @@ function writeCache(params) {
|
|
|
2348
2860
|
generator: {
|
|
2349
2861
|
name: "adorn-api",
|
|
2350
2862
|
version: params.adornVersion,
|
|
2351
|
-
typescript:
|
|
2863
|
+
typescript: import_typescript13.default.version
|
|
2352
2864
|
},
|
|
2353
2865
|
project: {
|
|
2354
2866
|
tsconfigPath: params.tsconfigAbs,
|
|
@@ -3101,7 +3613,7 @@ function getEdgesByRelation(graph, relation) {
|
|
|
3101
3613
|
}
|
|
3102
3614
|
|
|
3103
3615
|
// src/compiler/graph/builder.ts
|
|
3104
|
-
var
|
|
3616
|
+
var import_typescript14 = __toESM(require("typescript"), 1);
|
|
3105
3617
|
|
|
3106
3618
|
// src/compiler/graph/schemaGraph.ts
|
|
3107
3619
|
var SchemaGraph = class {
|
|
@@ -3353,7 +3865,7 @@ var SchemaGraph = class {
|
|
|
3353
3865
|
};
|
|
3354
3866
|
|
|
3355
3867
|
// src/cli.ts
|
|
3356
|
-
var
|
|
3868
|
+
var import_typescript15 = __toESM(require("typescript"), 1);
|
|
3357
3869
|
var import_node_process2 = __toESM(require("process"), 1);
|
|
3358
3870
|
var import_meta2 = {};
|
|
3359
3871
|
var ADORN_VERSION = (() => {
|
|
@@ -3432,7 +3944,7 @@ function sanitizeForJson(obj) {
|
|
|
3432
3944
|
return result;
|
|
3433
3945
|
}
|
|
3434
3946
|
function buildControllerGraph(controllers) {
|
|
3435
|
-
const graph = createGraph(
|
|
3947
|
+
const graph = createGraph(import_typescript15.default.version);
|
|
3436
3948
|
const nodeMap = /* @__PURE__ */ new Map();
|
|
3437
3949
|
for (const ctrl of controllers) {
|
|
3438
3950
|
const nodeId = `Controller:${ctrl.className}`;
|
|
@@ -3543,7 +4055,7 @@ async function buildCommand(args) {
|
|
|
3543
4055
|
outDir: outputDir,
|
|
3544
4056
|
project: projectPath,
|
|
3545
4057
|
adornVersion: ADORN_VERSION,
|
|
3546
|
-
typescriptVersion:
|
|
4058
|
+
typescriptVersion: import_typescript15.default.version
|
|
3547
4059
|
});
|
|
3548
4060
|
if (!stale.stale) {
|
|
3549
4061
|
progress.completePhase("staleness-check");
|