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.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 (column.args && sqlType === "varchar" || sqlType === "char") {
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 (column.args && sqlType === "decimal" || sqlType === "float") {
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 (sqlType === "enum" && column.args && column.args.length > 0) {
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 mode = options.mode ?? "full";
6835
- const context = {
6836
- visitedTables: /* @__PURE__ */ new Set(),
6837
- schemaCache: /* @__PURE__ */ new Map(),
6838
- depth: 0,
6839
- maxDepth: options.maxDepth ?? 5
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
- const property = mapColumnType(column);
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
- const property = mapColumnType(column);
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 Schema for query result
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 Schema for query result
8229
+ * @returns OpenAPI 3.1 JSON Schemas for query output and input payloads
7924
8230
  * @example
7925
- * const schema = qb.select('id', 'title', 'author').getSchema();
7926
- * console.log(JSON.stringify(schema, null, 2));
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
- return extractSchema(this.env.table, plan, this.context.state.ast.columns, options);
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
- return [{ columns: [], values: [] }];
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,