@zenstackhq/orm 3.1.0 → 3.2.0

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
@@ -617,6 +617,7 @@ import { match as match5 } from "ts-pattern";
617
617
  import { invariant as invariant3 } from "@zenstackhq/common-helpers";
618
618
  import Decimal from "decimal.js";
619
619
  import { sql as sql2 } from "kysely";
620
+ import { parse as parsePostgresArray } from "postgres-array";
620
621
  import { match as match3 } from "ts-pattern";
621
622
  import z from "zod";
622
623
 
@@ -664,7 +665,7 @@ var BaseCrudDialect = class {
664
665
  transformPrimitive(value, _type, _forArrayField) {
665
666
  return value;
666
667
  }
667
- transformOutput(value, _type) {
668
+ transformOutput(value, _type, _array) {
668
669
  return value;
669
670
  }
670
671
  // #region common query builders
@@ -1521,6 +1522,9 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1521
1522
  } else if (Array.isArray(value)) {
1522
1523
  if (type === "Json" && !forArrayField) {
1523
1524
  return JSON.stringify(value);
1525
+ }
1526
+ if (isEnum(this.schema, type)) {
1527
+ return this.eb.cast(sql2`ARRAY[${sql2.join(value.map((v) => this.transformPrimitive(v, type, false)), sql2.raw(","))}]`, this.createSchemaQualifiedEnumType(type, true));
1524
1528
  } else {
1525
1529
  return value.map((v) => this.transformPrimitive(v, type, false));
1526
1530
  }
@@ -1534,11 +1538,29 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1534
1538
  }).otherwise(() => value);
1535
1539
  }
1536
1540
  }
1537
- transformOutput(value, type) {
1541
+ createSchemaQualifiedEnumType(type, array) {
1542
+ let qualified = type;
1543
+ const enumDef = getEnum(this.schema, type);
1544
+ if (enumDef) {
1545
+ const schemaAttr = enumDef.attributes?.find((attr) => attr.name === "@@schema");
1546
+ if (schemaAttr) {
1547
+ const mapArg = schemaAttr.args?.find((arg) => arg.name === "map");
1548
+ if (mapArg && mapArg.value.kind === "literal") {
1549
+ const schemaName = mapArg.value.value;
1550
+ qualified = `"${schemaName}"."${type}"`;
1551
+ }
1552
+ } else {
1553
+ const defaultSchema = this.schema.provider.defaultSchema ?? "public";
1554
+ qualified = `"${defaultSchema}"."${type}"`;
1555
+ }
1556
+ }
1557
+ return array ? sql2.raw(`${qualified}[]`) : sql2.raw(qualified);
1558
+ }
1559
+ transformOutput(value, type, array) {
1538
1560
  if (value === null || value === void 0) {
1539
1561
  return value;
1540
1562
  }
1541
- return match3(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));
1563
+ return match3(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));
1542
1564
  }
