@zenstackhq/orm 3.1.1 → 3.2.1

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
@@ -39,6 +39,7 @@ __export(src_exports, {
39
39
  CRUD_EXT: () => CRUD_EXT,
40
40
  DbNull: () => DbNull,
41
41
  DbNullClass: () => DbNullClass,
42
+ InputValidator: () => InputValidator,
42
43
  JsonNull: () => JsonNull,
43
44
  JsonNullClass: () => JsonNullClass,
44
45
  KyselyUtils: () => kysely_utils_exports,
@@ -653,6 +654,7 @@ var import_ts_pattern5 = require("ts-pattern");
653
654
  var import_common_helpers3 = require("@zenstackhq/common-helpers");
654
655
  var import_decimal = __toESM(require("decimal.js"), 1);
655
656
  var import_kysely3 = require("kysely");
657
+ var import_postgres_array = require("postgres-array");
656
658
  var import_ts_pattern3 = require("ts-pattern");
657
659
  var import_zod = __toESM(require("zod"), 1);
658
660
 
@@ -700,7 +702,7 @@ var BaseCrudDialect = class {
700
702
  transformPrimitive(value, _type, _forArrayField) {
701
703
  return value;
702
704
  }
703
- transformOutput(value, _type) {
705
+ transformOutput(value, _type, _array) {
704
706
  return value;
705
707
  }
706
708
  // #region common query builders
@@ -1557,6 +1559,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1557
1559
  } else if (Array.isArray(value)) {
1558
1560
  if (type === "Json" && !forArrayField) {
1559
1561
  return JSON.stringify(value);
1562
+ }
1563
+ if (isEnum(this.schema, type)) {
1564
+ return this.eb.cast(import_kysely3.sql`ARRAY[${import_kysely3.sql.join(value.map((v) => this.transformPrimitive(v, type, false)), import_kysely3.sql.raw(","))}]`, this.createSchemaQualifiedEnumType(type, true));
1560
1565
  } else {
1561
1566
  return value.map((v) => this.transformPrimitive(v, type, false));
1562
1567
  }
@@ -1570,11 +1575,29 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1570
1575
  }).otherwise(() => value);
1571
1576
  }
1572
1577
  }
