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.cjs
CHANGED
|
@@ -96,6 +96,7 @@ __export(index_exports, {
|
|
|
96
96
|
bitOr: () => bitOr,
|
|
97
97
|
bitXor: () => bitXor,
|
|
98
98
|
bootstrapEntities: () => bootstrapEntities,
|
|
99
|
+
buildFilterParameters: () => buildFilterParameters,
|
|
99
100
|
caseWhen: () => caseWhen,
|
|
100
101
|
cast: () => cast,
|
|
101
102
|
cbrt: () => cbrt,
|
|
@@ -6950,26 +6951,33 @@ var SelectRelationFacet = class {
|
|
|
6950
6951
|
};
|
|
6951
6952
|
|
|
6952
6953
|
// src/openapi/type-mappers.ts
|
|
6953
|
-
var mapColumnType = (column) => {
|
|
6954
|
+
var mapColumnType = (column, options = {}) => {
|
|
6955
|
+
const resolved = resolveColumnOptions(options);
|
|
6954
6956
|
const sqlType = normalizeType(column.type);
|
|
6955
6957
|
const baseSchema = mapSqlTypeToBaseSchema(sqlType, column);
|
|
6956
6958
|
const schema = {
|
|
6957
|
-
...baseSchema
|
|
6958
|
-
description: column.comment,
|
|
6959
|
-
nullable: !column.notNull && !column.primary
|
|
6959
|
+
...baseSchema
|
|
6960
6960
|
};
|
|
6961
|
-
if (
|
|
6961
|
+
if (resolved.includeDescriptions && column.comment) {
|
|
6962
|
+
schema.description = column.comment;
|
|
6963
|
+
}
|
|
6964
|
+
if (resolved.includeNullable) {
|
|
6965
|
+
schema.nullable = !column.notNull && !column.primary;
|
|
6966
|
+
}
|
|
6967
|
+
if ((sqlType === "varchar" || sqlType === "char") && column.args) {
|
|
6962
6968
|
schema.maxLength = column.args[0];
|
|
6963
6969
|
}
|
|
6964
|
-
if (
|
|
6970
|
+
if ((sqlType === "decimal" || sqlType === "float") && column.args) {
|
|
6965
6971
|
if (column.args.length >= 1) {
|
|
6966
6972
|
schema.minimum = -(10 ** column.args[0]);
|
|
6967
6973
|
}
|
|
6968
6974
|
}
|
|
6969
|
-
if (
|
|
6975
|
+
if (!resolved.includeEnums) {
|
|
6976
|
+
delete schema.enum;
|
|
6977
|
+
} else if (sqlType === "enum" && column.args && column.args.length > 0) {
|
|
6970
6978
|
schema.enum = column.args;
|
|
6971
6979
|
}
|
|
6972
|
-
if (column.default !== void 0) {
|
|
6980
|
+
if (resolved.includeDefaults && column.default !== void 0) {
|
|
6973
6981
|
schema.default = column.default;
|
|
6974
6982
|
}
|
|
6975
6983
|
return schema;
|
|
@@ -7085,6 +7093,13 @@ var inferTypeFromTsType = (tsType) => {
|
|
|
7085
7093
|
}
|
|
7086
7094
|
return "string";
|
|
7087
7095
|
};
|
|
7096
|
+
var resolveColumnOptions = (options) => ({
|
|
7097
|
+
includeDescriptions: options.includeDescriptions ?? false,
|
|
7098
|
+
includeEnums: options.includeEnums ?? true,
|
|
7099
|
+
includeExamples: options.includeExamples ?? false,
|
|
7100
|
+
includeDefaults: options.includeDefaults ?? true,
|
|
7101
|
+
includeNullable: options.includeNullable ?? true
|
|
7102
|
+
});
|
|
7088
7103
|
var mapRelationType = (relationType) => {
|
|
7089
7104
|
switch (relationType) {
|
|
7090
7105
|
case "HAS_MANY":
|
|
@@ -7112,14 +7127,55 @@ var getTemporalFormat = (sqlType) => {
|
|
|
7112
7127
|
};
|
|
7113
7128
|
|
|
7114
7129
|
// src/openapi/schema-extractor.ts
|
|
7130
|
+
var DEFAULT_MAX_DEPTH = 5;
|
|
7115
7131
|
var extractSchema = (table, plan, projectionNodes, options = {}) => {
|
|
7116
|
-
const
|
|
7117
|
-
const
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7132
|
+
const outputOptions = resolveOutputOptions(options);
|
|
7133
|
+
const outputContext = createContext(outputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
7134
|
+
const output = extractOutputSchema(table, plan, projectionNodes, outputContext, outputOptions);
|
|
7135
|
+
const inputOptions = resolveInputOptions(options);
|
|
7136
|
+
if (!inputOptions) {
|
|
7137
|
+
return { output };
|
|
7138
|
+
}
|
|
7139
|
+
const inputContext = createContext(inputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
|
|
7140
|
+
const input = extractInputSchema(table, inputContext, inputOptions);
|
|
7141
|
+
return { output, input };
|
|
7142
|
+
};
|
|
7143
|
+
var resolveOutputOptions = (options) => ({
|
|
7144
|
+
mode: options.mode ?? "full",
|
|
7145
|
+
includeDescriptions: options.includeDescriptions,
|
|
7146
|
+
includeEnums: options.includeEnums,
|
|
7147
|
+
includeExamples: options.includeExamples,
|
|
7148
|
+
includeDefaults: options.includeDefaults,
|
|
7149
|
+
includeNullable: options.includeNullable,
|
|
7150
|
+
maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH
|
|
7151
|
+
});
|
|
7152
|
+
var resolveInputOptions = (options) => {
|
|
7153
|
+
if (options.input === false) return void 0;
|
|
7154
|
+
const input = options.input ?? {};
|
|
7155
|
+
const mode = input.mode ?? "create";
|
|
7156
|
+
return {
|
|
7157
|
+
mode,
|
|
7158
|
+
includeRelations: input.includeRelations ?? true,
|
|
7159
|
+
relationMode: input.relationMode ?? "mixed",
|
|
7160
|
+
includeDescriptions: input.includeDescriptions ?? options.includeDescriptions,
|
|
7161
|
+
includeEnums: input.includeEnums ?? options.includeEnums,
|
|
7162
|
+
includeExamples: input.includeExamples ?? options.includeExamples,
|
|
7163
|
+
includeDefaults: input.includeDefaults ?? options.includeDefaults,
|
|
7164
|
+
includeNullable: input.includeNullable ?? options.includeNullable,
|
|
7165
|
+
maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
|
|
7166
|
+
omitReadOnly: input.omitReadOnly ?? true,
|
|
7167
|
+
excludePrimaryKey: input.excludePrimaryKey ?? false,
|
|
7168
|
+
requirePrimaryKey: input.requirePrimaryKey ?? mode === "update"
|
|
7122
7169
|
};
|
|
7170
|
+
};
|
|
7171
|
+
var createContext = (maxDepth) => ({
|
|
7172
|
+
visitedTables: /* @__PURE__ */ new Set(),
|
|
7173
|
+
schemaCache: /* @__PURE__ */ new Map(),
|
|
7174
|
+
depth: 0,
|
|
7175
|
+
maxDepth
|
|
7176
|
+
});
|
|
7177
|
+
var extractOutputSchema = (table, plan, projectionNodes, context, options) => {
|
|
7178
|
+
const mode = options.mode ?? "full";
|
|
7123
7179
|
const hasComputedFields = projectionNodes && projectionNodes.some(
|
|
7124
7180
|
(node) => node.type !== "Column"
|
|
7125
7181
|
);
|
|
@@ -7131,9 +7187,97 @@ var extractSchema = (table, plan, projectionNodes, options = {}) => {
|
|
|
7131
7187
|
}
|
|
7132
7188
|
return extractFullTableSchema(table, context, options);
|
|
7133
7189
|
};
|
|
7190
|
+
var extractInputSchema = (table, context, options) => {
|
|
7191
|
+
const cacheKey = `${table.name}:${options.mode ?? "create"}`;
|
|
7192
|
+
if (context.schemaCache.has(cacheKey)) {
|
|
7193
|
+
return context.schemaCache.get(cacheKey);
|
|
7194
|
+
}
|
|
7195
|
+
if (context.visitedTables.has(cacheKey) && context.depth > 0) {
|
|
7196
|
+
return buildCircularReferenceSchema(table.name, "input");
|
|
7197
|
+
}
|
|
7198
|
+
context.visitedTables.add(cacheKey);
|
|
7199
|
+
const properties = {};
|
|
7200
|
+
const required = [];
|
|
7201
|
+
const primaryKey = findPrimaryKey(table);
|
|
7202
|
+
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
7203
|
+
const isPrimary = columnName === primaryKey || column.primary;
|
|
7204
|
+
if (options.excludePrimaryKey && isPrimary) continue;
|
|
7205
|
+
if (options.omitReadOnly && isReadOnlyColumn(column)) continue;
|
|
7206
|
+
properties[columnName] = mapColumnType(column, options);
|
|
7207
|
+
if (options.mode === "create" && isRequiredForCreate(column)) {
|
|
7208
|
+
required.push(columnName);
|
|
7209
|
+
}
|
|
7210
|
+
if (options.mode === "update" && options.requirePrimaryKey && isPrimary) {
|
|
7211
|
+
required.push(columnName);
|
|
7212
|
+
}
|
|
7213
|
+
}
|
|
7214
|
+
if (options.includeRelations && context.depth < context.maxDepth) {
|
|
7215
|
+
for (const [relationName, relation] of Object.entries(table.relations)) {
|
|
7216
|
+
properties[relationName] = extractInputRelationSchema(
|
|
7217
|
+
relation,
|
|
7218
|
+
{ ...context, depth: context.depth + 1 },
|
|
7219
|
+
options
|
|
7220
|
+
);
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
const schema = {
|
|
7224
|
+
type: "object",
|
|
7225
|
+
properties,
|
|
7226
|
+
required
|
|
7227
|
+
};
|
|
7228
|
+
context.schemaCache.set(cacheKey, schema);
|
|
7229
|
+
return schema;
|
|
7230
|
+
};
|
|
7231
|
+
var isReadOnlyColumn = (column) => Boolean(column.autoIncrement || column.generated === "always");
|
|
7232
|
+
var isRequiredForCreate = (column) => {
|
|
7233
|
+
if (isReadOnlyColumn(column)) return false;
|
|
7234
|
+
if (column.default !== void 0) return false;
|
|
7235
|
+
return Boolean(column.notNull || column.primary);
|
|
7236
|
+
};
|
|
7237
|
+
var buildPrimaryKeySchema = (table, options) => {
|
|
7238
|
+
const primaryKey = findPrimaryKey(table);
|
|
7239
|
+
const column = table.columns[primaryKey];
|
|
7240
|
+
if (!column) {
|
|
7241
|
+
return {
|
|
7242
|
+
anyOf: [
|
|
7243
|
+
{ type: "string" },
|
|
7244
|
+
{ type: "number" },
|
|
7245
|
+
{ type: "integer" }
|
|
7246
|
+
]
|
|
7247
|
+
};
|
|
7248
|
+
}
|
|
7249
|
+
return mapColumnType(column, options);
|
|
7250
|
+
};
|
|
7251
|
+
var extractInputRelationSchema = (relation, context, options) => {
|
|
7252
|
+
const { type: relationType, isNullable } = mapRelationType(relation.type);
|
|
7253
|
+
const relationMode = options.relationMode ?? "mixed";
|
|
7254
|
+
const allowIds = relationMode !== "objects";
|
|
7255
|
+
const allowObjects = relationMode !== "ids";
|
|
7256
|
+
const variants = [];
|
|
7257
|
+
if (allowIds) {
|
|
7258
|
+
variants.push(buildPrimaryKeySchema(relation.target, options));
|
|
7259
|
+
}
|
|
7260
|
+
if (allowObjects) {
|
|
7261
|
+
const targetSchema = extractInputSchema(relation.target, context, options);
|
|
7262
|
+
variants.push(targetSchema);
|
|
7263
|
+
}
|
|
7264
|
+
const itemSchema = variants.length === 1 ? variants[0] : { anyOf: variants };
|
|
7265
|
+
if (relationType === "array") {
|
|
7266
|
+
return {
|
|
7267
|
+
type: "array",
|
|
7268
|
+
items: itemSchema,
|
|
7269
|
+
nullable: isNullable
|
|
7270
|
+
};
|
|
7271
|
+
}
|
|
7272
|
+
return {
|
|
7273
|
+
...itemSchema,
|
|
7274
|
+
nullable: isNullable
|
|
7275
|
+
};
|
|
7276
|
+
};
|
|
7134
7277
|
var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
7135
7278
|
const properties = {};
|
|
7136
7279
|
const required = [];
|
|
7280
|
+
const includeDescriptions = Boolean(options.includeDescriptions);
|
|
7137
7281
|
for (const node of projectionNodes) {
|
|
7138
7282
|
if (!node || typeof node !== "object") continue;
|
|
7139
7283
|
const projection = node;
|
|
@@ -7143,10 +7287,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
7143
7287
|
const columnNode4 = node;
|
|
7144
7288
|
const column = table.columns[columnNode4.name];
|
|
7145
7289
|
if (!column) continue;
|
|
7146
|
-
const property = mapColumnType(column);
|
|
7147
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
7148
|
-
property.description = column.comment;
|
|
7149
|
-
}
|
|
7290
|
+
const property = mapColumnType(column, options);
|
|
7150
7291
|
properties[propertyName] = property;
|
|
7151
7292
|
if (column.notNull || column.primary) {
|
|
7152
7293
|
required.push(propertyName);
|
|
@@ -7154,7 +7295,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
7154
7295
|
} else if (projection.type === "Function" || projection.type === "WindowFunction") {
|
|
7155
7296
|
const fnNode = node;
|
|
7156
7297
|
const functionName = fnNode.fn?.toUpperCase() ?? fnNode.name?.toUpperCase() ?? "";
|
|
7157
|
-
const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName) : mapWindowFunctionToSchema(functionName);
|
|
7298
|
+
const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName, includeDescriptions) : mapWindowFunctionToSchema(functionName, includeDescriptions);
|
|
7158
7299
|
properties[propertyName] = propertySchema;
|
|
7159
7300
|
const isCountFunction = functionName === "COUNT";
|
|
7160
7301
|
const isWindowRankFunction = functionName === "ROW_NUMBER" || functionName === "RANK";
|
|
@@ -7164,23 +7305,29 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
7164
7305
|
} else if (projection.type === "CaseExpression") {
|
|
7165
7306
|
const propertySchema = {
|
|
7166
7307
|
type: "string",
|
|
7167
|
-
description: "Computed CASE expression",
|
|
7168
7308
|
nullable: true
|
|
7169
7309
|
};
|
|
7310
|
+
if (includeDescriptions) {
|
|
7311
|
+
propertySchema.description = "Computed CASE expression";
|
|
7312
|
+
}
|
|
7170
7313
|
properties[propertyName] = propertySchema;
|
|
7171
7314
|
} else if (projection.type === "ScalarSubquery") {
|
|
7172
7315
|
const propertySchema = {
|
|
7173
7316
|
type: "object",
|
|
7174
|
-
description: "Subquery result",
|
|
7175
7317
|
nullable: true
|
|
7176
7318
|
};
|
|
7319
|
+
if (includeDescriptions) {
|
|
7320
|
+
propertySchema.description = "Subquery result";
|
|
7321
|
+
}
|
|
7177
7322
|
properties[propertyName] = propertySchema;
|
|
7178
7323
|
} else if (projection.type === "CastExpression") {
|
|
7179
7324
|
const propertySchema = {
|
|
7180
7325
|
type: "string",
|
|
7181
|
-
description: "CAST expression result",
|
|
7182
7326
|
nullable: true
|
|
7183
7327
|
};
|
|
7328
|
+
if (includeDescriptions) {
|
|
7329
|
+
propertySchema.description = "CAST expression result";
|
|
7330
|
+
}
|
|
7184
7331
|
properties[propertyName] = propertySchema;
|
|
7185
7332
|
}
|
|
7186
7333
|
}
|
|
@@ -7190,7 +7337,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
|
|
|
7190
7337
|
required
|
|
7191
7338
|
};
|
|
7192
7339
|
};
|
|
7193
|
-
var mapFunctionNodeToSchema = (functionName) => {
|
|
7340
|
+
var mapFunctionNodeToSchema = (functionName, includeDescriptions) => {
|
|
7194
7341
|
const upperName = functionName.toUpperCase();
|
|
7195
7342
|
switch (upperName) {
|
|
7196
7343
|
case "COUNT":
|
|
@@ -7198,74 +7345,69 @@ var mapFunctionNodeToSchema = (functionName) => {
|
|
|
7198
7345
|
case "AVG":
|
|
7199
7346
|
case "MIN":
|
|
7200
7347
|
case "MAX":
|
|
7201
|
-
return {
|
|
7348
|
+
return withOptionalDescription({
|
|
7202
7349
|
type: "number",
|
|
7203
|
-
description: `${upperName} aggregate function result`,
|
|
7204
7350
|
nullable: false
|
|
7205
|
-
};
|
|
7351
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
7206
7352
|
case "GROUP_CONCAT":
|
|
7207
7353
|
case "STRING_AGG":
|
|
7208
7354
|
case "ARRAY_AGG":
|
|
7209
|
-
return {
|
|
7355
|
+
return withOptionalDescription({
|
|
7210
7356
|
type: "string",
|
|
7211
|
-
description: `${upperName} aggregate function result`,
|
|
7212
7357
|
nullable: true
|
|
7213
|
-
};
|
|
7358
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
7214
7359
|
case "JSON_ARRAYAGG":
|
|
7215
7360
|
case "JSON_OBJECTAGG":
|
|
7216
|
-
return {
|
|
7361
|
+
return withOptionalDescription({
|
|
7217
7362
|
type: "object",
|
|
7218
|
-
description: `${upperName} aggregate function result`,
|
|
7219
7363
|
nullable: true
|
|
7220
|
-
};
|
|
7364
|
+
}, includeDescriptions, `${upperName} aggregate function result`);
|
|
7221
7365
|
default:
|
|
7222
|
-
return {
|
|
7366
|
+
return withOptionalDescription({
|
|
7223
7367
|
type: "string",
|
|
7224
|
-
description: `Unknown function: ${functionName}`,
|
|
7225
7368
|
nullable: true
|
|
7226
|
-
};
|
|
7369
|
+
}, includeDescriptions, `Unknown function: ${functionName}`);
|
|
7227
7370
|
}
|
|
7228
7371
|
};
|
|
7229
|
-
var mapWindowFunctionToSchema = (functionName) => {
|
|
7372
|
+
var mapWindowFunctionToSchema = (functionName, includeDescriptions) => {
|
|
7230
7373
|
const upperName = functionName.toUpperCase();
|
|
7231
7374
|
switch (upperName) {
|
|
7232
7375
|
case "ROW_NUMBER":
|
|
7233
7376
|
case "RANK":
|
|
7234
7377
|
case "DENSE_RANK":
|
|
7235
7378
|
case "NTILE":
|
|
7236
|
-
return {
|
|
7379
|
+
return withOptionalDescription({
|
|
7237
7380
|
type: "integer",
|
|
7238
|
-
description: `${upperName} window function result`,
|
|
7239
7381
|
nullable: false
|
|
7240
|
-
};
|
|
7382
|
+
}, includeDescriptions, `${upperName} window function result`);
|
|
7241
7383
|
case "LAG":
|
|
7242
7384
|
case "LEAD":
|
|
7243
7385
|
case "FIRST_VALUE":
|
|
7244
7386
|
case "LAST_VALUE":
|
|
7245
|
-
return {
|
|
7387
|
+
return withOptionalDescription({
|
|
7246
7388
|
type: "string",
|
|
7247
|
-
description: `${upperName} window function result`,
|
|
7248
7389
|
nullable: true
|
|
7249
|
-
};
|
|
7390
|
+
}, includeDescriptions, `${upperName} window function result`);
|
|
7250
7391
|
default:
|
|
7251
|
-
return {
|
|
7392
|
+
return withOptionalDescription({
|
|
7252
7393
|
type: "string",
|
|
7253
|
-
description: `Unknown window function: ${functionName}`,
|
|
7254
7394
|
nullable: true
|
|
7255
|
-
};
|
|
7395
|
+
}, includeDescriptions, `Unknown window function: ${functionName}`);
|
|
7256
7396
|
}
|
|
7257
7397
|
};
|
|
7398
|
+
var withOptionalDescription = (schema, includeDescriptions, description) => {
|
|
7399
|
+
if (includeDescriptions) {
|
|
7400
|
+
return { ...schema, description };
|
|
7401
|
+
}
|
|
7402
|
+
return schema;
|
|
7403
|
+
};
|
|
7258
7404
|
var extractSelectedSchema = (table, plan, context, options) => {
|
|
7259
7405
|
const properties = {};
|
|
7260
7406
|
const required = [];
|
|
7261
7407
|
plan.rootColumns.forEach((columnName) => {
|
|
7262
7408
|
const column = table.columns[columnName];
|
|
7263
7409
|
if (!column) return;
|
|
7264
|
-
|
|
7265
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
7266
|
-
property.description = column.comment;
|
|
7267
|
-
}
|
|
7268
|
-
properties[columnName] = property;
|
|
7410
|
+
properties[columnName] = mapColumnType(column, options);
|
|
7269
7411
|
if (column.notNull || column.primary) {
|
|
7270
7412
|
required.push(columnName);
|
|
7271
7413
|
}
|
|
@@ -7298,26 +7440,13 @@ var extractFullTableSchema = (table, context, options) => {
|
|
|
7298
7440
|
return context.schemaCache.get(cacheKey);
|
|
7299
7441
|
}
|
|
7300
7442
|
if (context.visitedTables.has(cacheKey) && context.depth > 0) {
|
|
7301
|
-
return
|
|
7302
|
-
type: "object",
|
|
7303
|
-
properties: {
|
|
7304
|
-
_ref: {
|
|
7305
|
-
type: "string",
|
|
7306
|
-
description: `Circular reference to ${table.name}`
|
|
7307
|
-
}
|
|
7308
|
-
},
|
|
7309
|
-
required: []
|
|
7310
|
-
};
|
|
7443
|
+
return buildCircularReferenceSchema(table.name, "output");
|
|
7311
7444
|
}
|
|
7312
7445
|
context.visitedTables.add(cacheKey);
|
|
7313
7446
|
const properties = {};
|
|
7314
7447
|
const required = [];
|
|
7315
7448
|
Object.entries(table.columns).forEach(([columnName, column]) => {
|
|
7316
|
-
|
|
7317
|
-
if (!property.description && options.includeDescriptions && column.comment) {
|
|
7318
|
-
property.description = column.comment;
|
|
7319
|
-
}
|
|
7320
|
-
properties[columnName] = property;
|
|
7449
|
+
properties[columnName] = mapColumnType(column, options);
|
|
7321
7450
|
if (column.notNull || column.primary) {
|
|
7322
7451
|
required.push(columnName);
|
|
7323
7452
|
}
|
|
@@ -7377,10 +7506,188 @@ var extractRelationSchema = (relation, relationPlan, selectedColumns, context, o
|
|
|
7377
7506
|
description: targetSchema.description
|
|
7378
7507
|
};
|
|
7379
7508
|
};
|
|
7509
|
+
var buildCircularReferenceSchema = (tableName, kind) => ({
|
|
7510
|
+
type: "object",
|
|
7511
|
+
properties: {
|
|
7512
|
+
_ref: {
|
|
7513
|
+
type: "string",
|
|
7514
|
+
description: `Circular ${kind} reference to ${tableName}`
|
|
7515
|
+
}
|
|
7516
|
+
},
|
|
7517
|
+
required: []
|
|
7518
|
+
});
|
|
7380
7519
|
var schemaToJson = (schema, pretty = false) => {
|
|
7381
7520
|
return JSON.stringify(schema, null, pretty ? 2 : 0);
|
|
7382
7521
|
};
|
|
7383
7522
|
|
|
7523
|
+
// src/openapi/query-parameters.ts
|
|
7524
|
+
var FILTER_PARAM_NAME = "filter";
|
|
7525
|
+
var buildRootTableNames = (table, from) => {
|
|
7526
|
+
const names = /* @__PURE__ */ new Set([table.name]);
|
|
7527
|
+
if (from?.type === "Table") {
|
|
7528
|
+
names.add(from.name);
|
|
7529
|
+
if (from.alias) names.add(from.alias);
|
|
7530
|
+
}
|
|
7531
|
+
return names;
|
|
7532
|
+
};
|
|
7533
|
+
var collectFilterColumns = (expr, table, rootTables) => {
|
|
7534
|
+
const columns = /* @__PURE__ */ new Set();
|
|
7535
|
+
const recordColumn = (node) => {
|
|
7536
|
+
if (!rootTables.has(node.table)) return;
|
|
7537
|
+
if (node.name in table.columns) {
|
|
7538
|
+
columns.add(node.name);
|
|
7539
|
+
}
|
|
7540
|
+
};
|
|
7541
|
+
const visitOrderingTerm = (term) => {
|
|
7542
|
+
if (!term || typeof term !== "object") return;
|
|
7543
|
+
if (isOperandNode(term)) {
|
|
7544
|
+
visitOperand2(term);
|
|
7545
|
+
return;
|
|
7546
|
+
}
|
|
7547
|
+
if ("type" in term) {
|
|
7548
|
+
visitExpression2(term);
|
|
7549
|
+
}
|
|
7550
|
+
};
|
|
7551
|
+
const visitOrderBy = (orderBy) => {
|
|
7552
|
+
if (!orderBy) return;
|
|
7553
|
+
orderBy.forEach((node) => visitOrderingTerm(node.term));
|
|
7554
|
+
};
|
|
7555
|
+
const visitOperand2 = (node) => {
|
|
7556
|
+
switch (node.type) {
|
|
7557
|
+
case "Column":
|
|
7558
|
+
recordColumn(node);
|
|
7559
|
+
return;
|
|
7560
|
+
case "Function": {
|
|
7561
|
+
const fn8 = node;
|
|
7562
|
+
fn8.args?.forEach(visitOperand2);
|
|
7563
|
+
visitOrderBy(fn8.orderBy);
|
|
7564
|
+
if (fn8.separator) visitOperand2(fn8.separator);
|
|
7565
|
+
return;
|
|
7566
|
+
}
|
|
7567
|
+
case "JsonPath": {
|
|
7568
|
+
const jp = node;
|
|
7569
|
+
recordColumn(jp.column);
|
|
7570
|
+
return;
|
|
7571
|
+
}
|
|
7572
|
+
case "ScalarSubquery":
|
|
7573
|
+
return;
|
|
7574
|
+
case "CaseExpression": {
|
|
7575
|
+
const cs = node;
|
|
7576
|
+
cs.conditions.forEach((condition) => {
|
|
7577
|
+
visitExpression2(condition.when);
|
|
7578
|
+
visitOperand2(condition.then);
|
|
7579
|
+
});
|
|
7580
|
+
if (cs.else) visitOperand2(cs.else);
|
|
7581
|
+
return;
|
|
7582
|
+
}
|
|
7583
|
+
case "Cast": {
|
|
7584
|
+
const cast2 = node;
|
|
7585
|
+
visitOperand2(cast2.expression);
|
|
7586
|
+
return;
|
|
7587
|
+
}
|
|
7588
|
+
case "WindowFunction": {
|
|
7589
|
+
const windowFn = node;
|
|
7590
|
+
windowFn.args?.forEach(visitOperand2);
|
|
7591
|
+
windowFn.partitionBy?.forEach(recordColumn);
|
|
7592
|
+
visitOrderBy(windowFn.orderBy);
|
|
7593
|
+
return;
|
|
7594
|
+
}
|
|
7595
|
+
case "ArithmeticExpression": {
|
|
7596
|
+
const arith = node;
|
|
7597
|
+
visitOperand2(arith.left);
|
|
7598
|
+
visitOperand2(arith.right);
|
|
7599
|
+
return;
|
|
7600
|
+
}
|
|
7601
|
+
case "BitwiseExpression": {
|
|
7602
|
+
const bitwise = node;
|
|
7603
|
+
visitOperand2(bitwise.left);
|
|
7604
|
+
visitOperand2(bitwise.right);
|
|
7605
|
+
return;
|
|
7606
|
+
}
|
|
7607
|
+
case "Collate": {
|
|
7608
|
+
const collate2 = node;
|
|
7609
|
+
visitOperand2(collate2.expression);
|
|
7610
|
+
return;
|
|
7611
|
+
}
|
|
7612
|
+
case "AliasRef":
|
|
7613
|
+
case "Literal":
|
|
7614
|
+
return;
|
|
7615
|
+
default:
|
|
7616
|
+
return;
|
|
7617
|
+
}
|
|
7618
|
+
};
|
|
7619
|
+
const visitExpression2 = (node) => {
|
|
7620
|
+
switch (node.type) {
|
|
7621
|
+
case "BinaryExpression":
|
|
7622
|
+
visitOperand2(node.left);
|
|
7623
|
+
visitOperand2(node.right);
|
|
7624
|
+
if (node.escape) visitOperand2(node.escape);
|
|
7625
|
+
return;
|
|
7626
|
+
case "LogicalExpression":
|
|
7627
|
+
node.operands.forEach(visitExpression2);
|
|
7628
|
+
return;
|
|
7629
|
+
case "NullExpression":
|
|
7630
|
+
visitOperand2(node.left);
|
|
7631
|
+
return;
|
|
7632
|
+
case "InExpression":
|
|
7633
|
+
visitOperand2(node.left);
|
|
7634
|
+
if (Array.isArray(node.right)) {
|
|
7635
|
+
node.right.forEach(visitOperand2);
|
|
7636
|
+
}
|
|
7637
|
+
return;
|
|
7638
|
+
case "ExistsExpression":
|
|
7639
|
+
return;
|
|
7640
|
+
case "BetweenExpression":
|
|
7641
|
+
visitOperand2(node.left);
|
|
7642
|
+
visitOperand2(node.lower);
|
|
7643
|
+
visitOperand2(node.upper);
|
|
7644
|
+
return;
|
|
7645
|
+
case "ArithmeticExpression":
|
|
7646
|
+
visitOperand2(node.left);
|
|
7647
|
+
visitOperand2(node.right);
|
|
7648
|
+
return;
|
|
7649
|
+
case "BitwiseExpression":
|
|
7650
|
+
visitOperand2(node.left);
|
|
7651
|
+
visitOperand2(node.right);
|
|
7652
|
+
return;
|
|
7653
|
+
default:
|
|
7654
|
+
return;
|
|
7655
|
+
}
|
|
7656
|
+
};
|
|
7657
|
+
visitExpression2(expr);
|
|
7658
|
+
return columns;
|
|
7659
|
+
};
|
|
7660
|
+
var buildFilterParameters = (table, where, from, options = {}) => {
|
|
7661
|
+
if (!where) return [];
|
|
7662
|
+
const rootTables = buildRootTableNames(table, from);
|
|
7663
|
+
const columnNames = collectFilterColumns(where, table, rootTables);
|
|
7664
|
+
let schema;
|
|
7665
|
+
if (columnNames.size) {
|
|
7666
|
+
const properties = {};
|
|
7667
|
+
for (const name of columnNames) {
|
|
7668
|
+
const column = table.columns[name];
|
|
7669
|
+
if (!column) continue;
|
|
7670
|
+
properties[name] = mapColumnType(column, options);
|
|
7671
|
+
}
|
|
7672
|
+
schema = {
|
|
7673
|
+
type: "object",
|
|
7674
|
+
properties
|
|
7675
|
+
};
|
|
7676
|
+
} else {
|
|
7677
|
+
schema = {
|
|
7678
|
+
type: "object",
|
|
7679
|
+
additionalProperties: true
|
|
7680
|
+
};
|
|
7681
|
+
}
|
|
7682
|
+
return [{
|
|
7683
|
+
name: FILTER_PARAM_NAME,
|
|
7684
|
+
in: "query",
|
|
7685
|
+
style: "deepObject",
|
|
7686
|
+
explode: true,
|
|
7687
|
+
schema
|
|
7688
|
+
}];
|
|
7689
|
+
};
|
|
7690
|
+
|
|
7384
7691
|
// src/query-builder/select.ts
|
|
7385
7692
|
var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
7386
7693
|
env;
|
|
@@ -8200,16 +8507,26 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8200
8507
|
return this.context.hydration.getPlan();
|
|
8201
8508
|
}
|
|
8202
8509
|
/**
|
|
8203
|
-
* Gets OpenAPI 3.1 JSON
|
|
8510
|
+
* Gets OpenAPI 3.1 JSON Schemas for query output and optional input payloads
|
|
8204
8511
|
* @param options - Schema generation options
|
|
8205
|
-
* @returns OpenAPI 3.1 JSON
|
|
8512
|
+
* @returns OpenAPI 3.1 JSON Schemas for query output and input payloads
|
|
8206
8513
|
* @example
|
|
8207
|
-
* const
|
|
8208
|
-
* console.log(JSON.stringify(
|
|
8514
|
+
* const { output } = qb.select('id', 'title', 'author').getSchema();
|
|
8515
|
+
* console.log(JSON.stringify(output, null, 2));
|
|
8209
8516
|
*/
|
|
8210
8517
|
getSchema(options) {
|
|
8211
8518
|
const plan = this.context.hydration.getPlan();
|
|
8212
|
-
|
|
8519
|
+
const bundle = extractSchema(this.env.table, plan, this.context.state.ast.columns, options);
|
|
8520
|
+
const parameters = buildFilterParameters(
|
|
8521
|
+
this.env.table,
|
|
8522
|
+
this.context.state.ast.where,
|
|
8523
|
+
this.context.state.ast.from,
|
|
8524
|
+
options ?? {}
|
|
8525
|
+
);
|
|
8526
|
+
if (parameters.length) {
|
|
8527
|
+
return { ...bundle, parameters };
|
|
8528
|
+
}
|
|
8529
|
+
return bundle;
|
|
8213
8530
|
}
|
|
8214
8531
|
/**
|
|
8215
8532
|
* Gets the Abstract Syntax Tree (AST) representation of the query
|
|
@@ -11826,6 +12143,7 @@ var UnitOfWork = class {
|
|
|
11826
12143
|
const compiled = builder.compile(this.dialect);
|
|
11827
12144
|
const results = await this.executeCompiled(compiled);
|
|
11828
12145
|
this.applyReturningResults(tracked, results);
|
|
12146
|
+
this.applyInsertId(tracked, results);
|
|
11829
12147
|
tracked.status = "managed" /* Managed */;
|
|
11830
12148
|
tracked.original = this.createSnapshot(tracked.table, tracked.entity);
|
|
11831
12149
|
tracked.pk = this.getPrimaryKeyValue(tracked);
|
|
@@ -11951,6 +12269,16 @@ var UnitOfWork = class {
|
|
|
11951
12269
|
tracked.entity[columnName] = row[i];
|
|
11952
12270
|
}
|
|
11953
12271
|
}
|
|
12272
|
+
applyInsertId(tracked, results) {
|
|
12273
|
+
if (this.dialect.supportsReturning()) return;
|
|
12274
|
+
if (tracked.pk != null) return;
|
|
12275
|
+
const pkName = findPrimaryKey(tracked.table);
|
|
12276
|
+
const pkColumn = tracked.table.columns[pkName];
|
|
12277
|
+
if (!pkColumn?.autoIncrement) return;
|
|
12278
|
+
const insertId = results.find((result) => typeof result.insertId === "number")?.insertId;
|
|
12279
|
+
if (insertId == null) return;
|
|
12280
|
+
tracked.entity[pkName] = insertId;
|
|
12281
|
+
}
|
|
11954
12282
|
/**
|
|
11955
12283
|
* Normalizes a column name by removing quotes and table prefixes.
|
|
11956
12284
|
* @param column - The column name to normalize
|
|
@@ -13467,7 +13795,9 @@ function createMysqlExecutor(client) {
|
|
|
13467
13795
|
async executeSql(sql, params) {
|
|
13468
13796
|
const [rows] = await client.query(sql, params);
|
|
13469
13797
|
if (!Array.isArray(rows)) {
|
|
13470
|
-
|
|
13798
|
+
const insertId = rows?.insertId;
|
|
13799
|
+
const normalized = typeof insertId === "number" && insertId > 0 ? insertId : void 0;
|
|
13800
|
+
return [{ columns: [], values: [], insertId: normalized }];
|
|
13471
13801
|
}
|
|
13472
13802
|
const result = rowsToQueryResult(
|
|
13473
13803
|
rows
|
|
@@ -13766,6 +14096,7 @@ function createPooledExecutorFactory(opts) {
|
|
|
13766
14096
|
bitOr,
|
|
13767
14097
|
bitXor,
|
|
13768
14098
|
bootstrapEntities,
|
|
14099
|
+
buildFilterParameters,
|
|
13769
14100
|
caseWhen,
|
|
13770
14101
|
cast,
|
|
13771
14102
|
cbrt,
|