1543
1565
  transformOutputBigInt(value) {
1544
1566
  if (typeof value === "bigint") {
@@ -1571,6 +1593,15 @@ var PostgresCrudDialect = class extends BaseCrudDialect {
1571
1593
  transformOutputBytes(value) {
1572
1594
  return Buffer.isBuffer(value) ? Uint8Array.from(value) : typeof value === "string" && value.startsWith("\\x") ? Uint8Array.from(Buffer.from(value.slice(2), "hex")) : value;
1573
1595
  }
1596
+ transformOutputEnum(value, array) {
1597
+ if (array && typeof value === "string") {
1598
+ try {
1599
+ return parsePostgresArray(value);
1600
+ } catch {
1601
+ }
1602
+ }
1603
+ return value;
1604
+ }
1574
1605
  buildRelationSelection(query, model, relationField, parentAlias, payload) {
1575
1606
  const relationResultName = `${parentAlias}$${relationField}`;
1576
1607
  const joinedQuery = this.buildRelationJSON(model, query, relationField, parentAlias, payload, relationResultName);
@@ -1801,13 +1832,13 @@ var SqliteCrudDialect = class extends BaseCrudDialect {
1801
1832
  return match4(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);
1802
1833
  }
1803
1834
  }
1804
- transformOutput(value, type) {
1835
+ transformOutput(value, type, array) {
1805
1836
  if (value === null || value === void 0) {
1806
1837
  return value;
1807
1838
  } else if (this.schema.typeDefs && type in this.schema.typeDefs) {
1808
1839
  return this.transformOutputJson(value);
1809
1840
  } else {
1810
- return match4(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));
1841
+ return match4(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));
1811
1842
  }
1812
1843
  }
1813
1844
  transformOutputDecimal(value) {
@@ -2087,6 +2118,21 @@ var BaseOperationHandler = class {
2087
2118
  select: this.makeIdSelect(model)
2088
2119
  });
2089
2120
  }
2121
+ async existsNonUnique(kysely, model, filter) {
2122
+ const query = kysely.selectNoFrom((eb) => eb.exists(this.dialect.buildSelectModel(model, model).select(sql4.lit(1).as("$t")).where(() => this.dialect.buildFilter(model, model, filter))).as("exists")).modifyEnd(this.makeContextComment({
2123
+ model,
2124
+ operation: "read"
2125
+ }));
2126
+ let result = [];
2127
+ const compiled = kysely.getExecutor().compileQuery(query.toOperationNode(), createQueryId());
2128
+ try {
2129
+ const r = await kysely.getExecutor().executeQuery(compiled);
2130
+ result = r.rows;
2131
+ } catch (err) {
2132
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiled.sql, compiled.parameters);
2133
+ }
2134
+ return !!result[0]?.exists;
2135
+ }
2090
2136
  async read(kysely, model, args) {
2091
2137
  let query = this.dialect.buildSelectModel(model, model);
2092
2138
  if (args) {
@@ -2110,7 +2156,7 @@ var BaseOperationHandler = class {
2110
2156
  const r = await kysely.getExecutor().executeQuery(compiled);
2111
2157
  result = r.rows;
2112
2158
  } catch (err) {
2113
- throw createDBQueryError("Failed to execute query", err, compiled.sql, compiled.parameters);
2159
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiled.sql, compiled.parameters);
2114
2160
  }
2115
2161
  return result;
2116
2162
  }
@@ -3698,6 +3744,18 @@ var FindOperationHandler = class extends BaseOperationHandler {
3698
3744
  }
3699
3745
  };
3700
3746
 
3747
+ // src/client/crud/operations/exists.ts
3748
+ var ExistsOperationHandler = class extends BaseOperationHandler {
3749
+ static {
3750
+ __name(this, "ExistsOperationHandler");
3751
+ }
3752
+ async handle(_operation, args) {
3753
+ const normalizedArgs = this.normalizeArgs(args);
3754
+ const parsedArgs = this.inputValidator.validateExistsArgs(this.model, normalizedArgs);
3755
+ return await this.existsNonUnique(this.client.$qb, this.model, parsedArgs?.where);
3756
+ }
3757
+ };
3758
+
3701
3759
  // src/client/crud/operations/group-by.ts
3702
3760
  import { match as match10 } from "ts-pattern";
