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