1573
- transformOutput(value, type) {
1578
+ createSchemaQualifiedEnumType(type, array) {
1579
+ let qualified = type;
1580
+ const enumDef = getEnum(this.schema, type);
1581
+ if (enumDef) {
1582
+ const schemaAttr = enumDef.attributes?.find((attr) => attr.name === "@@schema");
1583
+ if (schemaAttr) {
1584
+ const mapArg = schemaAttr.args?.find((arg) => arg.name === "map");
1585
+ if (mapArg && mapArg.value.kind === "literal") {
1586
+ const schemaName = mapArg.value.value;
1587
+ qualified = `"${schemaName}"."${type}"`;
1588
+ }
1589
+ } else {
1590
+ const defaultSchema = this.schema.provider.defaultSchema ?? "public";
1591
+ qualified = `"${defaultSchema}"."${type}"`;
1592
+ }
1593
+ }
1594
+ return array ? import_kysely3.sql.raw(`${qualified}[]`) : import_kysely3.sql.raw(qualified);
1595
+ }
1596
+ transformOutput(value, type, array) {
1574
1597
  if (value === null || value === void 0) {
1575
1598
  return value;
1576
1599
  }
1577
- return (0, import_ts_pattern3.match)(type).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Decimal", () => this.transformDecimal(value)).otherwise(() => super.transformOutput(value, type));
1600
+ return (0, import_ts_pattern3.match)(type).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Decimal", () => this.transformDecimal(value)).when((type2) => isEnum(this.schema, type2), () => this.transformOutputEnum(value, array)).otherwise(() => super.transformOutput(value, type, array));
1578
1601
  }
1579
1602
  transformOutputBigInt(value) {
1580
1603
  if (typeof value === "bigint") {
@@ -1607,6 +1630,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1607
1630
  transformOutputBytes(value) {
1608
1631
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : typeof value === "string" && value.startsWith("\\x") ? Uint8Array.from(Buffer.from(value.slice(2), "hex")) : value;
1609
1632
  }
1633
+ transformOutputEnum(value, array) {
1634
+ if (array && typeof value === "string") {
1635
+ try {
1636
+ return (0, import_postgres_array.parse)(value);
1637
+ } catch {
1638
+ }
1639
+ }
1640
+ return value;
1641
+ }
1610
1642
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
1611
1643
  const relationResultName = `${parentAlias}$${relationField}`;
1612
1644
  const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
@@ -1837,13 +1869,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1837
1869
  return (0, import_ts_pattern4.match)(type).with("Boolean", () => value ? 1 : 0).with("DateTime", () => value instanceof Date ? value.toISOString() : typeof value === "string" ? new Date(value).toISOString() : value).with("Decimal", () => value.toString()).with("Bytes", () => Buffer.from(value)).otherwise(() => value);
1838
1870
  }
1839
1871
  }
1840
- transformOutput(value, type) {
1872
+ transformOutput(value, type, array) {
1841
1873
  if (value === null || value === void 0) {
1842
1874
  return value;
1843
1875
  } else if (this.schema.typeDefs && type in this.schema.typeDefs) {
1844
1876
  return this.transformOutputJson(value);
1845
1877
  } else {
1846
- return (0, import_ts_pattern4.match)(type).with("Boolean", () => this.transformOutputBoolean(value)).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("Decimal", () => this.transformOutputDecimal(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Json", () => this.transformOutputJson(value)).otherwise(() => super.transformOutput(value, type));
1878
+ return (0, import_ts_pattern4.match)(type).with("Boolean", () => this.transformOutputBoolean(value)).with("DateTime", () => this.transformOutputDate(value)).with("Bytes", () => this.transformOutputBytes(value)).with("Decimal", () => this.transformOutputDecimal(value)).with("BigInt", () => this.transformOutputBigInt(value)).with("Json", () => this.transformOutputJson(value)).otherwise(() => super.transformOutput(value, type, array));
1847
1879
  }
1848
1880
  }
1849
1881
  transformOutputDecimal(value) {
@@ -2123,6 +2155,21 @@ var BaseOperationHandler = class {
2123
2155
  select: this.makeIdSelect(model)
2124
2156
  });
2125
2157
  }
2158
+ async existsNonUnique(kysely, model, filter) {
2159
+ const query = kysely.selectNoFrom((eb) => eb.exists(this.dialect.buildSelectModel(model, model).select(import_kysely5.sql.lit(1).as("$t")).where(() => this.dialect.buildFilter(model, model, filter))).as("exists")).modifyEnd(this.makeContextComment({
2160
+ model,
2161
+ operation: "read"
2162
+ }));
2163
+ let result = [];
2164
+ const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), (0, import_kysely5.createQueryId)());
2165
+ try {
2166
+ const r = await kysely.getExecutor().executeQuery(compiled);
2167
+ result = r.rows;
2168
+ } catch (err) {
2169
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiled.sql, compiled.parameters);
2170
+ }
2171
+ return !!result[0]?.exists;
2172
+ }
2126
2173
  async read(kysely, model, args) {
2127
2174
  let query = this.dialect.buildSelectModel(model, model);
2128
2175
  if (args) {
@@ -2146,7 +2193,7 @@ var BaseOperationHandler = class {
2146
2193
  const r = await kysely.getExecutor().executeQuery(compiled);
2147
2194
  result = r.rows;
2148
2195
  } catch (err) {
2149
- throw createDBQueryError("Failed to execute query", err, compiled.sql, compiled.parameters);
2196
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiled.sql, compiled.parameters);
2150
2197
  }
2151
2198
  return result;
2152
2199
  }
@@ -3734,6 +3781,18 @@ var FindOperationHandler = class extends BaseOperationHandler {
3734
3781
  }
3735
3782
  };
3736
3783
 
3784
+ // src/client/crud/operations/exists.ts
3785
+ var ExistsOperationHandler = class extends BaseOperationHandler {
3786
+ static {
3787
+ __name(this, "ExistsOperationHandler");
3788
+ }
3789
+ async handle(_operation, args) {
3790
+ const normalizedArgs = this.normalizeArgs(args);
3791
+ const parsedArgs = this.inputValidator.validateExistsArgs(this.model, normalizedArgs);
3792
+ return await this.existsNonUnique(this.client.$qb, this.model, parsedArgs?.where);
3793
+ }
3794
+ };
3795
+
3737
3796
  // src/client/crud/operations/group-by.ts
3738
3797
  var import_ts_pattern10 = require("ts-pattern");