3703
3761
  var GroupByOperationHandler = class extends BaseOperationHandler {
@@ -4314,9 +4372,96 @@ var InputValidator = class {
4314
4372
  get extraValidationsEnabled() {
4315
4373
  return this.client.$options.validateInput !== false;
4316
4374
  }
4375
+ validateProcedureInput(proc, input) {
4376
+ const procDef = (this.schema.procedures ?? {})[proc];
4377
+ invariant7(procDef, `Procedure "${proc}" not found in schema`);
4378
+ const params = Object.values(procDef.params ?? {});
4379
+ if (typeof input === "undefined") {
4380
+ if (params.length === 0) {
4381
+ return void 0;
4382
+ }
4383
+ if (params.every((p) => p.optional)) {
4384
+ return void 0;
4385
+ }
4386
+ throw createInvalidInputError("Missing procedure arguments", `$procs.${proc}`);
4387
+ }
4388
+ if (typeof input !== "object") {
4389
+ throw createInvalidInputError("Procedure input must be an object", `$procs.${proc}`);
4390
+ }
4391
+ const envelope = input;
4392
+ const argsPayload = Object.prototype.hasOwnProperty.call(envelope, "args") ? envelope.args : void 0;
4393
+ if (params.length === 0) {
4394
+ if (typeof argsPayload === "undefined") {
4395
+ return input;
4396
+ }
4397
+ if (!argsPayload || typeof argsPayload !== "object" || Array.isArray(argsPayload)) {
4398
+ throw createInvalidInputError("Procedure `args` must be an object", `$procs.${proc}`);
4399
+ }
4400
+ if (Object.keys(argsPayload).length === 0) {
4401
+ return input;
4402
+ }
4403
+ throw createInvalidInputError("Procedure does not accept arguments", `$procs.${proc}`);
4404
+ }
4405
+ if (typeof argsPayload === "undefined") {
4406
+ if (params.every((p) => p.optional)) {
4407
+ return input;
4408
+ }
4409
+ throw createInvalidInputError("Missing procedure arguments", `$procs.${proc}`);
4410
+ }
4411
+ if (!argsPayload || typeof argsPayload !== "object" || Array.isArray(argsPayload)) {
4412
+ throw createInvalidInputError("Procedure `args` must be an object", `$procs.${proc}`);
4413
+ }
4414
+ const obj = argsPayload;
4415
+ for (const param of params) {
4416
+ const value = obj[param.name];
4417
+ if (!Object.prototype.hasOwnProperty.call(obj, param.name)) {
4418
+ if (param.optional) {
4419
+ continue;
4420
+ }
4421
+ throw createInvalidInputError(`Missing procedure argument: ${param.name}`, `$procs.${proc}`);
4422
+ }
4423
+ if (typeof value === "undefined") {
4424
+ if (param.optional) {
4425
+ continue;
4426
+ }
4427
+ throw createInvalidInputError(`Invalid procedure argument: ${param.name} is required`, `$procs.${proc}`);
4428
+ }
4429
+ const schema = this.makeProcedureParamSchema(param);
4430
+ const parsed = schema.safeParse(value);
4431
+ if (!parsed.success) {
4432
+ throw createInvalidInputError(`Invalid procedure argument: ${param.name}: ${formatError(parsed.error)}`, `$procs.${proc}`);
4433
+ }
4434
+ }
4435
+ return input;
4436
+ }
4437
+ makeProcedureParamSchema(param) {
4438
+ let schema;
4439
+ if (isTypeDef(this.schema, param.type)) {
4440
+ schema = this.makeTypeDefSchema(param.type);
4441
+ } else if (isEnum(this.schema, param.type)) {
4442
+ schema = this.makeEnumSchema(param.type);
4443
+ } else if (param.type in (this.schema.models ?? {})) {
4444
+ schema = z3.record(z3.string(), z3.unknown());
4445
+ } else {
4446
+ schema = this.makeScalarSchema(param.type);
4447
+ if (schema instanceof z3.ZodUnknown) {
4448
+ throw createInternalError(`Unsupported procedure parameter type: ${param.type}`);
4449
+ }
4450
+ }
4451
+ if (param.array) {
4452
+ schema = schema.array();
4453
+ }
4454
+ if (param.optional) {
4455
+ schema = schema.optional();
4456
+ }
4457
+ return schema;
4458
+ }
4317
4459
  validateFindArgs(model, args, options) {
4318
4460
  return this.validate(model, "find", options, (model2, options2) => this.makeFindSchema(model2, options2), args);
4319
4461
  }
4462
+ validateExistsArgs(model, args) {
4463
+ return this.validate(model, "exists", void 0, (model2) => this.makeExistsSchema(model2), args);
4464
+ }
4320
4465
  validateCreateArgs(model, args) {
4321
4466
  return this.validate(model, "create", void 0, (model2) => this.makeCreateSchema(model2), args);
4322
4467
  }
@@ -4421,6 +4566,11 @@ var InputValidator = class {
4421
4566
  }
4422
4567
  return result;
4423
4568
  }
4569
+ makeExistsSchema(model) {
4570
+ return z3.strictObject({
4571
+ where: this.makeWhereSchema(model, false).optional()
4572
+ }).optional();
4573
+ }
4424
4574
  makeScalarSchema(type, attributes) {
4425
4575
  if (this.schema.typeDefs && type in this.schema.typeDefs) {
4426
4576
  return this.makeTypeDefSchema(type);
@@ -4482,8 +4632,11 @@ var InputValidator = class {
4482
4632
  fieldSchema
4483
4633
  ];
4484
4634
  })));
