metal-orm 1.0.80 → 1.0.81
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/index.cjs +402 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -23
- package/dist/index.d.ts +79 -23
- package/dist/index.js +401 -71
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/core/execution/db-executor.ts +5 -4
- package/src/core/execution/executors/mysql-executor.ts +9 -7
- package/src/openapi/index.ts +1 -0
- package/src/openapi/query-parameters.ts +206 -0
- package/src/openapi/schema-extractor.ts +290 -122
- package/src/openapi/schema-types.ts +72 -6
- package/src/openapi/type-mappers.ts +28 -8
- package/src/orm/unit-of-work.ts +25 -13
- package/src/query-builder/select.ts +17 -7
package/dist/index.js
CHANGED
|
@@ -6668,26 +6668,33 @@ var SelectRelationFacet = class {
|
|
|
6668
6668
|
};
|
|
6669
6669
|
|
|
6670
6670
|
// src/openapi/type-mappers.ts
|
|
6671
|
-
var mapColumnType = (column) => {
|
|
6671
|
+
var mapColumnType = (column, options = {}) => {
|
|
6672
|
+
const resolved = resolveColumnOptions(options);
|
|
6672
6673
|
const sqlType = normalizeType(column.type);
|
|
6673
6674
|
const baseSchema = mapSqlTypeToBaseSchema(sqlType, column);
|
|
6674
6675
|
const schema = {
|
|
6675
|
-
...baseSchema
|
|
6676
|
-
description: column.comment,
|
|
6677
|
-
nullable: !column.notNull && !column.primary
|
|
6676
|
+
...baseSchema
|
|
6678
6677
|
};
|
|
6679
|
-
if (
|
|
6678
|
+
if (resolved.includeDescriptions && column.comment) {
|
|
6679
|
+
schema.description = column.comment;
|
|
6680
|
+
}
|
|
6681
|
+
if (resolved.includeNullable) {
|
|
6682
|
+
schema.nullable = !column.notNull && !column.primary;
|
|
6683
|
+
}
|
|
6684
|
+
if ((sqlType === "varchar" || sqlType === "char") && column.args) {
|
|
6680
6685
|
schema.maxLength = column.args[0];
|
|
6681
6686
|
}
|
|
6682
|
-
if (
|
|
6687
|
+
if ((sqlType === "decimal" || sqlType === "float") && column.args) {
|
|
6683
6688
|
if (column.args.length >= 1) {
|
|
6684
6689
|
schema.minimum = -(10 ** column.args[0]);
|
|
6685
6690
|
}
|
|
6686
6691
|
}
|
|
6687
|
-
if (
|
|
6692
|
+
if (!resolved.includeEnums) {
|
|
6693
|
+
delete schema.enum;
|
|
6694
|
+
} else if (sqlType === "enum" && column.args && column.args.length > 0) {
|
|
6688
6695
|
schema.enum = column.args;
|
|
6689
6696
|
}
|
|
6690
|
-
if (column.default !== void 0) {
|
|
6697
|
+
if (resolved.includeDefaults && column.default !== void 0) {
|
|
6691
6698
|
schema.default = column.default;
|
|
6692
6699
|
}
|
|
6693
6700
|
return schema;
|
|
@@ -6803,6 +6810,13 @@ var inferTypeFromTsType = (tsType) => {
|
|
|
6803
6810
|
}
|
|
6804
6811
|
return "string";
|
|
6805
6812
|
};
|
|
6813
|
+
var resolveColumnOptions = (options) => ({
|
|
6814
|
+
includeDescriptions: options.includeDescriptions ?? false,
|
|
6815
|
+
includeEnums: options.includeEnums ?? true,
|
|
6816
|
+
includeExamples: options.includeExamples ?? false,
|
|
6817
|
+
includeDefaults: options.includeDefaults ?? true,
|
|
6818
|
+
includeNullable: options.includeNullable ?? true
|
|
6819
|
+
});
|
|
6806
6820
|
var mapRelationType = (relationType) => {
|
|
6807
6821
|
switch (relationType) {
|
|
6808
6822
|
case "HAS_MANY":
|
|
@@ -6830,14 +6844,55 @@ var getTemporalFormat = (sqlType) => {
|
|
|
6830
6844
|
};
|
|
6831
6845
|
|
|
6832
6846
|
// src/openapi/schema-extractor.ts
|
|
6847
|
+
var DEFAULT_MAX_DEPTH = 5;
|
|
6833
6848
|
var extractSchema = (table, plan, projectionNodes, options = {}) => {
|
|
6834
|
-
const
|
|
6835
|
-
const
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6849
|
+
const outputOptions = resolveOutputOptions(options);
|
|
6850
|
+
const outputContext = createContext(outputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
6851
|
+
const output = extractOutputSchema(table, plan, projectionNodes, outputContext, outputOptions);
|
|
6852
|
+
const inputOptions = resolveInputOptions(options);
|
|
6853
|
+
if (!inputOptions) {
|
|
6854
|
+
return { output };
|
|
6855
|
+
}
|
|
6856
|
+
const inputContext = createContext(inputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
6857
|
+
const input = extractInputSchema(table, inputContext, inputOptions);
|
|
6858
|
+
return { output, input };
|
|
6859
|
+
};
|
|
6860
|
+
var resolveOutputOptions = (options) => ({
|
|
6861
|
+
mode: options.mode ?? "full",
|
|
6862
|
+
includeDescriptions: options.includeDescriptions,
|
|
6863
|
+
includeEnums: options.includeEnums,
|
|
6864
|
+
includeExamples: options.includeExamples,
|
|
6865
|
+
includeDefaults: options.includeDefaults,
|
|
6866
|
+
includeNullable: options.includeNullable,
|
|
6867
|
+
maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH
|
|
6868
|
+
});
|
|
6869
|
+
var resolveInputOptions = (options) => {
|
|
6870
|
+
if (options.input === false) return void 0;
|
|
6871
|
+
const input = options.input ?? {};
|
|
6872
|
+
const mode = input.mode ?? "create";
|
|
6873
|
+
return {
|
|
6874
|
+
mode,
|
|
6875
|
+
includeRelations: input.includeRelations ?? true,
|
|
6876
|
+
relationMode: input.relationMode ?? "mixed",
|
|
6877
|
+
includeDescriptions: input.includeDescriptions ?? options.includeDescriptions,
|
|
6878
|
+
includeEnums: input.includeEnums ?? options.includeEnums,
|
|
6879
|
+
includeExamples: input.includeExamples ?? options.includeExamples,
|
|
6880
|
+
includeDefaults: input.includeDefaults ?? options.includeDefaults,
|
|
6881
|
+
includeNullable: input.includeNullable ?? options.includeNullable,
|
|
6882
|
+
maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
6883
|
+
omitReadOnly: input.omitReadOnly ?? true,
|
|
6884
|
+
excludePrimaryKey: input.excludePrimaryKey ?? false,
|
|
6885
|
+
requirePrimaryKey: input.requirePrimaryKey ?? mode === "update"
|
|
6840
6886
|
};
|
|
6887
|
+
};
|
|
6888
|
+
var createContext = (maxDepth) => ({
|
|
6889
|
+
visitedTables: /* @__PURE__ */ new Set(),
|
|
6890
|
+
schemaCache: /* @__PURE__ */ new Map(),
|
|
6891
|
+
depth: 0,
|
|
6892
|
+
maxDepth
|
|
6893
|
+
});
|
|
6894
|
+
var extractOutputSchema = (table, plan, projectionNodes, context, options) => {
|
|
6895
|
+
const mode = options.mode ?? "full";
|
|
6841
6896
|
const hasComputedFields = projectionNodes && projectionNodes.some(
|
|
6842
6897
|
(node) => node.type !== "Column"
|
|
6843
6898
|
);
|
|
@@ -6849,9 +6904,97 @@ var extractSchema = (table, plan, projectionNodes, options = {}) => {
|
|
|
6849
6904
|
}
|
|
6850
6905
|
return extractFullTableSchema(table, context, options);
|
|
6851
6906
|
};
|
|
6907
|
+
var extractInputSchema = (table, context, options) => {
|
|
6908
|
+
const cacheKey = `${table.name}:${options.mode ?? "create"}`;
|
|
6909
|
+
if (context.schemaCache.has(cacheKey)) {
|
|
6910
|
+
return context.schemaCache.get(cacheKey);
|
|
6911
|
+
}
|
|
6912
|
+
if (context.visitedTables.has(cacheKey) && context.depth > 0) {
|
|
6913
|
+
return buildCircularReferenceSchema(table.name, "input");
|
|
6914
|
+
}
|
|
6915
|
+
context.visitedTables.add(cacheKey);
|
|
6916
|
+
const properties = {};
|
|
6917
|
+
const required = [];
|
|
6918
|
+
const primaryKey = findPrimaryKey(table);
|
|
6919
|
+
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
6920
|
+
const isPrimary = columnName === primaryKey || column.primary;
|
|
6921
|
+
if (options.excludePrimaryKey && isPrimary) continue;
|
|
6922
|
+
if (options.omitReadOnly && isReadOnlyColumn(column)) continue;
|
|
6923
|
+
properties[columnName] = mapColumnType(column, options);
|
|
6924
|
+
if (options.mode === "create" && isRequiredForCreate(column)) {
|
|
6925
|
+
required.push(columnName);
|
|
6926
|
+
}
|
|
6927
|
+
if (options.mode === "update" && options.requirePrimaryKey && isPrimary) {
|
|
6928
|
+
required.push(columnName);
|
|
6929
|
+
}
|
|
6930
|
+
}
|
|
6931
|
+
if (options.includeRelations && context.depth < context.maxDepth) {
|
|
6932
|
+
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
6933
|
+
properties[relationName] = extractInputRelationSchema(
|
|
6934
|
+
relation,
|
|
6935
|
+
{ ...context, depth: context.depth + 1 },
|
|
6936
|
+
options
|
|
6937
|
+
);
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
const schema = {
|
|
6941
|
+
type: "object",
|
|
6942
|
+
properties,
|
|
6943
|
+
required
|
|
6944
|
+
};
|
|
6945
|
+
context.schemaCache.set(cacheKey, schema);
|
|
6946
|
+
return schema;
|
|
6947
|
+
};
|
|
6948
|
+
var isReadOnlyColumn = (column) => Boolean(column.autoIncrement || column.generated === "always");
|
|
6949
|
+
var isRequiredForCreate = (column) => {
|
|
6950
|
+
if (isReadOnlyColumn(column)) return false;
|
|
6951
|
+
if (column.default !== void 0) return false;
|
|
6952
|
+
return Boolean(column.notNull || column.primary);
|
|
6953
|
+
};
|
|
6954
|
+
var buildPrimaryKeySchema = (table, options) => {
|
|
6955
|
+
const primaryKey = findPrimaryKey(table);
|
|
6956
|
+
const column = table.columns[primaryKey];
|
|
6957
|
+
if (!column) {
|
|
6958
|
+
return {
|
|
6959
|
+
anyOf: [
|
|
6960
|
+
{ type: "string" },
|
|
6961
|
+
{ type: "number" },
|
|
6962
|
+
{ type: "integer" }
|
|
6963
|
+
]
|
|
6964
|
+
};
|
|
6965
|
+
}
|
|
6966
|
+
return mapColumnType(column, options);
|
|
6967
|
+
};
|
|
6968
|
+
var extractInputRelationSchema = (relation, context, options) => {
|
|
6969
|
+
const { type: relationType, isNullable } = mapRelationType(relation.type);
|
|
6970
|
+
const relationMode = options.relationMode ?? "mixed";
|
|
6971
|
+
const allowIds = relationMode !== "objects";
|
|
6972
|
+
const allowObjects = relationMode !== "ids";
|
|
6973
|
+
const variants = [];
|
|
6974
|
+
if (allowIds) {
|
|
6975
|
+
variants.push(buildPrimaryKeySchema(relation.target, options));
|
|
6976
|
+
}
|
|
6977
|
+
if (allowObjects) {
|
|
6978
|
+
const targetSchema = extractInputSchema(relation.target, context, options);
|
|
6979
|
+
variants.push(targetSchema);
|
|
6980
|
+
}
|
|
6981
|
+
const itemSchema = variants.length === 1 ? variants[0] : { anyOf: variants };
|
|
6982
|
+
if (relationType === "array") {
|
|
6983
|
+
return {
|
|
6984
|
+
type: "array",
|
|
6985
|
+
items: itemSchema,
|
|
6986
|
+
nullable: isNullable
|
|
6987
|
+
};
|
|
6988
|
+
}
|
|
6989
|
+
return {
|
|
6990
|
+
...itemSchema,
|
|
6991
|
+
nullable: isNullable
|
|
6992
|
+
};
|
|
6993
|
+
};
|
|
6852
6994
|
var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
6853
6995
|
const properties = {};
|
|
6854
6996
|
const required = [];
|
|
6997
|
+
const includeDescriptions = Boolean(options.includeDescriptions);
|
|
6855
6998
|
for (const node of projectionNodes) {
|
|
6856
6999
|
if (!node || typeof node !== "object") continue;
|
|
6857
7000
|
const projection = node;
|
|
@@ -6861,10 +7004,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
6861
7004
|
const columnNode4 = node;
|
|
6862
7005
|
const column = table.columns[columnNode4.name];
|
|
6863
7006
|
if (!column) continue;
|
|
6864
|
-
const property = mapColumnType(column);
|
|
6865
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
6866
|
-
property.description = column.comment;
|
|
6867
|
-
}
|
|
7007
|
+
const property = mapColumnType(column, options);
|
|
6868
7008
|
properties[propertyName] = property;
|
|
6869
7009
|
if (column.notNull || column.primary) {
|
|
6870
7010
|
required.push(propertyName);
|
|
@@ -6872,7 +7012,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
6872
7012
|
} else if (projection.type === "Function" || projection.type === "WindowFunction") {
|
|
6873
7013
|
const fnNode = node;
|
|
6874
7014
|
const functionName = fnNode.fn?.toUpperCase() ?? fnNode.name?.toUpperCase() ?? "";
|
|
6875
|
-
const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName) : mapWindowFunctionToSchema(functionName);
|
|
7015
|
+
const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName, includeDescriptions) : mapWindowFunctionToSchema(functionName, includeDescriptions);
|
|
6876
7016
|
properties[propertyName] = propertySchema;
|
|
6877
7017
|
const isCountFunction = functionName === "COUNT";
|
|
6878
7018
|
const isWindowRankFunction = functionName === "ROW_NUMBER" || functionName === "RANK";
|
|
@@ -6882,23 +7022,29 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
6882
7022
|
} else if (projection.type === "CaseExpression") {
|
|
6883
7023
|
const propertySchema = {
|
|
6884
7024
|
type: "string",
|
|
6885
|
-
description: "Computed CASE expression",
|
|
6886
7025
|
nullable: true
|
|
6887
7026
|
};
|
|
7027
|
+
if (includeDescriptions) {
|
|
7028
|
+
propertySchema.description = "Computed CASE expression";
|
|
7029
|
+
}
|
|
6888
7030
|
properties[propertyName] = propertySchema;
|
|
6889
7031
|
} else if (projection.type === "ScalarSubquery") {
|
|
6890
7032
|
const propertySchema = {
|
|
6891
7033
|
type: "object",
|
|
6892
|
-
description: "Subquery result",
|
|
6893
7034
|
nullable: true
|
|
6894
7035
|
};
|
|
7036
|
+
if (includeDescriptions) {
|
|
7037
|
+
propertySchema.description = "Subquery result";
|
|
7038
|
+
}
|
|
6895
7039
|
properties[propertyName] = propertySchema;
|
|
6896
7040
|
} else if (projection.type === "CastExpression") {
|
|
6897
7041
|
const propertySchema = {
|
|
6898
7042
|
type: "string",
|
|
6899
|
-
description: "CAST expression result",
|
|
6900
7043
|
nullable: true
|
|
6901
7044
|
};
|
|
7045
|
+
if (includeDescriptions) {
|
|
7046
|
+
propertySchema.description = "CAST expression result";
|
|
7047
|
+
}
|
|
6902
7048
|
properties[propertyName] = propertySchema;
|
|
6903
7049
|
}
|
|
6904
7050
|
}
|
|
@@ -6908,7 +7054,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
6908
7054
|
required
|
|
6909
7055
|
};
|
|
6910
7056
|
};
|
|
6911
|
-
var mapFunctionNodeToSchema = (functionName) => {
|
|
7057
|
+
var mapFunctionNodeToSchema = (functionName, includeDescriptions) => {
|
|
6912
7058
|
const upperName = functionName.toUpperCase();
|
|
6913
7059
|
switch (upperName) {
|
|
6914
7060
|
case "COUNT":
|
|
@@ -6916,74 +7062,69 @@ var mapFunctionNodeToSchema = (functionName) => {
|
|
|
6916
7062
|
case "AVG":
|
|
6917
7063
|
case "MIN":
|
|
6918
7064
|
case "MAX":
|
|
6919
|
-
return {
|
|
7065
|
+
return withOptionalDescription({
|
|
6920
7066
|
type: "number",
|
|
6921
|
-
description: `${upperName} aggregate function result`,
|
|
6922
7067
|
nullable: false
|
|
6923
|
-
};
|
|
7068
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
6924
7069
|
case "GROUP_CONCAT":
|
|
6925
7070
|
case "STRING_AGG":
|
|
6926
7071
|
case "ARRAY_AGG":
|
|
6927
|
-
return {
|
|
7072
|
+
return withOptionalDescription({
|
|
6928
7073
|
type: "string",
|
|
6929
|
-
description: `${upperName} aggregate function result`,
|
|
6930
7074
|
nullable: true
|
|
6931
|
-
};
|
|
7075
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
6932
7076
|
case "JSON_ARRAYAGG":
|
|
6933
7077
|
case "JSON_OBJECTAGG":
|
|
6934
|
-
return {
|
|
7078
|
+
return withOptionalDescription({
|
|
6935
7079
|
type: "object",
|
|
6936
|
-
description: `${upperName} aggregate function result`,
|
|
6937
7080
|
nullable: true
|
|
6938
|
-
};
|
|
7081
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
6939
7082
|
default:
|
|
6940
|
-
return {
|
|
7083
|
+
return withOptionalDescription({
|
|
6941
7084
|
type: "string",
|
|
6942
|
-
description: `Unknown function: ${functionName}`,
|
|
6943
7085
|
nullable: true
|
|
6944
|
-
};
|
|
7086
|
+
}, includeDescriptions, `Unknown function: ${functionName}`);
|
|
6945
7087
|
}
|
|
6946
7088
|
};
|
|
6947
|
-
var mapWindowFunctionToSchema = (functionName) => {
|
|
7089
|
+
var mapWindowFunctionToSchema = (functionName, includeDescriptions) => {
|
|
6948
7090
|
const upperName = functionName.toUpperCase();
|
|
6949
7091
|
switch (upperName) {
|
|
6950
7092
|
case "ROW_NUMBER":
|
|
6951
7093
|
case "RANK":
|
|
6952
7094
|
case "DENSE_RANK":
|
|
6953
7095
|
case "NTILE":
|
|
6954
|
-
return {
|
|
7096
|
+
return withOptionalDescription({
|
|
6955
7097
|
type: "integer",
|
|
6956
|
-
description: `${upperName} window function result`,
|
|
6957
7098
|
nullable: false
|
|
6958
|
-
};
|
|
7099
|
+
}, includeDescriptions, `${upperName} window function result`);
|
|
6959
7100
|
case "LAG":
|
|
6960
7101
|
case "LEAD":
|
|
6961
7102
|
case "FIRST_VALUE":
|
|
6962
7103
|
case "LAST_VALUE":
|
|
6963
|
-
return {
|
|
7104
|
+
return withOptionalDescription({
|
|
6964
7105
|
type: "string",
|
|
6965
|
-
description: `${upperName} window function result`,
|
|
6966
7106
|
nullable: true
|
|
6967
|
-
};
|
|
7107
|
+
}, includeDescriptions, `${upperName} window function result`);
|
|
6968
7108
|
default:
|
|
6969
|
-
return {
|
|
7109
|
+
return withOptionalDescription({
|
|
6970
7110
|
type: "string",
|
|
6971
|
-
description: `Unknown window function: ${functionName}`,
|
|
6972
7111
|
nullable: true
|
|
6973
|
-
};
|
|
7112
|
+
}, includeDescriptions, `Unknown window function: ${functionName}`);
|
|
6974
7113
|
}
|
|
6975
7114
|
};
|
|
7115
|
+
var withOptionalDescription = (schema, includeDescriptions, description) => {
|
|
7116
|
+
if (includeDescriptions) {
|
|
7117
|
+
return { ...schema, description };
|
|
7118
|
+
}
|
|
7119
|
+
return schema;
|
|
7120
|
+
};
|
|
6976
7121
|
var extractSelectedSchema = (table, plan, context, options) => {
|
|
6977
7122
|
const properties = {};
|
|
6978
7123
|
const required = [];
|
|
6979
7124
|
plan.rootColumns.forEach((columnName) => {
|
|
6980
7125
|
const column = table.columns[columnName];
|
|
6981
7126
|
if (!column) return;
|
|
6982
|
-
|
|
6983
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
6984
|
-
property.description = column.comment;
|
|
6985
|
-
}
|
|
6986
|
-
properties[columnName] = property;
|
|
7127
|
+
properties[columnName] = mapColumnType(column, options);
|
|
6987
7128
|
if (column.notNull || column.primary) {
|
|
6988
7129
|
required.push(columnName);
|
|
6989
7130
|
}
|
|
@@ -7016,26 +7157,13 @@ var extractFullTableSchema = (table, context, options) => {
|
|
|
7016
7157
|
return context.schemaCache.get(cacheKey);
|
|
7017
7158
|
}
|
|
7018
7159
|
if (context.visitedTables.has(cacheKey) && context.depth > 0) {
|
|
7019
|
-
return
|
|
7020
|
-
type: "object",
|
|
7021
|
-
properties: {
|
|
7022
|
-
_ref: {
|
|
7023
|
-
type: "string",
|
|
7024
|
-
description: `Circular reference to ${table.name}`
|
|
7025
|
-
}
|
|
7026
|
-
},
|
|
7027
|
-
required: []
|
|
7028
|
-
};
|
|
7160
|
+
return buildCircularReferenceSchema(table.name, "output");
|
|
7029
7161
|
}
|
|
7030
7162
|
context.visitedTables.add(cacheKey);
|
|
7031
7163
|
const properties = {};
|
|
7032
7164
|
const required = [];
|
|
7033
7165
|
Object.entries(table.columns).forEach(([columnName, column]) => {
|
|
7034
|
-
|
|
7035
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
7036
|
-
property.description = column.comment;
|
|
7037
|
-
}
|
|
7038
|
-
properties[columnName] = property;
|
|
7166
|
+
properties[columnName] = mapColumnType(column, options);
|
|
7039
7167
|
if (column.notNull || column.primary) {
|
|
7040
7168
|
required.push(columnName);
|
|
7041
7169
|
}
|
|
@@ -7095,10 +7223,188 @@ var extractRelationSchema = (relation, relationPlan, selectedColumns, context, o
|
|
|
7095
7223
|
description: targetSchema.description
|
|
7096
7224
|
};
|
|
7097
7225
|
};
|
|
7226
|
+
var buildCircularReferenceSchema = (tableName, kind) => ({
|
|
7227
|
+
type: "object",
|
|
7228
|
+
properties: {
|
|
7229
|
+
_ref: {
|
|
7230
|
+
type: "string",
|
|
7231
|
+
description: `Circular ${kind} reference to ${tableName}`
|
|
7232
|
+
}
|
|
7233
|
+
},
|
|
7234
|
+
required: []
|
|
7235
|
+
});
|
|
7098
7236
|
var schemaToJson = (schema, pretty = false) => {
|
|
7099
7237
|
return JSON.stringify(schema, null, pretty ? 2 : 0);
|
|
7100
7238
|
};
|
|
7101
7239
|
|
|
7240
|
+
// src/openapi/query-parameters.ts
|
|
7241
|
+
var FILTER_PARAM_NAME = "filter";
|
|
7242
|
+
var buildRootTableNames = (table, from) => {
|
|
7243
|
+
const names = /* @__PURE__ */ new Set([table.name]);
|
|
7244
|
+
if (from?.type === "Table") {
|
|
7245
|
+
names.add(from.name);
|
|
7246
|
+
if (from.alias) names.add(from.alias);
|
|
7247
|
+
}
|
|
7248
|
+
return names;
|
|
7249
|
+
};
|
|
7250
|
+
var collectFilterColumns = (expr, table, rootTables) => {
|
|
7251
|
+
const columns = /* @__PURE__ */ new Set();
|
|
7252
|
+
const recordColumn = (node) => {
|
|
7253
|
+
if (!rootTables.has(node.table)) return;
|
|
7254
|
+
if (node.name in table.columns) {
|
|
7255
|
+
columns.add(node.name);
|
|
7256
|
+
}
|
|
7257
|
+
};
|
|
7258
|
+
const visitOrderingTerm = (term) => {
|
|
7259
|
+
if (!term || typeof term !== "object") return;
|
|
7260
|
+
if (isOperandNode(term)) {
|
|
7261
|
+
visitOperand2(term);
|
|
7262
|
+
return;
|
|
7263
|
+
}
|
|
7264
|
+
if ("type" in term) {
|
|
7265
|
+
visitExpression2(term);
|
|
7266
|
+
}
|
|
7267
|
+
};
|
|
7268
|
+
const visitOrderBy = (orderBy) => {
|
|
7269
|
+
if (!orderBy) return;
|
|
7270
|
+
orderBy.forEach((node) => visitOrderingTerm(node.term));
|
|
7271
|
+
};
|
|
7272
|
+
const visitOperand2 = (node) => {
|
|
7273
|
+
switch (node.type) {
|
|
7274
|
+
case "Column":
|
|
7275
|
+
recordColumn(node);
|
|
7276
|
+
return;
|
|
7277
|
+
case "Function": {
|
|
7278
|
+
const fn8 = node;
|
|
7279
|
+
fn8.args?.forEach(visitOperand2);
|
|
7280
|
+
visitOrderBy(fn8.orderBy);
|
|
7281
|
+
if (fn8.separator) visitOperand2(fn8.separator);
|
|
7282
|
+
return;
|
|
7283
|
+
}
|
|
7284
|
+
case "JsonPath": {
|
|
7285
|
+
const jp = node;
|
|
7286
|
+
recordColumn(jp.column);
|
|
7287
|
+
return;
|
|
7288
|
+
}
|
|
7289
|
+
case "ScalarSubquery":
|
|
7290
|
+
return;
|
|
7291
|
+
case "CaseExpression": {
|
|
7292
|
+
const cs = node;
|
|
7293
|
+
cs.conditions.forEach((condition) => {
|
|
7294
|
+
visitExpression2(condition.when);
|
|
7295
|
+
visitOperand2(condition.then);
|
|
7296
|
+
});
|
|
7297
|
+
if (cs.else) visitOperand2(cs.else);
|
|
7298
|
+
return;
|
|
7299
|
+
}
|
|
7300
|
+
case "Cast": {
|
|
7301
|
+
const cast2 = node;
|
|
7302
|
+
visitOperand2(cast2.expression);
|
|
7303
|
+
return;
|
|
7304
|
+
}
|
|
7305
|
+
case "WindowFunction": {
|
|
7306
|
+
const windowFn = node;
|
|
7307
|
+
windowFn.args?.forEach(visitOperand2);
|
|
7308
|
+
windowFn.partitionBy?.forEach(recordColumn);
|
|
7309
|
+
visitOrderBy(windowFn.orderBy);
|
|
7310
|
+
return;
|
|
7311
|
+
}
|
|
7312
|
+
case "ArithmeticExpression": {
|
|
7313
|
+
const arith = node;
|
|
7314
|
+
visitOperand2(arith.left);
|
|
7315
|
+
visitOperand2(arith.right);
|
|
7316
|
+
return;
|
|
7317
|
+
}
|
|
7318
|
+
case "BitwiseExpression": {
|
|
7319
|
+
const bitwise = node;
|
|
7320
|
+
visitOperand2(bitwise.left);
|
|
7321
|
+
visitOperand2(bitwise.right);
|
|
7322
|
+
return;
|
|
7323
|
+
}
|
|
7324
|
+
case "Collate": {
|
|
7325
|
+
const collate2 = node;
|
|
7326
|
+
visitOperand2(collate2.expression);
|
|
7327
|
+
return;
|
|
7328
|
+
}
|
|
7329
|
+
case "AliasRef":
|
|
7330
|
+
case "Literal":
|
|
7331
|
+
return;
|
|
7332
|
+
default:
|
|
7333
|
+
return;
|
|
7334
|
+
}
|
|
7335
|
+
};
|
|
7336
|
+
const visitExpression2 = (node) => {
|
|
7337
|
+
switch (node.type) {
|
|
7338
|
+
case "BinaryExpression":
|
|
7339
|
+
visitOperand2(node.left);
|
|
7340
|
+
visitOperand2(node.right);
|
|
7341
|
+
if (node.escape) visitOperand2(node.escape);
|
|
7342
|
+
return;
|
|
7343
|
+
case "LogicalExpression":
|
|
7344
|
+
node.operands.forEach(visitExpression2);
|
|
7345
|
+
return;
|
|
7346
|
+
case "NullExpression":
|
|
7347
|
+
visitOperand2(node.left);
|
|
7348
|
+
return;
|
|
7349
|
+
case "InExpression":
|
|
7350
|
+
visitOperand2(node.left);
|
|
7351
|
+
if (Array.isArray(node.right)) {
|
|
7352
|
+
node.right.forEach(visitOperand2);
|
|
7353
|
+
}
|
|
7354
|
+
return;
|
|
7355
|
+
case "ExistsExpression":
|
|
7356
|
+
return;
|
|
7357
|
+
case "BetweenExpression":
|
|
7358
|
+
visitOperand2(node.left);
|
|
7359
|
+
visitOperand2(node.lower);
|
|
7360
|
+
visitOperand2(node.upper);
|
|
7361
|
+
return;
|
|
7362
|
+
case "ArithmeticExpression":
|
|
7363
|
+
visitOperand2(node.left);
|
|
7364
|
+
visitOperand2(node.right);
|
|
7365
|
+
return;
|
|
7366
|
+
case "BitwiseExpression":
|
|
7367
|
+
visitOperand2(node.left);
|
|
7368
|
+
visitOperand2(node.right);
|
|
7369
|
+
return;
|
|
7370
|
+
default:
|
|
7371
|
+
return;
|
|
7372
|
+
}
|
|
7373
|
+
};
|
|
7374
|
+
visitExpression2(expr);
|
|
7375
|
+
return columns;
|
|
7376
|
+
};
|
|
7377
|
+
var buildFilterParameters = (table, where, from, options = {}) => {
|
|
7378
|
+
if (!where) return [];
|
|
7379
|
+
const rootTables = buildRootTableNames(table, from);
|
|
7380
|
+
const columnNames = collectFilterColumns(where, table, rootTables);
|
|
7381
|
+
let schema;
|
|
7382
|
+
if (columnNames.size) {
|
|
7383
|
+
const properties = {};
|
|
7384
|
+
for (const name of columnNames) {
|
|
7385
|
+
const column = table.columns[name];
|
|
7386
|
+
if (!column) continue;
|
|
7387
|
+
properties[name] = mapColumnType(column, options);
|
|
7388
|
+
}
|
|
7389
|
+
schema = {
|
|
7390
|
+
type: "object",
|
|
7391
|
+
properties
|
|
7392
|
+
};
|
|
7393
|
+
} else {
|
|
7394
|
+
schema = {
|
|
7395
|
+
type: "object",
|
|
7396
|
+
additionalProperties: true
|
|
7397
|
+
};
|
|
7398
|
+
}
|
|
7399
|
+
return [{
|
|
7400
|
+
name: FILTER_PARAM_NAME,
|
|
7401
|
+
in: "query",
|
|
7402
|
+
style: "deepObject",
|
|
7403
|
+
explode: true,
|
|
7404
|
+
schema
|
|
7405
|
+
}];
|
|
7406
|
+
};
|
|
7407
|
+
|
|
7102
7408
|
// src/query-builder/select.ts
|
|
7103
7409
|
var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
7104
7410
|
env;
|
|
@@ -7918,16 +8224,26 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
7918
8224
|
return this.context.hydration.getPlan();
|
|
7919
8225
|
}
|
|
7920
8226
|
/**
|
|
7921
|
-
* Gets OpenAPI 3.1 JSON
|
|
8227
|
+
* Gets OpenAPI 3.1 JSON Schemas for query output and optional input payloads
|
|
7922
8228
|
* @param options - Schema generation options
|
|
7923
|
-
* @returns OpenAPI 3.1 JSON
|
|
8229
|
+
* @returns OpenAPI 3.1 JSON Schemas for query output and input payloads
|
|
7924
8230
|
* @example
|
|
7925
|
-
* const
|
|
7926
|
-
* console.log(JSON.stringify(
|
|
8231
|
+
* const { output } = qb.select('id', 'title', 'author').getSchema();
|
|
8232
|
+
* console.log(JSON.stringify(output, null, 2));
|
|
7927
8233
|
*/
|
|
7928
8234
|
getSchema(options) {
|
|
7929
8235
|
const plan = this.context.hydration.getPlan();
|
|
7930
|
-
|
|
8236
|
+
const bundle = extractSchema(this.env.table, plan, this.context.state.ast.columns, options);
|
|
8237
|
+
const parameters = buildFilterParameters(
|
|
8238
|
+
this.env.table,
|
|
8239
|
+
this.context.state.ast.where,
|
|
8240
|
+
this.context.state.ast.from,
|
|
8241
|
+
options ?? {}
|
|
8242
|
+
);
|
|
8243
|
+
if (parameters.length) {
|
|
8244
|
+
return { ...bundle, parameters };
|
|
8245
|
+
}
|
|
8246
|
+
return bundle;
|
|
7931
8247
|
}
|
|
7932
8248
|
/**
|
|
7933
8249
|
* Gets the Abstract Syntax Tree (AST) representation of the query
|
|
@@ -11544,6 +11860,7 @@ var UnitOfWork = class {
|
|
|
11544
11860
|
const compiled = builder.compile(this.dialect);
|
|
11545
11861
|
const results = await this.executeCompiled(compiled);
|
|
11546
11862
|
this.applyReturningResults(tracked, results);
|
|
11863
|
+
this.applyInsertId(tracked, results);
|
|
11547
11864
|
tracked.status = "managed" /* Managed */;
|
|
11548
11865
|
tracked.original = this.createSnapshot(tracked.table, tracked.entity);
|
|
11549
11866
|
tracked.pk = this.getPrimaryKeyValue(tracked);
|
|
@@ -11669,6 +11986,16 @@ var UnitOfWork = class {
|
|
|
11669
11986
|
tracked.entity[columnName] = row[i];
|
|
11670
11987
|
}
|
|
11671
11988
|
}
|
|
11989
|
+
applyInsertId(tracked, results) {
|
|
11990
|
+
if (this.dialect.supportsReturning()) return;
|
|
11991
|
+
if (tracked.pk != null) return;
|
|
11992
|
+
const pkName = findPrimaryKey(tracked.table);
|
|
11993
|
+
const pkColumn = tracked.table.columns[pkName];
|
|
11994
|
+
if (!pkColumn?.autoIncrement) return;
|
|
11995
|
+
const insertId = results.find((result) => typeof result.insertId === "number")?.insertId;
|
|
11996
|
+
if (insertId == null) return;
|
|
11997
|
+
tracked.entity[pkName] = insertId;
|
|
11998
|
+
}
|
|
11672
11999
|
/**
|
|
11673
12000
|
* Normalizes a column name by removing quotes and table prefixes.
|
|
11674
12001
|
* @param column - The column name to normalize
|
|
@@ -13185,7 +13512,9 @@ function createMysqlExecutor(client) {
|
|
|
13185
13512
|
async executeSql(sql, params) {
|
|
13186
13513
|
const [rows] = await client.query(sql, params);
|
|
13187
13514
|
if (!Array.isArray(rows)) {
|
|
13188
|
-
|
|
13515
|
+
const insertId = rows?.insertId;
|
|
13516
|
+
const normalized = typeof insertId === "number" && insertId > 0 ? insertId : void 0;
|
|
13517
|
+
return [{ columns: [], values: [], insertId: normalized }];
|
|
13189
13518
|
}
|
|
13190
13519
|
const result = rowsToQueryResult(
|
|
13191
13520
|
rows
|
|
@@ -13483,6 +13812,7 @@ export {
|
|
|
13483
13812
|
bitOr,
|
|
13484
13813
|
bitXor,
|
|
13485
13814
|
bootstrapEntities,
|
|
13815
|
+
buildFilterParameters,
|
|
13486
13816
|
caseWhen,
|
|
13487
13817
|
cast,
|
|
13488
13818
|
cbrt,
|