metal-orm 1.0.80 → 1.0.82

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,
@@ -122,6 +123,7 @@ __export(index_exports, {
122
123
  createExecutorFromQueryRunner: () => createExecutorFromQueryRunner,
123
124
  createMssqlExecutor: () => createMssqlExecutor,
124
125
  createMysqlExecutor: () => createMysqlExecutor,
126
+ createParamProxy: () => createParamProxy,
125
127
  createPooledExecutorFactory: () => createPooledExecutorFactory,
126
128
  createPostgresExecutor: () => createPostgresExecutor,
127
129
  createQueryLoggingExecutor: () => createQueryLoggingExecutor,
@@ -642,6 +644,7 @@ var operandTypes = /* @__PURE__ */ new Set([
642
644
  "AliasRef",
643
645
  "Column",
644
646
  "Literal",
647
+ "Param",
645
648
  "Function",
646
649
  "JsonPath",
647
650
  "ScalarSubquery",
@@ -1081,6 +1084,9 @@ var visitOperand = (node, visitor) => {
1081
1084
  case "Literal":
1082
1085
  if (visitor.visitLiteral) return visitor.visitLiteral(node);
1083
1086
  break;
1087
+ case "Param":
1088
+ if (visitor.visitParam) return visitor.visitParam(node);
1089
+ break;
1084
1090
  case "Function":
1085
1091
  if (visitor.visitFunction) return visitor.visitFunction(node);
1086
1092
  break;
@@ -1112,6 +1118,47 @@ var visitOperand = (node, visitor) => {
1112
1118
  return unsupportedOperand(node);
1113
1119
  };
1114
1120
 
1121
+ // src/core/ast/param-proxy.ts
1122
+ var buildParamProxy = (name) => {
1123
+ const target = { type: "Param", name };
1124
+ return new Proxy(target, {
1125
+ get(t, prop, receiver) {
1126
+ if (prop === "then") return void 0;
1127
+ if (typeof prop === "symbol") {
1128
+ return Reflect.get(t, prop, receiver);
1129
+ }
1130
+ if (typeof prop === "string" && prop.startsWith("$")) {
1131
+ const trimmed = prop.slice(1);
1132
+ const nextName2 = name ? `${name}.${trimmed}` : trimmed;
1133
+ return buildParamProxy(nextName2);
1134
+ }
1135
+ if (prop in t) {
1136
+ return t[prop];
1137
+ }
1138
+ const nextName = name ? `${name}.${prop}` : prop;
1139
+ return buildParamProxy(nextName);
1140
+ }
1141
+ });
1142
+ };
1143
+ var createParamProxy = () => {
1144
+ const target = {};
1145
+ return new Proxy(target, {
1146
+ get(t, prop, receiver) {
1147
+ if (prop === "then") return void 0;
1148
+ if (typeof prop === "symbol") {
1149
+ return Reflect.get(t, prop, receiver);
1150
+ }
1151
+ if (typeof prop === "string" && prop.startsWith("$")) {
1152
+ return buildParamProxy(prop.slice(1));
1153
+ }
1154
+ if (prop in t) {
1155
+ return t[prop];
1156
+ }
1157
+ return buildParamProxy(String(prop));
1158
+ }
1159
+ });
1160
+ };
1161
+
1115
1162
  // src/core/ast/adapters.ts
1116
1163
  var hasAlias = (obj) => typeof obj === "object" && obj !== null && "alias" in obj;
1117
1164
  var toColumnRef = (col2) => ({
@@ -1821,6 +1868,7 @@ var Dialect = class _Dialect {
1821
1868
  }
1822
1869
  registerDefaultOperandCompilers() {
1823
1870
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
1871
+ this.registerOperandCompiler("Param", (_param, ctx) => ctx.addParameter(null));
1824
1872
  this.registerOperandCompiler("AliasRef", (alias, _ctx) => {
1825
1873
  void _ctx;
1826
1874
  return this.quoteIdentifier(alias.name);
@@ -4344,6 +4392,7 @@ var collectFromOperand = (node, collector) => {
4344
4392
  break;
4345
4393
  case "Literal":
4346
4394
  case "AliasRef":
4395
+ case "Param":
4347
4396
  break;
4348
4397
  default:
4349
4398
  break;
@@ -6950,26 +6999,33 @@ var SelectRelationFacet = class {
6950
6999
  };
6951
7000
 
6952
7001
  // src/openapi/type-mappers.ts
6953
- var mapColumnType = (column) => {
7002
+ var mapColumnType = (column, options = {}) => {
7003
+ const resolved = resolveColumnOptions(options);
6954
7004
  const sqlType = normalizeType(column.type);
6955
7005
  const baseSchema = mapSqlTypeToBaseSchema(sqlType, column);
6956
7006
  const schema = {
6957
- ...baseSchema,
6958
- description: column.comment,
6959
- nullable: !column.notNull && !column.primary
7007
+ ...baseSchema
6960
7008
  };
6961
- if (column.args && sqlType === "varchar" || sqlType === "char") {
7009
+ if (resolved.includeDescriptions && column.comment) {
7010
+ schema.description = column.comment;
7011
+ }
7012
+ if (resolved.includeNullable) {
7013
+ schema.nullable = !column.notNull && !column.primary;
7014
+ }
7015
+ if ((sqlType === "varchar" || sqlType === "char") && column.args) {
6962
7016
  schema.maxLength = column.args[0];
6963
7017
  }
6964
- if (column.args && sqlType === "decimal" || sqlType === "float") {
7018
+ if ((sqlType === "decimal" || sqlType === "float") && column.args) {
6965
7019
  if (column.args.length >= 1) {
6966
7020
  schema.minimum = -(10 ** column.args[0]);
6967
7021
  }
6968
7022
  }
6969
- if (sqlType === "enum" && column.args && column.args.length > 0) {
7023
+ if (!resolved.includeEnums) {
7024
+ delete schema.enum;
7025
+ } else if (sqlType === "enum" && column.args && column.args.length > 0) {
6970
7026
  schema.enum = column.args;
6971
7027
  }
6972
- if (column.default !== void 0) {
7028
+ if (resolved.includeDefaults && column.default !== void 0) {
6973
7029
  schema.default = column.default;
6974
7030
  }
6975
7031
  return schema;
@@ -7085,6 +7141,13 @@ var inferTypeFromTsType = (tsType) => {
7085
7141
  }
7086
7142
  return "string";
7087
7143
  };
7144
+ var resolveColumnOptions = (options) => ({
7145
+ includeDescriptions: options.includeDescriptions ?? false,
7146
+ includeEnums: options.includeEnums ?? true,
7147
+ includeExamples: options.includeExamples ?? false,
7148
+ includeDefaults: options.includeDefaults ?? true,
7149
+ includeNullable: options.includeNullable ?? true
7150
+ });
7088
7151
  var mapRelationType = (relationType) => {
7089
7152
  switch (relationType) {
7090
7153
  case "HAS_MANY":
@@ -7112,14 +7175,55 @@ var getTemporalFormat = (sqlType) => {
7112
7175
  };
7113
7176
 
7114
7177
  // src/openapi/schema-extractor.ts
7178
+ var DEFAULT_MAX_DEPTH = 5;
7115
7179
  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
7180
+ const outputOptions = resolveOutputOptions(options);
7181
+ const outputContext = createContext(outputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
7182
+ const output = extractOutputSchema(table, plan, projectionNodes, outputContext, outputOptions);
7183
+ const inputOptions = resolveInputOptions(options);
7184
+ if (!inputOptions) {
7185
+ return { output };
7186
+ }
7187
+ const inputContext = createContext(inputOptions.maxDepth ?? DEFAULT_MAX_DEPTH);
7188
+ const input = extractInputSchema(table, inputContext, inputOptions);
7189
+ return { output, input };
7190
+ };
7191
+ var resolveOutputOptions = (options) => ({
7192
+ mode: options.mode ?? "full",
7193
+ includeDescriptions: options.includeDescriptions,
7194
+ includeEnums: options.includeEnums,
7195
+ includeExamples: options.includeExamples,
7196
+ includeDefaults: options.includeDefaults,
7197
+ includeNullable: options.includeNullable,
7198
+ maxDepth: options.maxDepth ?? DEFAULT_MAX_DEPTH
7199
+ });
7200
+ var resolveInputOptions = (options) => {
7201
+ if (options.input === false) return void 0;
7202
+ const input = options.input ?? {};
7203
+ const mode = input.mode ?? "create";
7204
+ return {
7205
+ mode,
7206
+ includeRelations: input.includeRelations ?? true,
7207
+ relationMode: input.relationMode ?? "mixed",
7208
+ includeDescriptions: input.includeDescriptions ?? options.includeDescriptions,
7209
+ includeEnums: input.includeEnums ?? options.includeEnums,
7210
+ includeExamples: input.includeExamples ?? options.includeExamples,
7211
+ includeDefaults: input.includeDefaults ?? options.includeDefaults,
7212
+ includeNullable: input.includeNullable ?? options.includeNullable,
7213
+ maxDepth: input.maxDepth ?? options.maxDepth ?? DEFAULT_MAX_DEPTH,
7214
+ omitReadOnly: input.omitReadOnly ?? true,
7215
+ excludePrimaryKey: input.excludePrimaryKey ?? false,
7216
+ requirePrimaryKey: input.requirePrimaryKey ?? mode === "update"
7122
7217
  };
7218
+ };
7219
+ var createContext = (maxDepth) => ({
7220
+ visitedTables: /* @__PURE__ */ new Set(),
7221
+ schemaCache: /* @__PURE__ */ new Map(),
7222
+ depth: 0,
7223
+ maxDepth
7224
+ });
7225
+ var extractOutputSchema = (table, plan, projectionNodes, context, options) => {
7226
+ const mode = options.mode ?? "full";
7123
7227
  const hasComputedFields = projectionNodes && projectionNodes.some(
7124
7228
  (node) => node.type !== "Column"
7125
7229
  );
@@ -7131,9 +7235,97 @@ var extractSchema = (table, plan, projectionNodes, options = {}) => {
7131
7235
  }
7132
7236
  return extractFullTableSchema(table, context, options);
7133
7237
  };
7238
+ var extractInputSchema = (table, context, options) => {
7239
+ const cacheKey = `${table.name}:${options.mode ?? "create"}`;
7240
+ if (context.schemaCache.has(cacheKey)) {
7241
+ return context.schemaCache.get(cacheKey);
7242
+ }
7243
+ if (context.visitedTables.has(cacheKey) && context.depth > 0) {
7244
+ return buildCircularReferenceSchema(table.name, "input");
7245
+ }
7246
+ context.visitedTables.add(cacheKey);
7247
+ const properties = {};
7248
+ const required = [];
7249
+ const primaryKey = findPrimaryKey(table);
7250
+ for (const [columnName, column] of Object.entries(table.columns)) {
7251
+ const isPrimary = columnName === primaryKey || column.primary;
7252
+ if (options.excludePrimaryKey && isPrimary) continue;
7253
+ if (options.omitReadOnly && isReadOnlyColumn(column)) continue;
7254
+ properties[columnName] = mapColumnType(column, options);
7255
+ if (options.mode === "create" && isRequiredForCreate(column)) {
7256
+ required.push(columnName);
7257
+ }
7258
+ if (options.mode === "update" && options.requirePrimaryKey && isPrimary) {
7259
+ required.push(columnName);
7260
+ }
7261
+ }
7262
+ if (options.includeRelations && context.depth < context.maxDepth) {
7263
+ for (const [relationName, relation] of Object.entries(table.relations)) {
7264
+ properties[relationName] = extractInputRelationSchema(
7265
+ relation,
7266
+ { ...context, depth: context.depth + 1 },
7267
+ options
7268
+ );
7269
+ }
7270
+ }
7271
+ const schema = {
7272
+ type: "object",
7273
+ properties,
7274
+ required
7275
+ };
7276
+ context.schemaCache.set(cacheKey, schema);
7277
+ return schema;
7278
+ };
7279
+ var isReadOnlyColumn = (column) => Boolean(column.autoIncrement || column.generated === "always");
7280
+ var isRequiredForCreate = (column) => {
7281
+ if (isReadOnlyColumn(column)) return false;
7282
+ if (column.default !== void 0) return false;
7283
+ return Boolean(column.notNull || column.primary);
7284
+ };
7285
+ var buildPrimaryKeySchema = (table, options) => {
7286
+ const primaryKey = findPrimaryKey(table);
7287
+ const column = table.columns[primaryKey];
7288
+ if (!column) {
7289
+ return {
7290
+ anyOf: [
7291
+ { type: "string" },
7292
+ { type: "number" },
7293
+ { type: "integer" }
7294
+ ]
7295
+ };
7296
+ }
7297
+ return mapColumnType(column, options);
7298
+ };
7299
+ var extractInputRelationSchema = (relation, context, options) => {
7300
+ const { type: relationType, isNullable } = mapRelationType(relation.type);
7301
+ const relationMode = options.relationMode ?? "mixed";
7302
+ const allowIds = relationMode !== "objects";
7303
+ const allowObjects = relationMode !== "ids";
7304
+ const variants = [];
7305
+ if (allowIds) {
7306
+ variants.push(buildPrimaryKeySchema(relation.target, options));
7307
+ }
7308
+ if (allowObjects) {
7309
+ const targetSchema = extractInputSchema(relation.target, context, options);
7310
+ variants.push(targetSchema);
7311
+ }
7312
+ const itemSchema = variants.length === 1 ? variants[0] : { anyOf: variants };
7313
+ if (relationType === "array") {
7314
+ return {
7315
+ type: "array",
7316
+ items: itemSchema,
7317
+ nullable: isNullable
7318
+ };
7319
+ }
7320
+ return {
7321
+ ...itemSchema,
7322
+ nullable: isNullable
7323
+ };
7324
+ };
7134
7325
  var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
7135
7326
  const properties = {};
7136
7327
  const required = [];
7328
+ const includeDescriptions = Boolean(options.includeDescriptions);
7137
7329
  for (const node of projectionNodes) {
7138
7330
  if (!node || typeof node !== "object") continue;
7139
7331
  const projection = node;
@@ -7143,10 +7335,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
7143
7335
  const columnNode4 = node;
7144
7336
  const column = table.columns[columnNode4.name];
7145
7337
  if (!column) continue;
7146
- const property = mapColumnType(column);
7147
- if (!property.description && options.includeDescriptions && column.comment) {
7148
- property.description = column.comment;
7149
- }
7338
+ const property = mapColumnType(column, options);
7150
7339
  properties[propertyName] = property;
7151
7340
  if (column.notNull || column.primary) {
7152
7341
  required.push(propertyName);
@@ -7154,7 +7343,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
7154
7343
  } else if (projection.type === "Function" || projection.type === "WindowFunction") {
7155
7344
  const fnNode = node;
7156
7345
  const functionName = fnNode.fn?.toUpperCase() ?? fnNode.name?.toUpperCase() ?? "";
7157
- const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName) : mapWindowFunctionToSchema(functionName);
7346
+ const propertySchema = projection.type === "Function" ? mapFunctionNodeToSchema(functionName, includeDescriptions) : mapWindowFunctionToSchema(functionName, includeDescriptions);
7158
7347
  properties[propertyName] = propertySchema;
7159
7348
  const isCountFunction = functionName === "COUNT";
7160
7349
  const isWindowRankFunction = functionName === "ROW_NUMBER" || functionName === "RANK";
@@ -7164,23 +7353,29 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
7164
7353
  } else if (projection.type === "CaseExpression") {
7165
7354
  const propertySchema = {
7166
7355
  type: "string",
7167
- description: "Computed CASE expression",
7168
7356
  nullable: true
7169
7357
  };
7358
+ if (includeDescriptions) {
7359
+ propertySchema.description = "Computed CASE expression";
7360
+ }
7170
7361
  properties[propertyName] = propertySchema;
7171
7362
  } else if (projection.type === "ScalarSubquery") {
7172
7363
  const propertySchema = {
7173
7364
  type: "object",
7174
- description: "Subquery result",
7175
7365
  nullable: true
7176
7366
  };
7367
+ if (includeDescriptions) {
7368
+ propertySchema.description = "Subquery result";
7369
+ }
7177
7370
  properties[propertyName] = propertySchema;
7178
7371
  } else if (projection.type === "CastExpression") {
7179
7372
  const propertySchema = {
7180
7373
  type: "string",
7181
- description: "CAST expression result",
7182
7374
  nullable: true
7183
7375
  };
7376
+ if (includeDescriptions) {
7377
+ propertySchema.description = "CAST expression result";
7378
+ }
7184
7379
  properties[propertyName] = propertySchema;
7185
7380
  }
7186
7381
  }
@@ -7190,7 +7385,7 @@ var extractFromProjectionNodes = (table, projectionNodes, context, options) => {
7190
7385
  required
7191
7386
  };
7192
7387
  };
7193
- var mapFunctionNodeToSchema = (functionName) => {
7388
+ var mapFunctionNodeToSchema = (functionName, includeDescriptions) => {
7194
7389
  const upperName = functionName.toUpperCase();
7195
7390
  switch (upperName) {
7196
7391
  case "COUNT":
@@ -7198,74 +7393,69 @@ var mapFunctionNodeToSchema = (functionName) => {
7198
7393
  case "AVG":
7199
7394
  case "MIN":
7200
7395
  case "MAX":
7201
- return {
7396
+ return withOptionalDescription({
7202
7397
  type: "number",
7203
- description: `${upperName} aggregate function result`,
7204
7398
  nullable: false
7205
- };
7399
+ }, includeDescriptions, `${upperName} aggregate function result`);
7206
7400
  case "GROUP_CONCAT":
7207
7401
  case "STRING_AGG":
7208
7402
  case "ARRAY_AGG":
7209
- return {
7403
+ return withOptionalDescription({
7210
7404
  type: "string",
7211
- description: `${upperName} aggregate function result`,
7212
7405
  nullable: true
7213
- };
7406
+ }, includeDescriptions, `${upperName} aggregate function result`);
7214
7407
  case "JSON_ARRAYAGG":
7215
7408
  case "JSON_OBJECTAGG":
7216
- return {
7409
+ return withOptionalDescription({
7217
7410
  type: "object",
7218
- description: `${upperName} aggregate function result`,
7219
7411
  nullable: true
7220
- };
7412
+ }, includeDescriptions, `${upperName} aggregate function result`);
7221
7413
  default:
7222
- return {
7414
+ return withOptionalDescription({
7223
7415
  type: "string",
7224
- description: `Unknown function: ${functionName}`,
7225
7416
  nullable: true
7226
- };
7417
+ }, includeDescriptions, `Unknown function: ${functionName}`);
7227
7418
  }
7228
7419
  };
7229
- var mapWindowFunctionToSchema = (functionName) => {
7420
+ var mapWindowFunctionToSchema = (functionName, includeDescriptions) => {
7230
7421
  const upperName = functionName.toUpperCase();
7231
7422
  switch (upperName) {
7232
7423
  case "ROW_NUMBER":
7233
7424
  case "RANK":
7234
7425
  case "DENSE_RANK":
7235
7426
  case "NTILE":
7236
- return {
7427
+ return withOptionalDescription({
7237
7428
  type: "integer",
7238
- description: `${upperName} window function result`,
7239
7429
  nullable: false
7240
- };
7430
+ }, includeDescriptions, `${upperName} window function result`);
7241
7431
  case "LAG":
7242
7432
  case "LEAD":
7243
7433
  case "FIRST_VALUE":
7244
7434
  case "LAST_VALUE":
7245
- return {
7435
+ return withOptionalDescription({
7246
7436
  type: "string",
7247
- description: `${upperName} window function result`,
7248
7437
  nullable: true
7249
- };
7438
+ }, includeDescriptions, `${upperName} window function result`);
7250
7439
  default:
7251
- return {
7440
+ return withOptionalDescription({
7252
7441
  type: "string",
7253
- description: `Unknown window function: ${functionName}`,
7254
7442
  nullable: true
7255
- };
7443
+ }, includeDescriptions, `Unknown window function: ${functionName}`);
7256
7444
  }
7257
7445
  };
7446
+ var withOptionalDescription = (schema, includeDescriptions, description) => {
7447
+ if (includeDescriptions) {
7448
+ return { ...schema, description };
7449
+ }
7450
+ return schema;
7451
+ };
7258
7452
  var extractSelectedSchema = (table, plan, context, options) => {
7259
7453
  const properties = {};
7260
7454
  const required = [];
7261
7455
  plan.rootColumns.forEach((columnName) => {
7262
7456
  const column = table.columns[columnName];
7263
7457
  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;
7458
+ properties[columnName] = mapColumnType(column, options);
7269
7459
  if (column.notNull || column.primary) {
7270
7460
  required.push(columnName);
7271
7461
  }
@@ -7298,26 +7488,13 @@ var extractFullTableSchema = (table, context, options) => {
7298
7488
  return context.schemaCache.get(cacheKey);
7299
7489
  }
7300
7490
  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
- };
7491
+ return buildCircularReferenceSchema(table.name, "output");
7311
7492
  }
7312
7493
  context.visitedTables.add(cacheKey);
7313
7494
  const properties = {};
7314
7495
  const required = [];
7315
7496
  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;
7497
+ properties[columnName] = mapColumnType(column, options);
7321
7498
  if (column.notNull || column.primary) {
7322
7499
  required.push(columnName);
7323
7500
  }
@@ -7377,10 +7554,189 @@ var extractRelationSchema = (relation, relationPlan, selectedColumns, context, o
7377
7554
  description: targetSchema.description
7378
7555
  };
7379
7556
  };
7557
+ var buildCircularReferenceSchema = (tableName, kind) => ({
7558
+ type: "object",
7559
+ properties: {
7560
+ _ref: {
7561
+ type: "string",
7562
+ description: `Circular ${kind} reference to ${tableName}`
7563
+ }
7564
+ },
7565
+ required: []
7566
+ });
7380
7567
  var schemaToJson = (schema, pretty = false) => {
7381
7568
  return JSON.stringify(schema, null, pretty ? 2 : 0);
7382
7569
  };
7383
7570
 
7571
+ // src/openapi/query-parameters.ts
7572
+ var FILTER_PARAM_NAME = "filter";
7573
+ var buildRootTableNames = (table, from) => {
7574
+ const names = /* @__PURE__ */ new Set([table.name]);
7575
+ if (from?.type === "Table") {
7576
+ names.add(from.name);
7577
+ if (from.alias) names.add(from.alias);
7578
+ }
7579
+ return names;
7580
+ };
7581
+ var collectFilterColumns = (expr, table, rootTables) => {
7582
+ const columns = /* @__PURE__ */ new Set();
7583
+ const recordColumn = (node) => {
7584
+ if (!rootTables.has(node.table)) return;
7585
+ if (node.name in table.columns) {
7586
+ columns.add(node.name);
7587
+ }
7588
+ };
7589
+ const visitOrderingTerm = (term) => {
7590
+ if (!term || typeof term !== "object") return;
7591
+ if (isOperandNode(term)) {
7592
+ visitOperand2(term);
7593
+ return;
7594
+ }
7595
+ if ("type" in term) {
7596
+ visitExpression2(term);
7597
+ }
7598
+ };
7599
+ const visitOrderBy = (orderBy) => {
7600
+ if (!orderBy) return;
7601
+ orderBy.forEach((node) => visitOrderingTerm(node.term));
7602
+ };
7603
+ const visitOperand2 = (node) => {
7604
+ switch (node.type) {
7605
+ case "Column":
7606
+ recordColumn(node);
7607
+ return;
7608
+ case "Function": {
7609
+ const fn8 = node;
7610
+ fn8.args?.forEach(visitOperand2);
7611
+ visitOrderBy(fn8.orderBy);
7612
+ if (fn8.separator) visitOperand2(fn8.separator);
7613
+ return;
7614
+ }
7615
+ case "JsonPath": {
7616
+ const jp = node;
7617
+ recordColumn(jp.column);
7618
+ return;
7619
+ }
7620
+ case "ScalarSubquery":
7621
+ return;
7622
+ case "CaseExpression": {
7623
+ const cs = node;
7624
+ cs.conditions.forEach((condition) => {
7625
+ visitExpression2(condition.when);
7626
+ visitOperand2(condition.then);
7627
+ });
7628
+ if (cs.else) visitOperand2(cs.else);
7629
+ return;
7630
+ }
7631
+ case "Cast": {
7632
+ const cast2 = node;
7633
+ visitOperand2(cast2.expression);
7634
+ return;
7635
+ }
7636
+ case "WindowFunction": {
7637
+ const windowFn = node;
7638
+ windowFn.args?.forEach(visitOperand2);
7639
+ windowFn.partitionBy?.forEach(recordColumn);
7640
+ visitOrderBy(windowFn.orderBy);
7641
+ return;
7642
+ }
7643
+ case "ArithmeticExpression": {
7644
+ const arith = node;
7645
+ visitOperand2(arith.left);
7646
+ visitOperand2(arith.right);
7647
+ return;
7648
+ }
7649
+ case "BitwiseExpression": {
7650
+ const bitwise = node;
7651
+ visitOperand2(bitwise.left);
7652
+ visitOperand2(bitwise.right);
7653
+ return;
7654
+ }
7655
+ case "Collate": {
7656
+ const collate2 = node;
7657
+ visitOperand2(collate2.expression);
7658
+ return;
7659
+ }
7660
+ case "AliasRef":
7661
+ case "Literal":
7662
+ case "Param":
7663
+ return;
7664
+ default:
7665
+ return;
7666
+ }
7667
+ };
7668
+ const visitExpression2 = (node) => {
7669
+ switch (node.type) {
7670
+ case "BinaryExpression":
7671
+ visitOperand2(node.left);
7672
+ visitOperand2(node.right);
7673
+ if (node.escape) visitOperand2(node.escape);
7674
+ return;
7675
+ case "LogicalExpression":
7676
+ node.operands.forEach(visitExpression2);
7677
+ return;
7678
+ case "NullExpression":
7679
+ visitOperand2(node.left);
7680
+ return;
7681
+ case "InExpression":
7682
+ visitOperand2(node.left);
7683
+ if (Array.isArray(node.right)) {
7684
+ node.right.forEach(visitOperand2);
7685
+ }
7686
+ return;
7687
+ case "ExistsExpression":
7688
+ return;
7689
+ case "BetweenExpression":
7690
+ visitOperand2(node.left);
7691
+ visitOperand2(node.lower);
7692
+ visitOperand2(node.upper);
7693
+ return;
7694
+ case "ArithmeticExpression":
7695
+ visitOperand2(node.left);
7696
+ visitOperand2(node.right);
7697
+ return;
7698
+ case "BitwiseExpression":
7699
+ visitOperand2(node.left);
7700
+ visitOperand2(node.right);
7701
+ return;
7702
+ default:
7703
+ return;
7704
+ }
7705
+ };
7706
+ visitExpression2(expr);
7707
+ return columns;
7708
+ };
7709
+ var buildFilterParameters = (table, where, from, options = {}) => {
7710
+ if (!where) return [];
7711
+ const rootTables = buildRootTableNames(table, from);
7712
+ const columnNames = collectFilterColumns(where, table, rootTables);
7713
+ let schema;
7714
+ if (columnNames.size) {
7715
+ const properties = {};
7716
+ for (const name of columnNames) {
7717
+ const column = table.columns[name];
7718
+ if (!column) continue;
7719
+ properties[name] = mapColumnType(column, options);
7720
+ }
7721
+ schema = {
7722
+ type: "object",
7723
+ properties
7724
+ };
7725
+ } else {
7726
+ schema = {
7727
+ type: "object",
7728
+ additionalProperties: true
7729
+ };
7730
+ }
7731
+ return [{
7732
+ name: FILTER_PARAM_NAME,
7733
+ in: "query",
7734
+ style: "deepObject",
7735
+ explode: true,
7736
+ schema
7737
+ }];
7738
+ };
7739
+
7384
7740
  // src/query-builder/select.ts
7385
7741
  var SelectQueryBuilder = class _SelectQueryBuilder {
7386
7742
  env;
@@ -8200,16 +8556,26 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
8200
8556
  return this.context.hydration.getPlan();
8201
8557
  }
8202
8558
  /**
8203
- * Gets OpenAPI 3.1 JSON Schema for query result
8559
+ * Gets OpenAPI 3.1 JSON Schemas for query output and optional input payloads
8204
8560
  * @param options - Schema generation options
8205
- * @returns OpenAPI 3.1 JSON Schema for query result
8561
+ * @returns OpenAPI 3.1 JSON Schemas for query output and input payloads
8206
8562
  * @example
8207
- * const schema = qb.select('id', 'title', 'author').getSchema();
8208
- * console.log(JSON.stringify(schema, null, 2));
8563
+ * const { output } = qb.select('id', 'title', 'author').getSchema();
8564
+ * console.log(JSON.stringify(output, null, 2));
8209
8565
  */
8210
8566
  getSchema(options) {
8211
8567
  const plan = this.context.hydration.getPlan();
8212
- return extractSchema(this.env.table, plan, this.context.state.ast.columns, options);
8568
+ const bundle = extractSchema(this.env.table, plan, this.context.state.ast.columns, options);
8569
+ const parameters = buildFilterParameters(
8570
+ this.env.table,
8571
+ this.context.state.ast.where,
8572
+ this.context.state.ast.from,
8573
+ options ?? {}
8574
+ );
8575
+ if (parameters.length) {
8576
+ return { ...bundle, parameters };
8577
+ }
8578
+ return bundle;
8213
8579
  }
8214
8580
  /**
8215
8581
  * Gets the Abstract Syntax Tree (AST) representation of the query
@@ -11333,6 +11699,7 @@ var TypeScriptGenerator = class {
11333
11699
  case "WindowFunction":
11334
11700
  case "Cast":
11335
11701
  case "Collate":
11702
+ case "Param":
11336
11703
  return this.printOperand(term);
11337
11704
  default:
11338
11705
  return this.printExpression(term);
@@ -11377,6 +11744,9 @@ var TypeScriptGenerator = class {
11377
11744
  visitLiteral(node) {
11378
11745
  return this.printLiteralOperand(node);
11379
11746
  }
11747
+ visitParam(node) {
11748
+ return this.printParamOperand(node);
11749
+ }
11380
11750
  visitFunction(node) {
11381
11751
  return this.printFunctionOperand(node);
11382
11752
  }
@@ -11498,6 +11868,10 @@ var TypeScriptGenerator = class {
11498
11868
  if (literal.value === null) return "null";
11499
11869
  return typeof literal.value === "string" ? `'${literal.value}'` : String(literal.value);
11500
11870
  }
11871
+ printParamOperand(param) {
11872
+ const name = param.name.replace(/'/g, "\\'");
11873
+ return `{ type: 'Param', name: '${name}' }`;
11874
+ }
11501
11875
  /**
11502
11876
  * Prints a function operand to TypeScript code
11503
11877
  * @param fn - Function node
@@ -11826,6 +12200,7 @@ var UnitOfWork = class {
11826
12200
  const compiled = builder.compile(this.dialect);
11827
12201
  const results = await this.executeCompiled(compiled);
11828
12202
  this.applyReturningResults(tracked, results);
12203
+ this.applyInsertId(tracked, results);
11829
12204
  tracked.status = "managed" /* Managed */;
11830
12205
  tracked.original = this.createSnapshot(tracked.table, tracked.entity);
11831
12206
  tracked.pk = this.getPrimaryKeyValue(tracked);
@@ -11951,6 +12326,16 @@ var UnitOfWork = class {
11951
12326
  tracked.entity[columnName] = row[i];
11952
12327
  }
11953
12328
  }
12329
+ applyInsertId(tracked, results) {
12330
+ if (this.dialect.supportsReturning()) return;
12331
+ if (tracked.pk != null) return;
12332
+ const pkName = findPrimaryKey(tracked.table);
12333
+ const pkColumn = tracked.table.columns[pkName];
12334
+ if (!pkColumn?.autoIncrement) return;
12335
+ const insertId = results.find((result) => typeof result.insertId === "number")?.insertId;
12336
+ if (insertId == null) return;
12337
+ tracked.entity[pkName] = insertId;
12338
+ }
11954
12339
  /**
11955
12340
  * Normalizes a column name by removing quotes and table prefixes.
11956
12341
  * @param column - The column name to normalize
@@ -13467,7 +13852,9 @@ function createMysqlExecutor(client) {
13467
13852
  async executeSql(sql, params) {
13468
13853
  const [rows] = await client.query(sql, params);
13469
13854
  if (!Array.isArray(rows)) {
13470
- return [{ columns: [], values: [] }];
13855
+ const insertId = rows?.insertId;
13856
+ const normalized = typeof insertId === "number" && insertId > 0 ? insertId : void 0;
13857
+ return [{ columns: [], values: [], insertId: normalized }];
13471
13858
  }
13472
13859
  const result = rowsToQueryResult(
13473
13860
  rows
@@ -13766,6 +14153,7 @@ function createPooledExecutorFactory(opts) {
13766
14153
  bitOr,
13767
14154
  bitXor,
13768
14155
  bootstrapEntities,
14156
+ buildFilterParameters,
13769
14157
  caseWhen,
13770
14158
  cast,
13771
14159
  cbrt,
@@ -13792,6 +14180,7 @@ function createPooledExecutorFactory(opts) {
13792
14180
  createExecutorFromQueryRunner,
13793
14181
  createMssqlExecutor,
13794
14182
  createMysqlExecutor,
14183
+ createParamProxy,
13795
14184
  createPooledExecutorFactory,
13796
14185
  createPostgresExecutor,
13797
14186
  createQueryLoggingExecutor,