4485
- const finalSchema = z3.custom((v) => {
4486
- return schema.safeParse(v).success;
4635
+ const finalSchema = z3.any().superRefine((value, ctx) => {
4636
+ const parseResult = schema.safeParse(value);
4637
+ if (!parseResult.success) {
4638
+ parseResult.error.issues.forEach((issue) => ctx.addIssue(issue));
4639
+ }
4487
4640
  });
4488
4641
  this.setSchemaCache(key, finalSchema);
4489
4642
  return finalSchema;
@@ -4522,7 +4675,7 @@ var InputValidator = class {
4522
4675
  const enumDef = getEnum(this.schema, fieldDef.type);
4523
4676
  if (enumDef) {
4524
4677
  if (Object.keys(enumDef.values).length > 0) {
4525
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations);
4678
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, withAggregations, !!fieldDef.array);
4526
4679
  }
4527
4680
  } else if (fieldDef.array) {
4528
4681
  fieldSchema = this.makeArrayFilterSchema(fieldDef.type);
@@ -4546,7 +4699,7 @@ var InputValidator = class {
4546
4699
  const enumDef = getEnum(this.schema, def.type);
4547
4700
  if (enumDef) {
4548
4701
  if (Object.keys(enumDef.values).length > 0) {
4549
- fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false);
4702
+ fieldSchema = this.makeEnumFilterSchema(enumDef, !!def.optional, false, false);
4550
4703
  } else {
4551
4704
  fieldSchema = z3.never();
4552
4705
  }
@@ -4561,7 +4714,9 @@ var InputValidator = class {
4561
4714
  }
4562
4715
  }
4563
4716
  }
4564
- fields["$expr"] = z3.custom((v) => typeof v === "function").optional();
4717
+ fields["$expr"] = z3.custom((v) => typeof v === "function", {
4718
+ error: '"$expr" must be a function'
4719
+ }).optional();
4565
4720
  fields["AND"] = this.orArray(z3.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
4566
4721
  fields["OR"] = z3.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)).array().optional();
4567
4722
  fields["NOT"] = this.orArray(z3.lazy(() => this.makeWhereSchema(model, false, withoutRelationFields)), true).optional();
@@ -4594,15 +4749,13 @@ var InputValidator = class {
4594
4749
  if (this.isTypeDefType(fieldDef.type)) {
4595
4750
  fieldSchemas[fieldName] = this.makeTypedJsonFilterSchema(fieldDef.type, !!fieldDef.optional, !!fieldDef.array).optional();
4596
4751
  } else {
4597
- if (fieldDef.array) {
4752
+ const enumDef = getEnum(this.schema, fieldDef.type);
4753
+ if (enumDef) {
4754
+ fieldSchemas[fieldName] = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, false, !!fieldDef.array).optional();
4755
+ } else if (fieldDef.array) {
4598
4756
  fieldSchemas[fieldName] = this.makeArrayFilterSchema(fieldDef.type).optional();
4599
4757
  } else {
4600
- const enumDef = getEnum(this.schema, fieldDef.type);
4601
- if (enumDef) {
4602
- fieldSchemas[fieldName] = this.makeEnumFilterSchema(enumDef, !!fieldDef.optional, false).optional();
4603
- } else {
4604
- fieldSchemas[fieldName] = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, false).optional();
4605
- }
4758
+ fieldSchemas[fieldName] = this.makePrimitiveFilterSchema(fieldDef.type, !!fieldDef.optional, false).optional();
4606
4759
  }
4607
4760
  }
4608
4761
  }