3739
3798
  var GroupByOperationHandler = class extends BaseOperationHandler {
@@ -3852,7 +3911,7 @@ var UpdateOperationHandler = class extends BaseOperationHandler {
3852
3911
  const result = await this.safeTransaction(async (tx) => {
3853
3912
  const updateResult = await this.update(tx, this.model, args.where, args.data, void 0, void 0, void 0, selectedFields);
3854
3913
  if (needReadBack) {
3855
- const readFilter = updateResult ?? args.where;
3914
+ const readFilter = updateResult ? getIdValues(this.schema, this.model, updateResult) : args.where;
3856
3915
  let readBackResult = void 0;
3857
3916
  readBackResult = await this.readUnique(tx, this.model, {
3858
3917
  select: args.select,
@@ -4350,9 +4409,96 @@ var InputValidator = class {
4350
4409
  get extraValidationsEnabled() {
4351
4410
  return this.client.$options.validateInput !== false;
4352
4411
  }
4412
+ validateProcedureInput(proc, input) {
4413
+ const procDef = (this.schema.procedures ?? {})[proc];
4414
+ (0, import_common_helpers7.invariant)(procDef, `Procedure "${proc}" not found in schema`);
4415
+ const params = Object.values(procDef.params ?? {});
4416
+ if (typeof input === "undefined") {
4417
+ if (params.length === 0) {
4418
+ return void 0;
4419
+ }
4420
+ if (params.every((p) => p.optional)) {
4421
+ return void 0;
4422
+ }
4423
+ throw createInvalidInputError("Missing procedure arguments", `$procs.${proc}`);
4424
+ }
4425
+ if (typeof input !== "object") {
4426
+ throw createInvalidInputError("Procedure input must be an object", `$procs.${proc}`);
4427
+ }
4428
+ const envelope = input;
4429
+ const argsPayload = Object.prototype.hasOwnProperty.call(envelope, "args") ? envelope.args : void 0;
4430
+ if (params.length === 0) {
4431
+ if (typeof argsPayload === "undefined") {
4432
+ return input;
4433
+ }
4434
+ if (!argsPayload || typeof argsPayload !== "object" || Array.isArray(argsPayload)) {
4435
+ throw createInvalidInputError("Procedure `args` must be an object", `$procs.${proc}`);
4436
+ }
4437
+ if (Object.keys(argsPayload).length === 0) {
4438
+ return input;
4439
+ }
4440
+ throw createInvalidInputError("Procedure does not accept arguments", `$procs.${proc}`);
4441
+ }
4442
+ if (typeof argsPayload === "undefined") {
4443
+ if (params.every((p) => p.optional)) {
4444
+ return input;
4445
+ }
4446
+ throw createInvalidInputError("Missing procedure arguments", `$procs.${proc}`);
4447
+ }
4448
+ if (!argsPayload || typeof argsPayload !== "object" || Array.isArray(argsPayload)) {
4449
+ throw createInvalidInputError("Procedure `args` must be an object", `$procs.${proc}`);
4450
+ }
4451
+ const obj = argsPayload;
4452
+ for (const param of params) {
4453
+ const value = obj[param.name];
4454
+ if (!Object.prototype.hasOwnProperty.call(obj, param.name)) {
4455
+ if (param.optional) {
4456
+ continue;
4457
+ }
4458
+ throw createInvalidInputError(`Missing procedure argument: ${param.name}`, `$procs.${proc}`);
4459
+ }
4460
+ if (typeof value === "undefined") {
4461
+ if (param.optional) {
4462
+ continue;
4463
+ }
4464
+ throw createInvalidInputError(`Invalid procedure argument: ${param.name} is required`, `$procs.${proc}`);
4465
+ }
4466
+ const schema = this.makeProcedureParamSchema(param);
4467
+ const parsed = schema.safeParse(value);
4468
+ if (!parsed.success) {
4469
+ throw createInvalidInputError(`Invalid procedure argument: ${param.name}: ${formatError(parsed.error)}`, `$procs.${proc}`);
4470
+ }
4471
+ }
4472
+ return input;
4473
+ }
4474
+ makeProcedureParamSchema(param) {
4475
+ let schema;
4476
+ if (isTypeDef(this.schema, param.type)) {
4477
+ schema = this.makeTypeDefSchema(param.type);
4478
+ } else if (isEnum(this.schema, param.type)) {
4479
+ schema = this.makeEnumSchema(param.type);
4480
+ } else if (param.type in (this.schema.models ?? {})) {
4481
+ schema = import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown());
4482
+ } else {
4483
+ schema = this.makeScalarSchema(param.type);
4484
+ if (schema instanceof import_zod3.z.ZodUnknown) {
4485
+ throw createInternalError(`Unsupported procedure parameter type: ${param.type}`);
4486
+ }
4487
+ }
4488
+ if (param.array) {
4489
+ schema = schema.array();
4490
+ }
4491
+ if (param.optional) {
4492
+ schema = schema.optional();
4493
+ }
4494
+ return schema;
4495
+ }
4353
4496
  validateFindArgs(model, args, options) {
4354
4497
  return this.validate(model, "find", options, (model2, options2) => this.makeFindSchema(model2, options2), args);
4355
4498
  }
4499
+ validateExistsArgs(model, args) {
4500
+ return this.validate(model, "exists", void 0, (model2) => this.makeExistsSchema(model2), args);
4501
+ }
4356
4502
  validateCreateArgs(model, args) {
4357
4503
  return this.validate(model, "create", void 0, (model2) => this.makeCreateSchema(model2), args);
4358
4504
  }
@@ -4457,6 +4603,11 @@ var InputValidator = class {
4457
4603
  }
4458
4604
  return result;
4459
4605
  }
4606
+ makeExistsSchema(model) {
4607
+ return import_zod3.z.strictObject({
4608
+ where: this.makeWhereSchema(model, false).optional()
4609
+ }).optional();
4610
+ }
4460
4611
  makeScalarSchema(type, attributes) {
4461
4612
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
4462
4613
  return this.makeTypeDefSchema(type);
@@ -4561,7 +4712,7 @@ var InputValidator = class {
4561
4712
  const enumDef = getEnum(this.schema, fieldDef.type);
4562
4713
  if (enumDef) {
4563
4714
  if (Object.keys(enumDef.values).length > 0) {
4564
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
4715
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations, !!fieldDef.array);
4565
4716
  }
4566
4717
  } else if (fieldDef.array) {
4567
4718
  fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
@@ -4585,7 +4736,7 @@ var InputValidator = class {
4585
4736
  const enumDef = getEnum(this.schema, def.type);
4586
4737
  if (enumDef) {
4587
4738
  if (Object.keys(enumDef.values).length > 0) {
4588
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
4739
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false, false);
4589
4740
  } else {
4590
4741
  fieldSchema = import_zod3.z.never();
4591
4742
  }
@@ -4635,15 +4786,13 @@ var InputValidator = class {
4635
4786
  if (this.isTypeDefType(fieldDef.type)) {
4636
4787
  fieldSchemas[fieldName] = this.makeTypedJsonFilterSchema(fieldDef.type, !!fieldDef.optional, !!fieldDef.array).optional();
4637
4788
  } else {
4638
- if (fieldDef.array) {
4789
+ const enumDef = getEnum(this.schema, fieldDef.type);
4790
+ if (enumDef) {
4791
+ fieldSchemas[fieldName] = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, false, !!fieldDef.array).optional();
4792
+ } else if (fieldDef.array) {
4639
4793
  fieldSchemas[fieldName] = this.makeArrayFilterSchema(fieldDef.type).optional();
4640
4794
  } else {
4641
- const enumDef = getEnum(this.schema, fieldDef.type);
4642
- if (enumDef) {
4643
- fieldSchemas[fieldName] = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, false).optional();
4644
- } else {
4645
- fieldSchemas[fieldName] = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, false).optional();
4646
- }
4795
+ fieldSchemas[fieldName] = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, false).optional();
4647
4796
  }
4648
4797
  }
4649
4798
  }
@@ -4671,9 +4820,12 @@ var InputValidator = class {
4671
4820
  isTypeDefType(type) {
4672
4821
  return this.schema.typeDefs && type in this.schema.typeDefs;
4673
4822
  }
4674
- makeEnumFilterSchema(enumDef, optional, withAggregations) {
4823
+ makeEnumFilterSchema(enumDef, optional, withAggregations, array) {
4675
4824
  const baseSchema = import_zod3.z.enum(Object.keys(enumDef.values));
4676
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => import_zod3.z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
4825
+ if (array) {
4826
+ return this.internalMakeArrayFilterSchema(baseSchema);
4827
+ }
4828
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => import_zod3.z.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations, array)), [
4677
4829
  "equals",
4678
4830
  "in",
4679
4831
  "notIn",
@@ -4689,11 +4841,14 @@ var InputValidator = class {
4689
4841
  ]);
4690
4842
  }
4691
4843
  makeArrayFilterSchema(type) {
4844
+ return this.internalMakeArrayFilterSchema(this.makeScalarSchema(type));
4845
+ }
4846
+ internalMakeArrayFilterSchema(elementSchema) {
4692
4847
  return import_zod3.z.strictObject({
4693
- equals: this.makeScalarSchema(type).array().optional(),
4694
- has: this.makeScalarSchema(type).optional(),
4695
- hasEvery: this.makeScalarSchema(type).array().optional(),
4696
- hasSome: this.makeScalarSchema(type).array().optional(),
4848
+ equals: elementSchema.array().optional(),
4849
+ has: elementSchema.optional(),
4850
+ hasEvery: elementSchema.array().optional(),
4851
+ hasSome: elementSchema.array().optional(),
4697
4852
  isEmpty: import_zod3.z.boolean().optional()
4698
4853
  });
4699
4854
  }
@@ -5753,14 +5908,16 @@ var QueryNameMapper = class extends import_kysely6.OperationNodeTransformer {
5753
5908
  return super.transformSelectQuery(node);
5754
5909
  }
5755
5910
  const processedFroms = node.from.froms.map((from) => this.processSelectTable(from));
5756
- const processedJoins = this.withScopes([
5911
+ const processedJoins = [];
5912
+ const cumulativeScopes = [
5757
5913
  ...processedFroms.map(({ scope }) => scope)
5758
- ], () => (node.joins ?? []).map((join) => this.processSelectTable(join.table)));
5759
- const scopes = [
5760
- ...processedFroms.map(({ scope }) => scope),
5761
- ...processedJoins.map(({ scope }) => scope)
5762
5914
  ];
5763
- return this.withScopes(scopes, () => {
5915
+ for (const join of node.joins ?? []) {
5916
+ const processedJoin = this.withScopes(cumulativeScopes, () => this.processSelectTable(join.table));
5917
+ processedJoins.push(processedJoin);
5918
+ cumulativeScopes.push(processedJoin.scope);
5919
+ }
5920
+ return this.withScopes(cumulativeScopes, () => {
5764
5921
  const joins = node.joins ? node.joins.map((join, i) => ({
5765
5922
  ...join,
5766
5923
  table: processedJoins[i].node,
@@ -6095,9 +6252,9 @@ var QueryNameMapper = class extends import_kysely6.OperationNodeTransformer {
6095
6252
  let schema = this.schema.provider.defaultSchema ?? "public";
6096
6253
  const schemaAttr = this.schema.models[model]?.attributes?.find((attr) => attr.name === "@@schema");
6097
6254
  if (schemaAttr) {
6098
- const nameArg = schemaAttr.args?.find((arg) => arg.name === "map");
6099
- if (nameArg && nameArg.value.kind === "literal") {
6100
- schema = nameArg.value.value;
6255
+ const mapArg = schemaAttr.args?.find((arg) => arg.name === "map");
6256
+ if (mapArg && mapArg.value.kind === "literal") {
6257
+ schema = mapArg.value.value;
6101
6258
  }
6102
6259
  }
6103
6260
  return schema;
@@ -6348,7 +6505,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
6348
6505
  if (err instanceof ORMError) {
6349
6506
  throw err;
6350
6507
  } else {
6351
- throw createDBQueryError("Failed to execute query", err, compiledQuery.sql, compiledQuery.parameters);
6508
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiledQuery.sql, compiledQuery.parameters);
6352
6509
  }
6353
6510
  }
6354
6511
  });
@@ -6588,7 +6745,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends import_kysely7.
6588
6745
  try {
6589
6746
  return await connection.executeQuery(compiledQuery);
6590
6747
  } catch (err) {
6591
- throw createDBQueryError("Failed to execute query", err, compiledQuery.sql, compiledQuery.parameters);
6748
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiledQuery.sql, compiledQuery.parameters);
6592
6749
  }
6593
6750
  }
6594
6751
  };
@@ -7046,7 +7203,7 @@ var ResultProcessor = class {
7046
7203
  }
7047
7204
  if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
7048
7205
  if (value) {
7049
- const subRow = this.dialect.transformOutput(value, "Json");
7206
+ const subRow = this.dialect.transformOutput(value, "Json", false);
7050
7207
  const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
7051
7208
  const idValues = getIdValues(this.schema, subModel, subRow);
7052
7209
  if (Object.values(idValues).some((v) => v === null || v === void 0)) {
@@ -7080,10 +7237,10 @@ var ResultProcessor = class {
7080
7237
  processFieldValue(value, fieldDef) {
7081
7238
  const type = fieldDef.type;
7082
7239
  if (Array.isArray(value)) {
7083
- value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type));
7240
+ value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type, false));
7084
7241
  return value;
7085
7242
  } else {
7086
- return this.dialect.transformOutput(value, type);
7243
+ return this.dialect.transformOutput(value, type, !!fieldDef.array);
7087
7244
  }
7088
7245
  }
7089
7246
  processRelation(value, fieldDef) {
@@ -7241,24 +7398,54 @@ var ClientImpl = class _ClientImpl {
7241
7398
  return txBuilder.execute((tx) => execute(tx));
7242
7399
  }
7243
7400
  }
7244
- get $procedures() {
7401
+ get $procs() {
7245
7402
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
7246
- acc[name] = (...args) => this.handleProc(name, args);
7403
+ acc[name] = (input) => this.handleProc(name, input);
7247
7404
  return acc;
7248
7405
  }, {});
7249
7406
  }
7250
- async handleProc(name, args) {
7407
+ async handleProc(name, input) {
7251
7408
  if (!("procedures" in this.$options) || !this.$options || typeof this.$options.procedures !== "object") {
7252
7409
  throw createConfigError("Procedures are not configured for the client.");
7253
7410
  }
7411
+ const procDef = (this.$schema.procedures ?? {})[name];
7412
+ if (!procDef) {
7413
+ throw createConfigError(`Procedure "${name}" is not defined in schema.`);
7414
+ }
7254
7415
  const procOptions = this.$options.procedures;
7255
7416
  if (!procOptions[name] || typeof procOptions[name] !== "function") {
7256
- throw new Error(`Procedure "${name}" does not have a handler configured.`);
7257
- }
7258
- return procOptions[name].apply(this, [
7259
- this,
7260
- ...args
7261
- ]);
7417
+ throw createConfigError(`Procedure "${name}" does not have a handler configured.`);
7418
+ }
7419
+ const inputValidator = new InputValidator(this);
7420
+ const validatedInput = inputValidator.validateProcedureInput(name, input);
7421
+ const handler = procOptions[name];
7422
+ const invokeWithClient = /* @__PURE__ */ __name(async (client, _input) => {
7423
+ let proceed = /* @__PURE__ */ __name(async (nextInput) => {
7424
+ const sanitizedNextInput = nextInput && typeof nextInput === "object" && !Array.isArray(nextInput) ? nextInput : {};
7425
+ return handler({
7426
+ client,
7427
+ ...sanitizedNextInput
7428
+ });
7429
+ }, "proceed");
7430
+ const plugins = [
7431
+ ...client.$options?.plugins ?? []
7432
+ ];
7433
+ for (const plugin of plugins) {
7434
+ const onProcedure = plugin.onProcedure;
7435
+ if (onProcedure) {
7436
+ const _proceed = proceed;
7437
+ proceed = /* @__PURE__ */ __name((nextInput) => onProcedure({
7438
+ client,
7439
+ name,
7440
+ mutation: !!procDef.mutation,
7441
+ input: nextInput,
7442
+ proceed: /* @__PURE__ */ __name((finalInput) => _proceed(finalInput), "proceed")
7443
+ }), "proceed");
7444
+ }
7445
+ }
7446
+ return proceed(_input);
7447
+ }, "invokeWithClient");
7448
+ return invokeWithClient(this, validatedInput);
7262
7449
  }
7263
7450
  async $connect() {
7264
7451
  await this.kysely.connection().execute(async (conn) => {
@@ -7465,7 +7652,10 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
7465
7652
  }, "aggregate"),
7466
7653
  groupBy: /* @__PURE__ */ __name((args) => {
7467
7654
  return createPromise("groupBy", "groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
7468
- }, "groupBy")
7655
+ }, "groupBy"),
7656
+ exists: /* @__PURE__ */ __name((args) => {
7657
+ return createPromise("exists", "exists", args, new ExistsOperationHandler(client, model, inputValidator), false);
7658
+ }, "exists")
7469
7659
  };
7470
7660
  }
7471
7661
  __name(createModelCrudHandler, "createModelCrudHandler");
@@ -7897,6 +8087,7 @@ var MatchingExpressionVisitor = class extends ExpressionVisitor {
7897
8087
  CRUD_EXT,
7898
8088
  DbNull,
7899
8089
  DbNullClass,
8090
+ InputValidator,
7900
8091
  JsonNull,
7901
8092
  JsonNullClass,
7902
8093
  KyselyUtils,