@@ -4630,9 +4783,12 @@ var InputValidator = class {
4630
4783
  isTypeDefType(type) {
4631
4784
  return this.schema.typeDefs && type in this.schema.typeDefs;
4632
4785
  }
4633
- makeEnumFilterSchema(enumDef, optional, withAggregations) {
4786
+ makeEnumFilterSchema(enumDef, optional, withAggregations, array) {
4634
4787
  const baseSchema = z3.enum(Object.keys(enumDef.values));
4635
- const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z3.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations)), [
4788
+ if (array) {
4789
+ return this.internalMakeArrayFilterSchema(baseSchema);
4790
+ }
4791
+ const components = this.makeCommonPrimitiveFilterComponents(baseSchema, optional, () => z3.lazy(() => this.makeEnumFilterSchema(enumDef, optional, withAggregations, array)), [
4636
4792
  "equals",
4637
4793
  "in",
4638
4794
  "notIn",
@@ -4648,11 +4804,14 @@ var InputValidator = class {
4648
4804
  ]);
4649
4805
  }
4650
4806
  makeArrayFilterSchema(type) {
4807
+ return this.internalMakeArrayFilterSchema(this.makeScalarSchema(type));
4808
+ }
4809
+ internalMakeArrayFilterSchema(elementSchema) {
4651
4810
  return z3.strictObject({
4652
- equals: this.makeScalarSchema(type).array().optional(),
4653
- has: this.makeScalarSchema(type).optional(),
4654
- hasEvery: this.makeScalarSchema(type).array().optional(),
4655
- hasSome: this.makeScalarSchema(type).array().optional(),
4811
+ equals: elementSchema.array().optional(),
4812
+ has: elementSchema.optional(),
4813
+ hasEvery: elementSchema.array().optional(),
4814
+ hasSome: elementSchema.array().optional(),
4656
4815
  isEmpty: z3.boolean().optional()
4657
4816
  });
4658
4817
  }
@@ -5712,14 +5871,16 @@ var QueryNameMapper = class extends OperationNodeTransformer {
5712
5871
  return super.transformSelectQuery(node);
5713
5872
  }
5714
5873
  const processedFroms = node.from.froms.map((from) => this.processSelectTable(from));
5715
- const processedJoins = this.withScopes([
5874
+ const processedJoins = [];
5875
+ const cumulativeScopes = [
5716
5876
  ...processedFroms.map(({ scope }) => scope)
5717
- ], () => (node.joins ?? []).map((join) => this.processSelectTable(join.table)));
5718
- const scopes = [
5719
- ...processedFroms.map(({ scope }) => scope),
5720
- ...processedJoins.map(({ scope }) => scope)
5721
5877
  ];
5722
- return this.withScopes(scopes, () => {
5878
+ for (const join of node.joins ?? []) {
5879
+ const processedJoin = this.withScopes(cumulativeScopes, () => this.processSelectTable(join.table));
5880
+ processedJoins.push(processedJoin);
5881
+ cumulativeScopes.push(processedJoin.scope);
5882
+ }
5883
+ return this.withScopes(cumulativeScopes, () => {
5723
5884
  const joins = node.joins ? node.joins.map((join, i) => ({
5724
5885
  ...join,
5725
5886
  table: processedJoins[i].node,
@@ -6054,9 +6215,9 @@ var QueryNameMapper = class extends OperationNodeTransformer {
6054
6215
  let schema = this.schema.provider.defaultSchema ?? "public";
6055
6216
  const schemaAttr = this.schema.models[model]?.attributes?.find((attr) => attr.name === "@@schema");
6056
6217
  if (schemaAttr) {
6057
- const nameArg = schemaAttr.args?.find((arg) => arg.name === "map");
6058
- if (nameArg && nameArg.value.kind === "literal") {
6059
- schema = nameArg.value.value;
6218
+ const mapArg = schemaAttr.args?.find((arg) => arg.name === "map");
6219
+ if (mapArg && mapArg.value.kind === "literal") {
6220
+ schema = mapArg.value.value;
6060
6221
  }
6061
6222
  }
6062
6223
  return schema;
@@ -6307,7 +6468,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
6307
6468
  if (err instanceof ORMError) {
6308
6469
  throw err;
6309
6470
  } else {
6310
- throw createDBQueryError("Failed to execute query", err, compiledQuery.sql, compiledQuery.parameters);
6471
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiledQuery.sql, compiledQuery.parameters);
6311
6472
  }
6312
6473
  }
6313
6474
  });
@@ -6547,7 +6708,7 @@ var ZenStackQueryExecutor = class _ZenStackQueryExecutor extends DefaultQueryExe
6547
6708
  try {
6548
6709
  return await connection.executeQuery(compiledQuery);
6549
6710
  } catch (err) {
6550
- throw createDBQueryError("Failed to execute query", err, compiledQuery.sql, compiledQuery.parameters);
6711
+ throw createDBQueryError(`Failed to execute query: ${err}`, err, compiledQuery.sql, compiledQuery.parameters);
6551
6712
  }
6552
6713
  }
6553
6714
  };
@@ -7005,7 +7166,7 @@ var ResultProcessor = class {
7005
7166
  }
7006
7167
  if (key.startsWith(DELEGATE_JOINED_FIELD_PREFIX)) {
7007
7168
  if (value) {
7008
- const subRow = this.dialect.transformOutput(value, "Json");
7169
+ const subRow = this.dialect.transformOutput(value, "Json", false);
7009
7170
  const subModel = key.slice(DELEGATE_JOINED_FIELD_PREFIX.length);
7010
7171
  const idValues = getIdValues(this.schema, subModel, subRow);
7011
7172
  if (Object.values(idValues).some((v) => v === null || v === void 0)) {
@@ -7039,10 +7200,10 @@ var ResultProcessor = class {
7039
7200
  processFieldValue(value, fieldDef) {
7040
7201
  const type = fieldDef.type;
7041
7202
  if (Array.isArray(value)) {
7042
- value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type));
7203
+ value.forEach((v, i) => value[i] = this.dialect.transformOutput(v, type, false));
7043
7204
  return value;
7044
7205
  } else {
7045
- return this.dialect.transformOutput(value, type);
7206
+ return this.dialect.transformOutput(value, type, !!fieldDef.array);
7046
7207
  }
7047
7208
  }
7048
7209
  processRelation(value, fieldDef) {
@@ -7200,24 +7361,54 @@ var ClientImpl = class _ClientImpl {
7200
7361
  return txBuilder.execute((tx) => execute(tx));
7201
7362
  }
7202
7363
  }
7203
- get $procedures() {
7364
+ get $procs() {
7204
7365
  return Object.keys(this.$schema.procedures ?? {}).reduce((acc, name) => {
7205
- acc[name] = (...args) => this.handleProc(name, args);
7366
+ acc[name] = (input) => this.handleProc(name, input);
7206
7367
  return acc;
7207
7368
  }, {});
7208
7369
  }
7209
- async handleProc(name, args) {
7370
+ async handleProc(name, input) {
7210
7371
  if (!("procedures" in this.$options) || !this.$options || typeof this.$options.procedures !== "object") {
7211
7372
  throw createConfigError("Procedures are not configured for the client.");
7212
7373
  }
7374
+ const procDef = (this.$schema.procedures ?? {})[name];
7375
+ if (!procDef) {
7376
+ throw createConfigError(`Procedure "${name}" is not defined in schema.`);
7377
+ }
7213
7378
  const procOptions = this.$options.procedures;
7214
7379
  if (!procOptions[name] || typeof procOptions[name] !== "function") {
7215
- throw new Error(`Procedure "${name}" does not have a handler configured.`);
7216
- }
7217
- return procOptions[name].apply(this, [
7218
- this,
7219
- ...args
7220
- ]);
7380
+ throw createConfigError(`Procedure "${name}" does not have a handler configured.`);
7381
+ }
7382
+ const inputValidator = new InputValidator(this);
7383
+ const validatedInput = inputValidator.validateProcedureInput(name, input);
7384
+ const handler = procOptions[name];
7385
+ const invokeWithClient = /* @__PURE__ */ __name(async (client, _input) => {
7386
+ let proceed = /* @__PURE__ */ __name(async (nextInput) => {
7387
+ const sanitizedNextInput = nextInput && typeof nextInput === "object" && !Array.isArray(nextInput) ? nextInput : {};
7388
+ return handler({
7389
+ client,
7390
+ ...sanitizedNextInput
7391
+ });
7392
+ }, "proceed");
7393
+ const plugins = [
7394
+ ...client.$options?.plugins ?? []
7395
+ ];
7396
+ for (const plugin of plugins) {
7397
+ const onProcedure = plugin.onProcedure;
7398
+ if (onProcedure) {
7399
+ const _proceed = proceed;
7400
+ proceed = /* @__PURE__ */ __name((nextInput) => onProcedure({
7401
+ client,
7402
+ name,
7403
+ mutation: !!procDef.mutation,
7404
+ input: nextInput,
7405
+ proceed: /* @__PURE__ */ __name((finalInput) => _proceed(finalInput), "proceed")
7406
+ }), "proceed");
7407
+ }
7408
+ }
7409
+ return proceed(_input);
7410
+ }, "invokeWithClient");
7411
+ return invokeWithClient(this, validatedInput);
7221
7412
  }
7222
7413
  async $connect() {
7223
7414
  await this.kysely.connection().execute(async (conn) => {
@@ -7424,7 +7615,10 @@ function createModelCrudHandler(client, model, inputValidator, resultProcessor)
7424
7615
  }, "aggregate"),
7425
7616
  groupBy: /* @__PURE__ */ __name((args) => {
7426
7617
  return createPromise("groupBy", "groupBy", args, new GroupByOperationHandler(client, model, inputValidator), true);
7427
- }, "groupBy")
7618
+ }, "groupBy"),
7619
+ exists: /* @__PURE__ */ __name((args) => {
7620
+ return createPromise("exists", "exists", args, new ExistsOperationHandler(client, model, inputValidator), false);
7621
+ }, "exists")
7428
7622
  };
7429
7623
  }
7430
7624
  __name(createModelCrudHandler, "createModelCrudHandler");
@@ -7855,6 +8049,7 @@ export {
7855
8049
  CRUD_EXT,
7856
8050
  DbNull,
7857
8051
  DbNullClass,
8052
+ InputValidator,
7858
8053
  JsonNull,
7859
8054
  JsonNullClass,
7860
8055
  kysely_utils_exports as KyselyUtils,