@zenstackhq/runtime 3.0.0-alpha.1 → 3.0.0-alpha.10

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.
Files changed (40) hide show
  1. package/dist/{contract-DguafRNB.d.cts → contract-BiU0iYAh.d.cts} +813 -709
  2. package/dist/{contract-DguafRNB.d.ts → contract-BiU0iYAh.d.ts} +813 -709
  3. package/dist/{utils/pg-utils.cjs → helpers.cjs} +8 -16
  4. package/dist/helpers.cjs.map +1 -0
  5. package/dist/helpers.d.cts +1 -0
  6. package/dist/helpers.d.ts +1 -0
  7. package/dist/helpers.js +6 -0
  8. package/dist/helpers.js.map +1 -0
  9. package/dist/index.cjs +517 -328
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +28 -6
  12. package/dist/index.d.ts +28 -6
  13. package/dist/index.js +466 -282
  14. package/dist/index.js.map +1 -1
  15. package/dist/plugins/policy.cjs +115 -104
  16. package/dist/plugins/policy.cjs.map +1 -1
  17. package/dist/plugins/policy.d.cts +2 -4
  18. package/dist/plugins/policy.d.ts +2 -4
  19. package/dist/plugins/policy.js +87 -66
  20. package/dist/plugins/policy.js.map +1 -1
  21. package/dist/schema.cjs.map +1 -1
  22. package/dist/schema.js.map +1 -1
  23. package/package.json +23 -46
  24. package/dist/client.cjs +0 -6094
  25. package/dist/client.cjs.map +0 -1
  26. package/dist/client.d.cts +0 -19
  27. package/dist/client.d.ts +0 -19
  28. package/dist/client.js +0 -6060
  29. package/dist/client.js.map +0 -1
  30. package/dist/utils/pg-utils.cjs.map +0 -1
  31. package/dist/utils/pg-utils.d.cts +0 -8
  32. package/dist/utils/pg-utils.d.ts +0 -8
  33. package/dist/utils/pg-utils.js +0 -16
  34. package/dist/utils/pg-utils.js.map +0 -1
  35. package/dist/utils/sqlite-utils.cjs +0 -55
  36. package/dist/utils/sqlite-utils.cjs.map +0 -1
  37. package/dist/utils/sqlite-utils.d.cts +0 -8
  38. package/dist/utils/sqlite-utils.d.ts +0 -8
  39. package/dist/utils/sqlite-utils.js +0 -22
  40. package/dist/utils/sqlite-utils.js.map +0 -1
@@ -1,9 +1,8 @@
1
- import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetFields, FieldHasDefault, GetFieldType, FieldIsOptional, RelationFields, RelationFieldType, FieldIsArray, GetEnums, GetEnum, BuiltinType, NonRelationFields, GetModel, FieldDef, GetField, FieldIsRelationArray, RelationInfo, FieldType, FieldIsRelation, DataSourceProviderType, ProcedureDef, DataSourceProvider } from '@zenstackhq/sdk/schema';
2
1
  import Decimal, { Decimal as Decimal$1 } from 'decimal.js';
3
- import { Kysely, Generated, ExpressionBuilder, OperandExpression, SqlBool, SelectQueryBuilder, Expression, ExpressionWrapper, RootOperationNode, QueryResult, UnknownRow, OperationNode, KyselyConfig, SqliteDialectConfig, PostgresDialectConfig } from 'kysely';
4
- import { Optional } from 'utility-types';
5
- import { Model } from '@zenstackhq/language/ast';
2
+ import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetFields, FieldHasDefault, GetFieldType, FieldIsOptional, NonRelationFields, RelationFields, FieldIsArray, RelationFieldType, GetField, FieldIsRelation, GetEnums, GetEnum, BuiltinType, GetModel, FieldDef, FieldIsRelationArray, FieldType, RelationInfo, DataSourceProviderType, DataSourceProvider, ProcedureDef } from '@zenstackhq/sdk/schema';
3
+ import { Generated, Kysely, ExpressionBuilder, OperandExpression, SqlBool, SelectQueryBuilder, Expression, ExpressionWrapper, RootOperationNode, QueryResult, UnknownRow, OperationNode, SqliteDialectConfig, PostgresDialectConfig, KyselyConfig } from 'kysely';
6
4
 
5
+ type Optional<T extends object, K extends keyof T = keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
7
6
  type NullableIf<T, Condition extends boolean> = Condition extends true ? T | null : T;
8
7
  type WrapType<T, Optional = false, Array = false> = Optional extends true ? T | null : Array extends true ? T[] : T;
9
8
  type MapBaseType$1<T> = T extends 'String' ? string : T extends 'Boolean' ? boolean : T extends 'Int' | 'Float' ? number : T extends 'BigInt' ? bigint : T extends 'Decimal' ? Decimal : T extends 'DateTime' ? Date : T extends 'Json' ? JsonValue : unknown;
@@ -24,10 +23,13 @@ type AtLeast<O extends object, K extends string> = NoExpand<O extends unknown ?
24
23
  type Without<T, U> = {
25
24
  [P in Exclude<keyof T, keyof U>]?: never;
26
25
  };
27
- type XOR<T, U> = T extends object ? U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U : T;
26
+ type XOR<T, U> = T extends object ? (U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U) : T;
28
27
  type MaybePromise<T> = T | Promise<T>;
29
28
  type PrependParameter<Param, Func> = Func extends (...args: any[]) => infer R ? (p: Param, ...args: Parameters<Func>) => R : never;
30
29
  type OrUndefinedIf<T, Condition extends boolean> = Condition extends true ? T | undefined : T;
30
+ type UnwrapTuplePromises<T extends readonly unknown[]> = {
31
+ [K in keyof T]: Awaited<T[K]>;
32
+ };
31
33
 
32
34
  type ToKyselySchema<Schema extends SchemaDef> = {
33
35
  [Model in GetModels<Schema>]: ToKyselyTable<Schema, Model>;
@@ -157,7 +159,7 @@ type Distinct<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
157
159
  type Cursor<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
158
160
  cursor?: WhereUniqueInput<Schema, Model>;
159
161
  };
160
- type Select<Schema extends SchemaDef, Model extends GetModels<Schema>, AllowCount extends Boolean, AllowRelation extends boolean = true> = {
162
+ type Select<Schema extends SchemaDef, Model extends GetModels<Schema>, AllowCount extends boolean, AllowRelation extends boolean = true> = {
161
163
  [Key in NonRelationFields<Schema, Model>]?: true;
162
164
  } & (AllowRelation extends true ? Include<Schema, Model> : {}) & // relation fields
163
165
  (AllowCount extends true ? {
@@ -202,7 +204,7 @@ type OptionalFieldsForCreate<Schema extends SchemaDef, Model extends GetModels<S
202
204
  };
203
205
  type GetRelation<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetFields<Schema, Model>> = GetField<Schema, Model, Field>['relation'];
204
206
  type OppositeRelation<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetFields<Schema, Model>, FT = FieldType<Schema, Model, Field>> = FT extends GetModels<Schema> ? GetRelation<Schema, Model, Field> extends RelationInfo ? GetRelation<Schema, Model, Field>['opposite'] extends GetFields<Schema, FT> ? Schema['models'][FT]['fields'][GetRelation<Schema, Model, Field>['opposite']]['relation'] : never : never : never;
205
- type OppositeRelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetFields<Schema, Model>, Opposite = OppositeRelation<Schema, Model, Field>> = Opposite extends RelationInfo ? Opposite['fields'] extends string[] ? Opposite['fields'] : [] : [];
207
+ type OppositeRelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetFields<Schema, Model>, Opposite = OppositeRelation<Schema, Model, Field>> = Opposite extends RelationInfo ? (Opposite['fields'] extends string[] ? Opposite['fields'] : []) : [];
206
208
  type OppositeRelationAndFK<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetFields<Schema, Model>, FT = FieldType<Schema, Model, Field>, Relation = GetField<Schema, Model, Field>['relation'], Opposite = Relation extends RelationInfo ? Relation['opposite'] : never> = FT extends GetModels<Schema> ? Opposite extends GetFields<Schema, FT> ? Opposite | OppositeRelationFields<Schema, Model, Field>[number] : never : never;
207
209
  type FindArgs<Schema extends SchemaDef, Model extends GetModels<Schema>, Collection extends boolean, AllowFilter extends boolean = true> = (Collection extends true ? {
208
210
  skip?: number;
@@ -220,8 +222,8 @@ type CreateArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
220
222
  include?: Include<Schema, Model>;
221
223
  omit?: OmitFields<Schema, Model>;
222
224
  };
223
- type CreateManyArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateManyPayload<Schema, Model>;
224
- type CreateManyAndReturnArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateManyPayload<Schema, Model> & {
225
+ type CreateManyArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateManyInput<Schema, Model>;
226
+ type CreateManyAndReturnArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateManyInput<Schema, Model> & {
225
227
  select?: Select<Schema, Model, false, false>;
226
228
  omit?: OmitFields<Schema, Model>;
227
229
  };
@@ -244,19 +246,22 @@ type CreateRelationFieldPayload<Schema extends SchemaDef, Model extends GetModel
244
246
  type CreateRelationPayload<Schema extends SchemaDef, Model extends GetModels<Schema>> = OptionalWrap<Schema, Model, {
245
247
  [Key in RelationFields<Schema, Model>]: CreateRelationFieldPayload<Schema, Model, Key>;
246
248
  }>;
247
- type CreateWithFKInput<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateScalarPayload<Schema, Model> & CreateFKPayload<Schema, Model>;
249
+ type CreateWithFKInput<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateScalarPayload<Schema, Model> & CreateFKPayload<Schema, Model> & CreateWithNonOwnedRelationPayload<Schema, Model>;
248
250
  type CreateWithRelationInput<Schema extends SchemaDef, Model extends GetModels<Schema>> = CreateScalarPayload<Schema, Model> & CreateRelationPayload<Schema, Model>;
251
+ type CreateWithNonOwnedRelationPayload<Schema extends SchemaDef, Model extends GetModels<Schema>> = OptionalWrap<Schema, Model, {
252
+ [Key in NonOwnedRelationFields<Schema, Model>]: CreateRelationFieldPayload<Schema, Model, Key>;
253
+ }>;
249
254
  type ConnectOrCreatePayload<Schema extends SchemaDef, Model extends GetModels<Schema>, Without extends string = never> = {
250
255
  where: WhereUniqueInput<Schema, Model>;
251
256
  create: CreateInput<Schema, Model, Without>;
252
257
  };
253
- type CreateManyPayload<Schema extends SchemaDef, Model extends GetModels<Schema>, Without extends string = never> = {
258
+ type CreateManyInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Without extends string = never> = {
254
259
  data: OrArray<Omit<CreateScalarPayload<Schema, Model>, Without> & Omit<CreateFKPayload<Schema, Model>, Without>>;
255
260
  skipDuplicates?: boolean;
256
261
  };
257
262
  type CreateInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Without extends string = never> = XOR<Omit<CreateWithFKInput<Schema, Model>, Without>, Omit<CreateWithRelationInput<Schema, Model>, Without>>;
258
263
  type NestedCreateInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = OrArray<CreateInput<Schema, RelationFieldType<Schema, Model, Field>, OppositeRelationAndFK<Schema, Model, Field>>, FieldIsArray<Schema, Model, Field>>;
259
- type NestedCreateManyInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = CreateManyPayload<Schema, RelationFieldType<Schema, Model, Field>, OppositeRelationAndFK<Schema, Model, Field>>;
264
+ type NestedCreateManyInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = CreateManyInput<Schema, RelationFieldType<Schema, Model, Field>, OppositeRelationAndFK<Schema, Model, Field>>;
260
265
  type UpdateArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
261
266
  data: UpdateInput<Schema, Model>;
262
267
  where: WhereUniqueInput<Schema, Model>;
@@ -448,607 +453,92 @@ type NestedUpsertInput<Schema extends SchemaDef, Model extends GetModels<Schema>
448
453
  type NestedUpdateManyInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = OrArray<UpdateManyPayload<Schema, RelationFieldType<Schema, Model, Field>, OppositeRelationAndFK<Schema, Model, Field>>>;
449
454
  type NestedDeleteInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = FieldIsArray<Schema, Model, Field> extends true ? OrArray<WhereUniqueInput<Schema, RelationFieldType<Schema, Model, Field>>, true> : boolean | WhereInput<Schema, RelationFieldType<Schema, Model, Field>>;
450
455
  type NestedDeleteManyInput<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends RelationFields<Schema, Model>> = OrArray<WhereInput<Schema, RelationFieldType<Schema, Model, Field>, true>>;
451
- interface ModelOperations<Schema extends SchemaDef, Model extends GetModels<Schema>> {
456
+ type NonOwnedRelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>> = keyof {
457
+ [Key in RelationFields<Schema, Model> as GetField<Schema, Model, Key>['relation'] extends {
458
+ references: unknown[];
459
+ } ? never : Key]: Key;
460
+ };
461
+
462
+ type AuthType<Schema extends SchemaDef> = string extends GetModels<Schema> ? Record<string, unknown> : Schema['authType'] extends GetModels<Schema> ? Partial<ModelResult<Schema, Schema['authType']>> : never;
463
+
464
+ /**
465
+ * Client API methods that are not supported in transactions.
466
+ */
467
+ declare const TRANSACTION_UNSUPPORTED_METHODS: readonly ["$transaction", "$disconnect", "$use"];
468
+
469
+ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
470
+ protected readonly schema: Schema;
471
+ protected readonly options: ClientOptions<Schema>;
472
+ constructor(schema: Schema, options: ClientOptions<Schema>);
473
+ abstract get provider(): DataSourceProviderType;
474
+ transformPrimitive(value: unknown, _type: BuiltinType, _forArrayField: boolean): unknown;
475
+ abstract buildRelationSelection(query: SelectQueryBuilder<any, any, any>, model: string, relationField: string, parentAlias: string, payload: true | FindArgs<Schema, GetModels<Schema>, true>): SelectQueryBuilder<any, any, any>;
476
+ abstract buildSkipTake(query: SelectQueryBuilder<any, any, any>, skip: number | undefined, take: number | undefined): SelectQueryBuilder<any, any, any>;
477
+ buildFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, where: boolean | object | undefined): Expression<SqlBool>;
478
+ protected buildCompositeFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, key: 'AND' | 'OR' | 'NOT', payload: any): Expression<SqlBool>;
479
+ private buildRelationFilter;
480
+ private buildToOneRelationFilter;
481
+ private buildToManyRelationFilter;
482
+ private buildArrayFilter;
483
+ buildPrimitiveFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, field: string, fieldDef: FieldDef, payload: any): Expression<SqlBool>;
484
+ private buildLiteralFilter;
485
+ private buildStandardFilter;
486
+ private buildStringFilter;
487
+ private prepStringCasing;
488
+ private buildNumberFilter;
489
+ private buildBooleanFilter;
490
+ private buildDateTimeFilter;
491
+ private buildBytesFilter;
492
+ private buildEnumFilter;
493
+ buildOrderBy(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, orderBy: OrArray<OrderBy<Schema, GetModels<Schema>, boolean, boolean>> | undefined, useDefaultIfEmpty: boolean, negated: boolean): SelectQueryBuilder<any, any, any>;
494
+ private negateSort;
495
+ true(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
496
+ false(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
497
+ isTrue(expression: Expression<SqlBool>): boolean;
498
+ isFalse(expression: Expression<SqlBool>): boolean;
499
+ protected and(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
500
+ protected or(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
501
+ protected not(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): ExpressionWrapper<any, any, SqlBool>;
452
502
  /**
453
- * Returns a list of entities.
454
- * @param args - query args
455
- * @returns a list of entities
456
- *
457
- * @example
458
- * ```ts
459
- * // find all users and return all scalar fields
460
- * await client.user.findMany();
461
- *
462
- * // find all users with name 'Alex'
463
- * await client.user.findMany({
464
- * where: {
465
- * name: 'Alex'
466
- * }
467
- * });
468
- *
469
- * // select fields
470
- * await client.user.findMany({
471
- * select: {
472
- * name: true,
473
- * email: true,
474
- * }
475
- * }); // result: `Array<{ name: string, email: string }>`
476
- *
477
- * // omit fields
478
- * await client.user.findMany({
479
- * omit: {
480
- * name: true,
481
- * }
482
- * }); // result: `Array<{ id: number; email: string; ... }>`
483
- *
484
- * // include relations (and all scalar fields)
485
- * await client.user.findMany({
486
- * include: {
487
- * posts: true,
488
- * }
489
- * }); // result: `Array<{ ...; posts: Post[] }>`
490
- *
491
- * // include relations with filter
492
- * await client.user.findMany({
493
- * include: {
494
- * posts: {
495
- * where: {
496
- * published: true
497
- * }
498
- * }
499
- * }
500
- * });
501
- *
502
- * // pagination and sorting
503
- * await client.user.findMany({
504
- * skip: 10,
505
- * take: 10,
506
- * orderBy: [{ name: 'asc' }, { email: 'desc' }],
507
- * });
508
- *
509
- * // pagination with cursor (https://www.prisma.io/docs/orm/prisma-client/queries/pagination#cursor-based-pagination)
510
- * await client.user.findMany({
511
- * cursor: { id: 10 },
512
- * skip: 1,
513
- * take: 10,
514
- * orderBy: { id: 'asc' },
515
- * });
516
- *
517
- * // distinct
518
- * await client.user.findMany({
519
- * distinct: ['name']
520
- * });
521
- *
522
- * // count all relations
523
- * await client.user.findMany({
524
- * _count: true,
525
- * }); // result: `{ _count: { posts: number; ... } }`
526
- *
527
- * // count selected relations
528
- * await client.user.findMany({
529
- * _count: { select: { posts: true } },
530
- * }); // result: `{ _count: { posts: number } }`
531
- * ```
503
+ * Builds an Kysely expression that returns a JSON object for the given key-value pairs.
532
504
  */
533
- findMany<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): Promise<ModelResult<Schema, Model, T>[]>;
505
+ abstract buildJsonObject(eb: ExpressionBuilder<any, any>, value: Record<string, Expression<unknown>>): ExpressionWrapper<any, any, unknown>;
534
506
  /**
535
- * Returns a uniquely identified entity.
536
- * @param args - query args
537
- * @returns a single entity or null if not found
538
- * @see {@link findMany}
507
+ * Builds an Kysely expression that returns the length of an array.
539
508
  */
540
- findUnique<T extends FindUniqueArgs<Schema, Model>>(args?: SelectSubset<T, FindUniqueArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T> | null>;
509
+ abstract buildArrayLength(eb: ExpressionBuilder<any, any>, array: Expression<unknown>): ExpressionWrapper<any, any, number>;
541
510
  /**
542
- * Returns a uniquely identified entity or throws `NotFoundError` if not found.
543
- * @param args - query args
544
- * @returns a single entity
545
- * @see {@link findMany}
511
+ * Builds an array literal SQL string for the given values.
546
512
  */
547
- findUniqueOrThrow<T extends FindUniqueArgs<Schema, Model>>(args?: SelectSubset<T, FindUniqueArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>>;
513
+ abstract buildArrayLiteralSQL(values: unknown[]): string;
548
514
  /**
549
- * Returns the first entity.
550
- * @param args - query args
551
- * @returns a single entity or null if not found
552
- * @see {@link findMany}
515
+ * Whether the dialect supports updating with a limit on the number of updated rows.
553
516
  */
554
- findFirst<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): Promise<ModelResult<Schema, Model, T> | null>;
517
+ abstract get supportsUpdateWithLimit(): boolean;
555
518
  /**
556
- * Returns the first entity or throws `NotFoundError` if not found.
557
- * @param args - query args
558
- * @returns a single entity
559
- * @see {@link findMany}
519
+ * Whether the dialect supports deleting with a limit on the number of deleted rows.
560
520
  */
561
- findFirstOrThrow<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): Promise<ModelResult<Schema, Model, T>>;
521
+ abstract get supportsDeleteWithLimit(): boolean;
562
522
  /**
563
- * Creates a new entity.
564
- * @param args - create args
565
- * @returns the created entity
566
- *
567
- * @example
568
- * ```ts
569
- * // simple create
570
- * await client.user.create({
571
- * data: { name: 'Alex', email: 'alex@zenstack.dev' }
572
- * });
573
- *
574
- * // nested create with relation
575
- * await client.user.create({
576
- * data: {
577
- * email: 'alex@zenstack.dev',
578
- * posts: { create: { title: 'Hello World' } }
579
- * }
580
- * });
581
- *
582
- * // you can use `select`, `omit`, and `include` to control
583
- * // the fields returned by the query, as with `findMany`
584
- * await client.user.create({
585
- * data: {
586
- * email: 'alex@zenstack.dev',
587
- * posts: { create: { title: 'Hello World' } }
588
- * },
589
- * include: { posts: true }
590
- * }); // result: `{ id: number; posts: Post[] }`
591
- *
592
- * // connect relations
593
- * await client.user.create({
594
- * data: {
595
- * email: 'alex@zenstack.dev',
596
- * posts: { connect: { id: 1 } }
597
- * }
598
- * });
599
- *
600
- * // connect relations, and create if not found
601
- * await client.user.create({
602
- * data: {
603
- * email: 'alex@zenstack.dev',
604
- * posts: {
605
- * connectOrCreate: {
606
- * where: { id: 1 },
607
- * create: { title: 'Hello World' }
608
- * }
609
- * }
610
- * }
611
- * });
612
- * ```
523
+ * Whether the dialect supports DISTINCT ON.
613
524
  */
614
- create<T extends CreateArgs<Schema, Model>>(args: SelectSubset<T, CreateArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>>;
525
+ abstract get supportsDistinctOn(): boolean;
526
+ }
527
+
528
+ type CrudOperation = 'findMany' | 'findUnique' | 'findFirst' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'count' | 'aggregate' | 'groupBy';
529
+
530
+ /**
531
+ * The result of the hooks interception filter.
532
+ */
533
+ type MutationInterceptionFilterResult = {
615
534
  /**
616
- * Creates multiple entities. Only scalar fields are allowed.
617
- * @param args - create args
618
- * @returns count of created entities: `{ count: number }`
619
- *
620
- * @example
621
- * ```ts
622
- * // create multiple entities
623
- * await client.user.createMany({
624
- * data: [
625
- * { name: 'Alex', email: 'alex@zenstack.dev' },
626
- * { name: 'John', email: 'john@zenstack.dev' }
627
- * ]
628
- * });
629
- *
630
- * // skip items that cause unique constraint violation
631
- * await client.user.createMany({
632
- * data: [
633
- * { name: 'Alex', email: 'alex@zenstack.dev' },
634
- * { name: 'John', email: 'john@zenstack.dev' }
635
- * ],
636
- * skipDuplicates: true
637
- * });
638
- * ```
535
+ * Whether to intercept the mutation or not.
639
536
  */
640
- createMany(args?: CreateManyPayload<Schema, Model>): Promise<BatchResult>;
537
+ intercept: boolean;
641
538
  /**
642
- * Creates multiple entities and returns them.
643
- * @param args - create args. See {@link createMany} for input. Use
644
- * `select` and `omit` to control the fields returned.
645
- * @returns the created entities
646
- *
647
- * @example
648
- * ```ts
649
- * // create multiple entities and return selected fields
650
- * await client.user.createManyAndReturn({
651
- * data: [
652
- * { name: 'Alex', email: 'alex@zenstack.dev' },
653
- * { name: 'John', email: 'john@zenstack.dev' }
654
- * ],
655
- * select: { id: true, email: true }
656
- * });
657
- * ```
539
+ * Whether entities should be loaded before the mutation.
658
540
  */
659
- createManyAndReturn<T extends CreateManyAndReturnArgs<Schema, Model>>(args?: SelectSubset<T, CreateManyAndReturnArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>[]>;
660
- /**
661
- * Updates a uniquely identified entity.
662
- * @param args - update args. See {@link findMany} for how to control
663
- * fields and relations returned.
664
- * @returns the updated entity. Throws `NotFoundError` if the entity is not found.
665
- *
666
- * @example
667
- * ```ts
668
- * // update fields
669
- * await client.user.update({
670
- * where: { id: 1 },
671
- * data: { name: 'Alex' }
672
- * });
673
- *
674
- * // connect a relation
675
- * await client.user.update({
676
- * where: { id: 1 },
677
- * data: { posts: { connect: { id: 1 } } }
678
- * });
679
- *
680
- * // connect relation, and create if not found
681
- * await client.user.update({
682
- * where: { id: 1 },
683
- * data: {
684
- * posts: {
685
- * connectOrCreate: {
686
- * where: { id: 1 },
687
- * create: { title: 'Hello World' }
688
- * }
689
- * }
690
- * }
691
- * });
692
- *
693
- * // create many related entities (only available for one-to-many relations)
694
- * await client.user.update({
695
- * where: { id: 1 },
696
- * data: {
697
- * posts: {
698
- * createMany: {
699
- * data: [{ title: 'Hello World' }, { title: 'Hello World 2' }],
700
- * }
701
- * }
702
- * }
703
- * });
704
- *
705
- * // disconnect a one-to-many relation
706
- * await client.user.update({
707
- * where: { id: 1 },
708
- * data: { posts: { disconnect: { id: 1 } } }
709
- * });
710
- *
711
- * // disconnect a one-to-one relation
712
- * await client.user.update({
713
- * where: { id: 1 },
714
- * data: { profile: { disconnect: true } }
715
- * });
716
- *
717
- * // replace a relation (only available for one-to-many relations)
718
- * await client.user.update({
719
- * where: { id: 1 },
720
- * data: {
721
- * posts: {
722
- * set: [{ id: 1 }, { id: 2 }]
723
- * }
724
- * }
725
- * });
726
- *
727
- * // update a relation
728
- * await client.user.update({
729
- * where: { id: 1 },
730
- * data: {
731
- * posts: {
732
- * update: { where: { id: 1 }, data: { title: 'Hello World' } }
733
- * }
734
- * }
735
- * });
736
- *
737
- * // upsert a relation
738
- * await client.user.update({
739
- * where: { id: 1 },
740
- * data: {
741
- * posts: {
742
- * upsert: {
743
- * where: { id: 1 },
744
- * create: { title: 'Hello World' },
745
- * update: { title: 'Hello World' }
746
- * }
747
- * }
748
- * }
749
- * });
750
- *
751
- * // update many related entities (only available for one-to-many relations)
752
- * await client.user.update({
753
- * where: { id: 1 },
754
- * data: {
755
- * posts: {
756
- * updateMany: {
757
- * where: { published: true },
758
- * data: { title: 'Hello World' }
759
- * }
760
- * }
761
- * }
762
- * });
763
- *
764
- * // delete a one-to-many relation
765
- * await client.user.update({
766
- * where: { id: 1 },
767
- * data: { posts: { delete: { id: 1 } } }
768
- * });
769
- *
770
- * // delete a one-to-one relation
771
- * await client.user.update({
772
- * where: { id: 1 },
773
- * data: { profile: { delete: true } }
774
- * });
775
- * ```
776
- */
777
- update<T extends UpdateArgs<Schema, Model>>(args: SelectSubset<T, UpdateArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>>;
778
- /**
779
- * Updates multiple entities.
780
- * @param args - update args. Only scalar fields are allowed for data.
781
- * @returns count of updated entities: `{ count: number }`
782
- *
783
- * @example
784
- * ```ts
785
- * // update many entities
786
- * await client.user.updateMany({
787
- * where: { email: { endsWith: '@zenstack.dev' } },
788
- * data: { role: 'ADMIN' }
789
- * });
790
- *
791
- * // limit the number of updated entities
792
- * await client.user.updateMany({
793
- * where: { email: { endsWith: '@zenstack.dev' } },
794
- * data: { role: 'ADMIN' },
795
- * limit: 10
796
- * });
797
- */
798
- updateMany<T extends UpdateManyArgs<Schema, Model>>(args: Subset<T, UpdateManyArgs<Schema, Model>>): Promise<BatchResult>;
799
- /**
800
- * Updates multiple entities and returns them.
801
- * @param args - update args. Only scalar fields are allowed for data.
802
- * @returns the updated entities
803
- *
804
- * @example
805
- * ```ts
806
- * // update many entities and return selected fields
807
- * await client.user.updateManyAndReturn({
808
- * where: { email: { endsWith: '@zenstack.dev' } },
809
- * data: { role: 'ADMIN' },
810
- * select: { id: true, email: true }
811
- * }); // result: `Array<{ id: string; email: string }>`
812
- *
813
- * // limit the number of updated entities
814
- * await client.user.updateManyAndReturn({
815
- * where: { email: { endsWith: '@zenstack.dev' } },
816
- * data: { role: 'ADMIN' },
817
- * limit: 10
818
- * });
819
- * ```
820
- */
821
- updateManyAndReturn<T extends UpdateManyAndReturnArgs<Schema, Model>>(args: Subset<T, UpdateManyAndReturnArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>[]>;
822
- /**
823
- * Creates or updates an entity.
824
- * @param args - upsert args
825
- * @returns the upserted entity
826
- *
827
- * @example
828
- * ```ts
829
- * // upsert an entity
830
- * await client.user.upsert({
831
- * // `where` clause is used to find the entity
832
- * where: { id: 1 },
833
- * // `create` clause is used if the entity is not found
834
- * create: { email: 'alex@zenstack.dev', name: 'Alex' },
835
- * // `update` clause is used if the entity is found
836
- * update: { name: 'Alex-new' },
837
- * // `select` and `omit` can be used to control the returned fields
838
- * ...
839
- * });
840
- * ```
841
- */
842
- upsert<T extends UpsertArgs<Schema, Model>>(args: SelectSubset<T, UpsertArgs<Schema, Model>>): Promise<ModelResult<Schema, Model, T>>;
843
- /**
844
- * Deletes a uniquely identifiable entity.
845
- * @param args - delete args
846
- * @returns the deleted entity. Throws `NotFoundError` if the entity is not found.
847
- *
848
- * @example
849
- * ```ts
850
- * // delete an entity
851
- * await client.user.delete({
852
- * where: { id: 1 }
853
- * });
854
- *
855
- * // delete an entity and return selected fields
856
- * await client.user.delete({
857
- * where: { id: 1 },
858
- * select: { id: true, email: true }
859
- * }); // result: `{ id: string; email: string }`
860
- * ```
861
- */
862
- delete<T extends DeleteArgs<Schema, Model>>(args: SelectSubset<T, DeleteArgs<Schema, Model>>): Promise<ModelResult<Schema, Model>>;
863
- /**
864
- * Deletes multiple entities.
865
- * @param args - delete args
866
- * @returns count of deleted entities: `{ count: number }`
867
- *
868
- * @example
869
- * ```ts
870
- * // delete many entities
871
- * await client.user.deleteMany({
872
- * where: { email: { endsWith: '@zenstack.dev' } }
873
- * });
874
- *
875
- * // limit the number of deleted entities
876
- * await client.user.deleteMany({
877
- * where: { email: { endsWith: '@zenstack.dev' } },
878
- * limit: 10
879
- * });
880
- * ```
881
- */
882
- deleteMany<T extends DeleteManyArgs<Schema, Model>>(args?: Subset<T, DeleteManyArgs<Schema, Model>>): Promise<BatchResult>;
883
- /**
884
- * Counts rows or field values.
885
- * @param args - count args
886
- * @returns `number`, or an object containing count of selected relations
887
- *
888
- * @example
889
- * ```ts
890
- * // count all
891
- * await client.user.count();
892
- *
893
- * // count with a filter
894
- * await client.user.count({ where: { email: { endsWith: '@zenstack.dev' } } });
895
- *
896
- * // count rows and field values
897
- * await client.user.count({
898
- * select: { _all: true, email: true }
899
- * }); // result: `{ _all: number, email: number }`
900
- */
901
- count<T extends CountArgs<Schema, Model>>(args?: Subset<T, CountArgs<Schema, Model>>): Promise<CountResult<Schema, Model, T>>;
902
- /**
903
- * Aggregates rows.
904
- * @param args - aggregation args
905
- * @returns an object containing aggregated values
906
- *
907
- * @example
908
- * ```ts
909
- * // aggregate rows
910
- * await client.profile.aggregate({
911
- * where: { email: { endsWith: '@zenstack.dev' } },
912
- * _count: true,
913
- * _avg: { age: true },
914
- * _sum: { age: true },
915
- * _min: { age: true },
916
- * _max: { age: true }
917
- * }); // result: `{ _count: number, _avg: { age: number }, ... }`
918
- */
919
- aggregate<T extends AggregateArgs<Schema, Model>>(args: Subset<T, AggregateArgs<Schema, Model>>): Promise<AggregateResult<Schema, Model, T>>;
920
- /**
921
- * Groups rows by columns.
922
- * @param args - groupBy args
923
- * @returns an object containing grouped values
924
- *
925
- * @example
926
- * ```ts
927
- * // group by a field
928
- * await client.profile.groupBy({
929
- * by: 'country',
930
- * _count: true
931
- * }); // result: `Array<{ country: string, _count: number }>`
932
- *
933
- * // group by multiple fields
934
- * await client.profile.groupBy({
935
- * by: ['country', 'city'],
936
- * _count: true
937
- * }); // result: `Array<{ country: string, city: string, _count: number }>`
938
- *
939
- * // group by with sorting, the `orderBy` fields must be in the `by` list
940
- * await client.profile.groupBy({
941
- * by: 'country',
942
- * orderBy: { country: 'desc' }
943
- * });
944
- *
945
- * // group by with having (post-aggregation filter), the `having` fields must
946
- * // be in the `by` list
947
- * await client.profile.groupBy({
948
- * by: 'country',
949
- * having: { country: 'US' }
950
- * });
951
- */
952
- groupBy<T extends GroupByArgs<Schema, Model>>(args: Subset<T, GroupByArgs<Schema, Model>>): Promise<GroupByResult<Schema, Model, T>>;
953
- }
954
-
955
- type AuthType<Schema extends SchemaDef> = string extends GetModels<Schema> ? Record<string, unknown> : Schema['authType'] extends GetModels<Schema> ? Partial<ModelResult<Schema, Schema['authType']>> : never;
956
-
957
- declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
958
- protected readonly schema: Schema;
959
- protected readonly options: ClientOptions<Schema>;
960
- constructor(schema: Schema, options: ClientOptions<Schema>);
961
- abstract get provider(): DataSourceProviderType;
962
- transformPrimitive(value: unknown, _type: BuiltinType): unknown;
963
- abstract buildRelationSelection(query: SelectQueryBuilder<any, any, any>, model: string, relationField: string, parentAlias: string, payload: true | FindArgs<Schema, GetModels<Schema>, true>): SelectQueryBuilder<any, any, any>;
964
- abstract buildSkipTake(query: SelectQueryBuilder<any, any, any>, skip: number | undefined, take: number | undefined): SelectQueryBuilder<any, any, any>;
965
- buildFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, where: boolean | object | undefined): Expression<SqlBool>;
966
- protected buildCompositeFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, key: 'AND' | 'OR' | 'NOT', payload: any): Expression<SqlBool>;
967
- private buildRelationFilter;
968
- private buildToOneRelationFilter;
969
- private buildToManyRelationFilter;
970
- private buildArrayFilter;
971
- buildPrimitiveFilter(eb: ExpressionBuilder<any, any>, model: string, modelAlias: string, field: string, fieldDef: FieldDef, payload: any): Expression<SqlBool>;
972
- private buildLiteralFilter;
973
- private buildStandardFilter;
974
- private buildStringFilter;
975
- private prepStringCasing;
976
- private buildNumberFilter;
977
- private buildBooleanFilter;
978
- private buildDateTimeFilter;
979
- private buildBytesFilter;
980
- private buildEnumFilter;
981
- buildOrderBy(query: SelectQueryBuilder<any, any, any>, model: string, modelAlias: string, orderBy: OrArray<OrderBy<Schema, GetModels<Schema>, boolean, boolean>> | undefined, useDefaultIfEmpty: boolean, negated: boolean): SelectQueryBuilder<any, any, any>;
982
- private negateSort;
983
- true(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
984
- false(eb: ExpressionBuilder<any, any>): Expression<SqlBool>;
985
- isTrue(expression: Expression<SqlBool>): boolean;
986
- isFalse(expression: Expression<SqlBool>): boolean;
987
- protected and(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
988
- protected or(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): Expression<SqlBool>;
989
- protected not(eb: ExpressionBuilder<any, any>, ...args: Expression<SqlBool>[]): ExpressionWrapper<any, any, SqlBool>;
990
- /**
991
- * Builds an Kysely expression that returns a JSON object for the given key-value pairs.
992
- */
993
- abstract buildJsonObject(eb: ExpressionBuilder<any, any>, value: Record<string, Expression<unknown>>): ExpressionWrapper<any, any, unknown>;
994
- /**
995
- * Builds an Kysely expression that returns the length of an array.
996
- */
997
- abstract buildArrayLength(eb: ExpressionBuilder<any, any>, array: Expression<unknown>): ExpressionWrapper<any, any, number>;
998
- /**
999
- * Builds an array literal SQL string for the given values.
1000
- */
1001
- abstract buildArrayLiteralSQL(values: unknown[]): string;
1002
- /**
1003
- * Whether the dialect supports updating with a limit on the number of updated rows.
1004
- */
1005
- abstract get supportsUpdateWithLimit(): boolean;
1006
- /**
1007
- * Whether the dialect supports deleting with a limit on the number of deleted rows.
1008
- */
1009
- abstract get supportsDeleteWithLimit(): boolean;
1010
- /**
1011
- * Whether the dialect supports DISTINCT ON.
1012
- */
1013
- abstract get supportsDistinctOn(): boolean;
1014
- }
1015
-
1016
- type CrudOperation = 'findMany' | 'findUnique' | 'findFirst' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'count' | 'aggregate' | 'groupBy';
1017
-
1018
- type QueryContext<Schema extends SchemaDef> = {
1019
- /**
1020
- * The ZenStack client that's invoking the plugin.
1021
- */
1022
- client: ClientContract<Schema>;
1023
- /**
1024
- * The model that is being queried.
1025
- */
1026
- model: GetModels<Schema>;
1027
- /**
1028
- * The query operation that is being performed.
1029
- */
1030
- operation: CrudOperation;
1031
- /**
1032
- * The query arguments.
1033
- */
1034
- queryArgs: unknown;
1035
- };
1036
- /**
1037
- * The result of the hooks interception filter.
1038
- */
1039
- type MutationInterceptionFilterResult = {
1040
- /**
1041
- * Whether to intercept the mutation or not.
1042
- */
1043
- intercept: boolean;
1044
- /**
1045
- * Whether to use a transaction for the mutation.
1046
- */
1047
- useTransactionForMutation?: boolean;
1048
- /**
1049
- * Whether entities should be loaded before the mutation.
1050
- */
1051
- loadBeforeMutationEntity?: boolean;
541
+ loadBeforeMutationEntity?: boolean;
1052
542
  /**
1053
543
  * Whether entities should be loaded after the mutation.
1054
544
  */
@@ -1068,9 +558,6 @@ type MutationHooksArgs<Schema extends SchemaDef> = {
1068
558
  */
1069
559
  queryNode: OperationNode;
1070
560
  };
1071
- type OnQueryArgs<Schema extends SchemaDef> = QueryContext<Schema> & {
1072
- proceed: ProceedQueryFunction<Schema>;
1073
- };
1074
561
  type PluginBeforeEntityMutationArgs<Schema extends SchemaDef> = MutationHooksArgs<Schema> & {
1075
562
  entities?: Record<string, unknown>[];
1076
563
  };
@@ -1078,16 +565,12 @@ type PluginAfterEntityMutationArgs<Schema extends SchemaDef> = MutationHooksArgs
1078
565
  beforeMutationEntities?: Record<string, unknown>[];
1079
566
  afterMutationEntities?: Record<string, unknown>[];
1080
567
  };
1081
- type ProceedQueryFunction<Schema extends SchemaDef> = (queryArgs: unknown, tx?: ClientContract<Schema>) => Promise<unknown>;
1082
- type OnKyselyQueryTransactionCallback = (proceed: ProceedKyselyQueryFunction) => Promise<QueryResult<any>>;
1083
- type OnKyselyQueryTransaction = (callback: OnKyselyQueryTransactionCallback) => Promise<QueryResult<any>>;
1084
568
  type OnKyselyQueryArgs<Schema extends SchemaDef> = {
1085
569
  kysely: ToKysely<Schema>;
1086
570
  schema: SchemaDef;
1087
571
  client: ClientContract<Schema>;
1088
572
  query: RootOperationNode;
1089
573
  proceed: ProceedKyselyQueryFunction;
1090
- transaction: OnKyselyQueryTransaction;
1091
574
  };
1092
575
  type ProceedKyselyQueryFunction = (query: RootOperationNode) => Promise<QueryResult<any>>;
1093
576
  /**
@@ -1109,7 +592,7 @@ interface RuntimePlugin<Schema extends SchemaDef = SchemaDef> {
1109
592
  /**
1110
593
  * Intercepts an ORM query.
1111
594
  */
1112
- onQuery?: (args: OnQueryArgs<Schema>) => Promise<unknown>;
595
+ onQuery?: OnQueryHooks<Schema>;
1113
596
  /**
1114
597
  * Intercepts a Kysely query.
1115
598
  */
@@ -1132,141 +615,762 @@ interface RuntimePlugin<Schema extends SchemaDef = SchemaDef> {
1132
615
  * @param args.afterMutationEntity Only available if `loadAfterMutationEntity` is set to true in the
1133
616
  * return value of {@link RuntimePlugin.mutationInterceptionFilter}.
1134
617
  */
1135
- afterEntityMutation?: (args: PluginAfterEntityMutationArgs<Schema>) => MaybePromise<void>;
1136
- }
1137
- type CliGeneratorContext = {
1138
- model: Model;
1139
- outputPath: string;
1140
- tsSchemaFile: string;
1141
- };
1142
- type CliGenerator = (context: CliGeneratorContext) => MaybePromise<void>;
1143
-
1144
- type DialectConfig<Provider extends DataSourceProvider> = Provider['type'] extends 'sqlite' ? Optional<SqliteDialectConfig, 'database'> : Provider extends 'postgresql' ? Optional<PostgresDialectConfig, 'pool'> : never;
1145
- type ZModelFunctionContext<Schema extends SchemaDef> = {
1146
- dialect: BaseCrudDialect<Schema>;
1147
- model: GetModels<Schema>;
1148
- operation: CRUD;
1149
- };
1150
- type ZModelFunction<Schema extends SchemaDef> = (eb: ExpressionBuilder<ToKyselySchema<Schema>, keyof ToKyselySchema<Schema>>, args: Expression<any>[], context: ZModelFunctionContext<Schema>) => Expression<unknown>;
1151
- /**
1152
- * ZenStack client options.
1153
- */
1154
- type ClientOptions<Schema extends SchemaDef> = {
618
+ afterEntityMutation?: (args: PluginAfterEntityMutationArgs<Schema>) => MaybePromise<void>;
619
+ }
620
+ type OnQueryHooks<Schema extends SchemaDef = SchemaDef> = {
621
+ [Model in GetModels<Schema> as Uncapitalize<Model>]?: OnQueryOperationHooks<Schema, Model>;
622
+ } & {
623
+ $allModels?: OnQueryOperationHooks<Schema, GetModels<Schema>>;
624
+ };
625
+ type OnQueryOperationHooks<Schema extends SchemaDef, Model extends GetModels<Schema>> = {
626
+ [Operation in keyof ModelOperations<Schema, Model>]?: (ctx: OnQueryHookContext<Schema, Model, Operation>) => Promise<Awaited<ReturnType<ModelOperations<Schema, Model>[Operation]>>>;
627
+ } & {
628
+ $allOperations?: (ctx: {
629
+ model: Model;
630
+ operation: CrudOperation;
631
+ args: unknown;
632
+ query: (args: unknown) => Promise<unknown>;
633
+ }) => MaybePromise<unknown>;
634
+ };
635
+ type OnQueryHookContext<Schema extends SchemaDef, Model extends GetModels<Schema>, Operation extends keyof ModelOperations<Schema, Model>> = {
636
+ /**
637
+ * The model that is being queried.
638
+ */
639
+ model: Model;
640
+ /**
641
+ * The operation that is being performed.
642
+ */
643
+ operation: Operation;
644
+ /**
645
+ * The query arguments.
646
+ */
647
+ args: Parameters<ModelOperations<Schema, Model>[Operation]>[0];
648
+ /**
649
+ * The query function to proceed with the original query.
650
+ * It takes the same arguments as the operation method.
651
+ *
652
+ * @param args The query arguments.
653
+ */
654
+ query: (args: Parameters<ModelOperations<Schema, Model>[Operation]>[0]) => ReturnType<ModelOperations<Schema, Model>[Operation]>;
655
+ /**
656
+ * The ZenStack client that is performing the operation.
657
+ */
658
+ client: ClientContract<Schema>;
659
+ };
660
+ /**
661
+ * Defines a ZenStack runtime plugin.
662
+ */
663
+ declare function definePlugin<Schema extends SchemaDef>(plugin: RuntimePlugin<Schema>): RuntimePlugin<Schema>;
664
+
665
+ type DialectConfig<Provider extends DataSourceProvider> = Provider['type'] extends 'sqlite' ? Optional<SqliteDialectConfig, 'database'> : Provider['type'] extends 'postgresql' ? Optional<PostgresDialectConfig, 'pool'> : never;
666
+ type ZModelFunctionContext<Schema extends SchemaDef> = {
667
+ dialect: BaseCrudDialect<Schema>;
668
+ model: GetModels<Schema>;
669
+ operation: CRUD;
670
+ };
671
+ type ZModelFunction<Schema extends SchemaDef> = (eb: ExpressionBuilder<ToKyselySchema<Schema>, keyof ToKyselySchema<Schema>>, args: Expression<any>[], context: ZModelFunctionContext<Schema>) => Expression<unknown>;
672
+ /**
673
+ * ZenStack client options.
674
+ */
675
+ type ClientOptions<Schema extends SchemaDef> = {
676
+ /**
677
+ * Database dialect configuration.
678
+ */
679
+ dialectConfig: DialectConfig<Schema['provider']>;
680
+ /**
681
+ * Custom function definitions.
682
+ */
683
+ functions?: Record<string, ZModelFunction<Schema>>;
684
+ /**
685
+ * Plugins.
686
+ */
687
+ plugins?: RuntimePlugin<Schema>[];
688
+ /**
689
+ * Logging configuration.
690
+ */
691
+ log?: KyselyConfig['log'];
692
+ /**
693
+ * Debug mode.
694
+ */
695
+ debug?: boolean;
696
+ } & (HasComputedFields<Schema> extends true ? {
697
+ /**
698
+ * Computed field definitions.
699
+ */
700
+ computedFields: ComputedFieldsOptions<Schema>;
701
+ } : {}) & (HasProcedures<Schema> extends true ? {
702
+ /**
703
+ * Custom procedure definitions.
704
+ */
705
+ procedures: ProceduresOptions<Schema>;
706
+ } : {});
707
+ type ComputedFieldsOptions<Schema extends SchemaDef> = {
708
+ [Model in GetModels<Schema> as 'computedFields' extends keyof GetModel<Schema, Model> ? Model : never]: {
709
+ [Field in keyof Schema['models'][Model]['computedFields']]: PrependParameter<ExpressionBuilder<ToKyselySchema<Schema>, Model>, Schema['models'][Model]['computedFields'][Field]>;
710
+ };
711
+ };
712
+ type HasComputedFields<Schema extends SchemaDef> = string extends GetModels<Schema> ? false : keyof ComputedFieldsOptions<Schema> extends never ? false : true;
713
+ type ProceduresOptions<Schema extends SchemaDef> = Schema extends {
714
+ procedures: Record<string, ProcedureDef>;
715
+ } ? {
716
+ [Key in keyof Schema['procedures']]: PrependParameter<ClientContract<Schema>, ProcedureFunc<Schema, Schema['procedures'][Key]>>;
717
+ } : {};
718
+ type HasProcedures<Schema extends SchemaDef> = Schema extends {
719
+ procedures: Record<string, ProcedureDef>;
720
+ } ? true : false;
721
+
722
+ /**
723
+ * A promise that only executes when it's awaited or .then() is called.
724
+ */
725
+ type ZenStackPromise<Schema extends SchemaDef, T> = Promise<T> & {
726
+ /**
727
+ * @private
728
+ * Callable to get a plain promise.
729
+ */
730
+ cb: (txClient?: ClientContract<Schema>) => Promise<T>;
731
+ };
732
+
733
+ type TransactionUnsupportedMethods = (typeof TRANSACTION_UNSUPPORTED_METHODS)[number];
734
+ /**
735
+ * Transaction isolation levels.
736
+ */
737
+ declare enum TransactionIsolationLevel {
738
+ ReadUncommitted = "read uncommitted",
739
+ ReadCommitted = "read committed",
740
+ RepeatableRead = "repeatable read",
741
+ Serializable = "serializable",
742
+ Snapshot = "snapshot"
743
+ }
744
+ /**
745
+ * ZenStack client interface.
746
+ */
747
+ type ClientContract<Schema extends SchemaDef> = {
748
+ readonly $schema: Schema;
749
+ /**
750
+ * The client options.
751
+ */
752
+ readonly $options: ClientOptions<Schema>;
753
+ /**
754
+ * Executes a prepared raw query and returns the number of affected rows.
755
+ * @example
756
+ * ```
757
+ * const result = await client.$executeRaw`UPDATE User SET cool = ${true} WHERE email = ${'user@email.com'};`
758
+ * ```
759
+ */
760
+ $executeRaw(query: TemplateStringsArray, ...values: any[]): ZenStackPromise<Schema, number>;
761
+ /**
762
+ * Executes a raw query and returns the number of affected rows.
763
+ * This method is susceptible to SQL injections.
764
+ * @example
765
+ * ```
766
+ * const result = await client.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com')
767
+ * ```
768
+ */
769
+ $executeRawUnsafe(query: string, ...values: any[]): ZenStackPromise<Schema, number>;
770
+ /**
771
+ * Performs a prepared raw query and returns the `SELECT` data.
772
+ * @example
773
+ * ```
774
+ * const result = await client.$queryRaw`SELECT * FROM User WHERE id = ${1} OR email = ${'user@email.com'};`
775
+ * ```
776
+ */
777
+ $queryRaw<T = unknown>(query: TemplateStringsArray, ...values: any[]): ZenStackPromise<Schema, T>;
778
+ /**
779
+ * Performs a raw query and returns the `SELECT` data.
780
+ * This method is susceptible to SQL injections.
781
+ * @example
782
+ * ```
783
+ * const result = await client.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com')
784
+ * ```
785
+ */
786
+ $queryRawUnsafe<T = unknown>(query: string, ...values: any[]): ZenStackPromise<Schema, T>;
787
+ /**
788
+ * The current user identity.
789
+ */
790
+ get $auth(): AuthType<Schema> | undefined;
791
+ /**
792
+ * Sets the current user identity.
793
+ */
794
+ $setAuth(auth: AuthType<Schema> | undefined): ClientContract<Schema>;
795
+ /**
796
+ * The Kysely query builder instance.
797
+ */
798
+ readonly $qb: ToKysely<Schema>;
799
+ /**
800
+ * The raw Kysely query builder without any ZenStack enhancements.
801
+ */
802
+ readonly $qbRaw: ToKysely<any>;
803
+ /**
804
+ * Starts an interactive transaction.
805
+ */
806
+ $transaction<T>(callback: (tx: Omit<ClientContract<Schema>, TransactionUnsupportedMethods>) => Promise<T>, options?: {
807
+ isolationLevel?: TransactionIsolationLevel;
808
+ }): Promise<T>;
809
+ /**
810
+ * Starts a sequential transaction.
811
+ */
812
+ $transaction<P extends ZenStackPromise<Schema, any>[]>(arg: [...P], options?: {
813
+ isolationLevel?: TransactionIsolationLevel;
814
+ }): Promise<UnwrapTuplePromises<P>>;
815
+ /**
816
+ * Returns a new client with the specified plugin installed.
817
+ */
818
+ $use(plugin: RuntimePlugin<Schema>): ClientContract<Schema>;
819
+ /**
820
+ * Returns a new client with the specified plugin removed.
821
+ */
822
+ $unuse(pluginId: string): ClientContract<Schema>;
823
+ /**
824
+ * Returns a new client with all plugins removed.
825
+ */
826
+ $unuseAll(): ClientContract<Schema>;
827
+ /**
828
+ * Disconnects the underlying Kysely instance from the database.
829
+ */
830
+ $disconnect(): Promise<void>;
831
+ /**
832
+ * Pushes the schema to the database. For testing purposes only.
833
+ * @private
834
+ */
835
+ $pushSchema(): Promise<void>;
836
+ } & {
837
+ [Key in GetModels<Schema> as Uncapitalize<Key>]: ModelOperations<Schema, Key>;
838
+ } & Procedures<Schema>;
839
+ type _TypeMap = {
840
+ String: string;
841
+ Int: number;
842
+ Float: number;
843
+ BigInt: bigint;
844
+ Decimal: Decimal$1;
845
+ Boolean: boolean;
846
+ DateTime: Date;
847
+ };
848
+ type MapType<Schema extends SchemaDef, T extends string> = T extends keyof _TypeMap ? _TypeMap[T] : T extends GetModels<Schema> ? ModelResult<Schema, T> : unknown;
849
+ type Procedures<Schema extends SchemaDef> = Schema['procedures'] extends Record<string, ProcedureDef> ? {
850
+ $procedures: {
851
+ [Key in keyof Schema['procedures']]: ProcedureFunc<Schema, Schema['procedures'][Key]>;
852
+ };
853
+ } : {};
854
+ type ProcedureFunc<Schema extends SchemaDef, Proc extends ProcedureDef> = (...args: MapProcedureParams<Schema, Proc['params']>) => Promise<MapType<Schema, Proc['returnType']>>;
855
+ type MapProcedureParams<Schema extends SchemaDef, Params> = {
856
+ [P in keyof Params]: Params[P] extends {
857
+ type: infer U;
858
+ } ? OrUndefinedIf<MapType<Schema, U & string>, Params[P] extends {
859
+ optional: true;
860
+ } ? true : false> : never;
861
+ };
862
+ /**
863
+ * Creates a new ZenStack client instance.
864
+ */
865
+ interface ClientConstructor {
866
+ new <Schema extends SchemaDef>(schema: Schema, options: ClientOptions<Schema>): ClientContract<Schema>;
867
+ }
868
+ /**
869
+ * CRUD operations.
870
+ */
871
+ type CRUD = 'create' | 'read' | 'update' | 'delete';
872
+ interface ModelOperations<Schema extends SchemaDef, Model extends GetModels<Schema>> {
873
+ /**
874
+ * Returns a list of entities.
875
+ * @param args - query args
876
+ * @returns a list of entities
877
+ *
878
+ * @example
879
+ * ```ts
880
+ * // find all users and return all scalar fields
881
+ * await client.user.findMany();
882
+ *
883
+ * // find all users with name 'Alex'
884
+ * await client.user.findMany({
885
+ * where: {
886
+ * name: 'Alex'
887
+ * }
888
+ * });
889
+ *
890
+ * // select fields
891
+ * await client.user.findMany({
892
+ * select: {
893
+ * name: true,
894
+ * email: true,
895
+ * }
896
+ * }); // result: `Array<{ name: string, email: string }>`
897
+ *
898
+ * // omit fields
899
+ * await client.user.findMany({
900
+ * omit: {
901
+ * name: true,
902
+ * }
903
+ * }); // result: `Array<{ id: number; email: string; ... }>`
904
+ *
905
+ * // include relations (and all scalar fields)
906
+ * await client.user.findMany({
907
+ * include: {
908
+ * posts: true,
909
+ * }
910
+ * }); // result: `Array<{ ...; posts: Post[] }>`
911
+ *
912
+ * // include relations with filter
913
+ * await client.user.findMany({
914
+ * include: {
915
+ * posts: {
916
+ * where: {
917
+ * published: true
918
+ * }
919
+ * }
920
+ * }
921
+ * });
922
+ *
923
+ * // pagination and sorting
924
+ * await client.user.findMany({
925
+ * skip: 10,
926
+ * take: 10,
927
+ * orderBy: [{ name: 'asc' }, { email: 'desc' }],
928
+ * });
929
+ *
930
+ * // pagination with cursor (https://www.prisma.io/docs/orm/prisma-client/queries/pagination#cursor-based-pagination)
931
+ * await client.user.findMany({
932
+ * cursor: { id: 10 },
933
+ * skip: 1,
934
+ * take: 10,
935
+ * orderBy: { id: 'asc' },
936
+ * });
937
+ *
938
+ * // distinct
939
+ * await client.user.findMany({
940
+ * distinct: ['name']
941
+ * });
942
+ *
943
+ * // count all relations
944
+ * await client.user.findMany({
945
+ * _count: true,
946
+ * }); // result: `{ _count: { posts: number; ... } }`
947
+ *
948
+ * // count selected relations
949
+ * await client.user.findMany({
950
+ * _count: { select: { posts: true } },
951
+ * }); // result: `{ _count: { posts: number } }`
952
+ * ```
953
+ */
954
+ findMany<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>[]>;
1155
955
  /**
1156
- * Database dialect configuration.
956
+ * Returns a uniquely identified entity.
957
+ * @param args - query args
958
+ * @returns a single entity or null if not found
959
+ * @see {@link findMany}
1157
960
  */
1158
- dialectConfig?: DialectConfig<Schema['provider']>;
961
+ findUnique<T extends FindUniqueArgs<Schema, Model>>(args?: SelectSubset<T, FindUniqueArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T> | null>;
1159
962
  /**
1160
- * Custom function definitions.
963
+ * Returns a uniquely identified entity or throws `NotFoundError` if not found.
964
+ * @param args - query args
965
+ * @returns a single entity
966
+ * @see {@link findMany}
1161
967
  */
1162
- functions?: Record<string, ZModelFunction<Schema>>;
968
+ findUniqueOrThrow<T extends FindUniqueArgs<Schema, Model>>(args?: SelectSubset<T, FindUniqueArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>>;
1163
969
  /**
1164
- * Plugins.
970
+ * Returns the first entity.
971
+ * @param args - query args
972
+ * @returns a single entity or null if not found
973
+ * @see {@link findMany}
1165
974
  */
1166
- plugins?: RuntimePlugin<Schema>[];
975
+ findFirst<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T> | null>;
1167
976
  /**
1168
- * Logging configuration.
977
+ * Returns the first entity or throws `NotFoundError` if not found.
978
+ * @param args - query args
979
+ * @returns a single entity
980
+ * @see {@link findMany}
1169
981
  */
1170
- log?: KyselyConfig['log'];
1171
- } & (HasComputedFields<Schema> extends true ? {
982
+ findFirstOrThrow<T extends FindArgs<Schema, Model, true>>(args?: SelectSubset<T, FindArgs<Schema, Model, true>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>>;
1172
983
  /**
1173
- * Computed field definitions.
984
+ * Creates a new entity.
985
+ * @param args - create args
986
+ * @returns the created entity
987
+ *
988
+ * @example
989
+ * ```ts
990
+ * // simple create
991
+ * await client.user.create({
992
+ * data: { name: 'Alex', email: 'alex@zenstack.dev' }
993
+ * });
994
+ *
995
+ * // nested create with relation
996
+ * await client.user.create({
997
+ * data: {
998
+ * email: 'alex@zenstack.dev',
999
+ * posts: { create: { title: 'Hello World' } }
1000
+ * }
1001
+ * });
1002
+ *
1003
+ * // you can use `select`, `omit`, and `include` to control
1004
+ * // the fields returned by the query, as with `findMany`
1005
+ * await client.user.create({
1006
+ * data: {
1007
+ * email: 'alex@zenstack.dev',
1008
+ * posts: { create: { title: 'Hello World' } }
1009
+ * },
1010
+ * include: { posts: true }
1011
+ * }); // result: `{ id: number; posts: Post[] }`
1012
+ *
1013
+ * // connect relations
1014
+ * await client.user.create({
1015
+ * data: {
1016
+ * email: 'alex@zenstack.dev',
1017
+ * posts: { connect: { id: 1 } }
1018
+ * }
1019
+ * });
1020
+ *
1021
+ * // connect relations, and create if not found
1022
+ * await client.user.create({
1023
+ * data: {
1024
+ * email: 'alex@zenstack.dev',
1025
+ * posts: {
1026
+ * connectOrCreate: {
1027
+ * where: { id: 1 },
1028
+ * create: { title: 'Hello World' }
1029
+ * }
1030
+ * }
1031
+ * }
1032
+ * });
1033
+ * ```
1174
1034
  */
1175
- computedFields: ComputedFieldsOptions<Schema>;
1176
- } : {}) & (HasProcedures<Schema> extends true ? {
1035
+ create<T extends CreateArgs<Schema, Model>>(args: SelectSubset<T, CreateArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>>;
1177
1036
  /**
1178
- * Custom procedure definitions.
1037
+ * Creates multiple entities. Only scalar fields are allowed.
1038
+ * @param args - create args
1039
+ * @returns count of created entities: `{ count: number }`
1040
+ *
1041
+ * @example
1042
+ * ```ts
1043
+ * // create multiple entities
1044
+ * await client.user.createMany({
1045
+ * data: [
1046
+ * { name: 'Alex', email: 'alex@zenstack.dev' },
1047
+ * { name: 'John', email: 'john@zenstack.dev' }
1048
+ * ]
1049
+ * });
1050
+ *
1051
+ * // skip items that cause unique constraint violation
1052
+ * await client.user.createMany({
1053
+ * data: [
1054
+ * { name: 'Alex', email: 'alex@zenstack.dev' },
1055
+ * { name: 'John', email: 'john@zenstack.dev' }
1056
+ * ],
1057
+ * skipDuplicates: true
1058
+ * });
1059
+ * ```
1179
1060
  */
1180
- procedures: ProceduresOptions<Schema>;
1181
- } : {});
1182
- type ComputedFieldsOptions<Schema extends SchemaDef> = {
1183
- [Model in GetModels<Schema> as 'computedFields' extends keyof GetModel<Schema, Model> ? Model : never]: {
1184
- [Field in keyof Schema['models'][Model]['computedFields']]: PrependParameter<ExpressionBuilder<ToKyselySchema<Schema>, Model>, Schema['models'][Model]['computedFields'][Field]>;
1185
- };
1186
- };
1187
- type HasComputedFields<Schema extends SchemaDef> = string extends GetModels<Schema> ? false : keyof ComputedFieldsOptions<Schema> extends never ? false : true;
1188
- type ProceduresOptions<Schema extends SchemaDef> = Schema extends {
1189
- procedures: Record<string, ProcedureDef>;
1190
- } ? {
1191
- [Key in keyof Schema['procedures']]: PrependParameter<ClientContract<Schema>, ProcedureFunc<Schema, Schema['procedures'][Key]>>;
1192
- } : {};
1193
- type HasProcedures<Schema extends SchemaDef> = Schema extends {
1194
- procedures: Record<string, ProcedureDef>;
1195
- } ? true : false;
1196
-
1197
- /**
1198
- * ZenStack client interface.
1199
- */
1200
- type ClientContract<Schema extends SchemaDef> = {
1201
- readonly $schema: Schema;
1061
+ createMany<T extends CreateManyArgs<Schema, Model>>(args?: SelectSubset<T, CreateManyArgs<Schema, Model>>): ZenStackPromise<Schema, BatchResult>;
1202
1062
  /**
1203
- * The client options.
1063
+ * Creates multiple entities and returns them.
1064
+ * @param args - create args. See {@link createMany} for input. Use
1065
+ * `select` and `omit` to control the fields returned.
1066
+ * @returns the created entities
1067
+ *
1068
+ * @example
1069
+ * ```ts
1070
+ * // create multiple entities and return selected fields
1071
+ * await client.user.createManyAndReturn({
1072
+ * data: [
1073
+ * { name: 'Alex', email: 'alex@zenstack.dev' },
1074
+ * { name: 'John', email: 'john@zenstack.dev' }
1075
+ * ],
1076
+ * select: { id: true, email: true }
1077
+ * });
1078
+ * ```
1204
1079
  */
1205
- readonly $options: ClientOptions<Schema>;
1080
+ createManyAndReturn<T extends CreateManyAndReturnArgs<Schema, Model>>(args?: SelectSubset<T, CreateManyAndReturnArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>[]>;
1206
1081
  /**
1207
- * The current user identity.
1082
+ * Updates a uniquely identified entity.
1083
+ * @param args - update args. See {@link findMany} for how to control
1084
+ * fields and relations returned.
1085
+ * @returns the updated entity. Throws `NotFoundError` if the entity is not found.
1086
+ *
1087
+ * @example
1088
+ * ```ts
1089
+ * // update fields
1090
+ * await client.user.update({
1091
+ * where: { id: 1 },
1092
+ * data: { name: 'Alex' }
1093
+ * });
1094
+ *
1095
+ * // connect a relation
1096
+ * await client.user.update({
1097
+ * where: { id: 1 },
1098
+ * data: { posts: { connect: { id: 1 } } }
1099
+ * });
1100
+ *
1101
+ * // connect relation, and create if not found
1102
+ * await client.user.update({
1103
+ * where: { id: 1 },
1104
+ * data: {
1105
+ * posts: {
1106
+ * connectOrCreate: {
1107
+ * where: { id: 1 },
1108
+ * create: { title: 'Hello World' }
1109
+ * }
1110
+ * }
1111
+ * }
1112
+ * });
1113
+ *
1114
+ * // create many related entities (only available for one-to-many relations)
1115
+ * await client.user.update({
1116
+ * where: { id: 1 },
1117
+ * data: {
1118
+ * posts: {
1119
+ * createMany: {
1120
+ * data: [{ title: 'Hello World' }, { title: 'Hello World 2' }],
1121
+ * }
1122
+ * }
1123
+ * }
1124
+ * });
1125
+ *
1126
+ * // disconnect a one-to-many relation
1127
+ * await client.user.update({
1128
+ * where: { id: 1 },
1129
+ * data: { posts: { disconnect: { id: 1 } } }
1130
+ * });
1131
+ *
1132
+ * // disconnect a one-to-one relation
1133
+ * await client.user.update({
1134
+ * where: { id: 1 },
1135
+ * data: { profile: { disconnect: true } }
1136
+ * });
1137
+ *
1138
+ * // replace a relation (only available for one-to-many relations)
1139
+ * await client.user.update({
1140
+ * where: { id: 1 },
1141
+ * data: {
1142
+ * posts: {
1143
+ * set: [{ id: 1 }, { id: 2 }]
1144
+ * }
1145
+ * }
1146
+ * });
1147
+ *
1148
+ * // update a relation
1149
+ * await client.user.update({
1150
+ * where: { id: 1 },
1151
+ * data: {
1152
+ * posts: {
1153
+ * update: { where: { id: 1 }, data: { title: 'Hello World' } }
1154
+ * }
1155
+ * }
1156
+ * });
1157
+ *
1158
+ * // upsert a relation
1159
+ * await client.user.update({
1160
+ * where: { id: 1 },
1161
+ * data: {
1162
+ * posts: {
1163
+ * upsert: {
1164
+ * where: { id: 1 },
1165
+ * create: { title: 'Hello World' },
1166
+ * update: { title: 'Hello World' }
1167
+ * }
1168
+ * }
1169
+ * }
1170
+ * });
1171
+ *
1172
+ * // update many related entities (only available for one-to-many relations)
1173
+ * await client.user.update({
1174
+ * where: { id: 1 },
1175
+ * data: {
1176
+ * posts: {
1177
+ * updateMany: {
1178
+ * where: { published: true },
1179
+ * data: { title: 'Hello World' }
1180
+ * }
1181
+ * }
1182
+ * }
1183
+ * });
1184
+ *
1185
+ * // delete a one-to-many relation
1186
+ * await client.user.update({
1187
+ * where: { id: 1 },
1188
+ * data: { posts: { delete: { id: 1 } } }
1189
+ * });
1190
+ *
1191
+ * // delete a one-to-one relation
1192
+ * await client.user.update({
1193
+ * where: { id: 1 },
1194
+ * data: { profile: { delete: true } }
1195
+ * });
1196
+ * ```
1208
1197
  */
1209
- get $auth(): AuthType<Schema> | undefined;
1198
+ update<T extends UpdateArgs<Schema, Model>>(args: SelectSubset<T, UpdateArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>>;
1210
1199
  /**
1211
- * Sets the current user identity.
1200
+ * Updates multiple entities.
1201
+ * @param args - update args. Only scalar fields are allowed for data.
1202
+ * @returns count of updated entities: `{ count: number }`
1203
+ *
1204
+ * @example
1205
+ * ```ts
1206
+ * // update many entities
1207
+ * await client.user.updateMany({
1208
+ * where: { email: { endsWith: '@zenstack.dev' } },
1209
+ * data: { role: 'ADMIN' }
1210
+ * });
1211
+ *
1212
+ * // limit the number of updated entities
1213
+ * await client.user.updateMany({
1214
+ * where: { email: { endsWith: '@zenstack.dev' } },
1215
+ * data: { role: 'ADMIN' },
1216
+ * limit: 10
1217
+ * });
1212
1218
  */
1213
- $setAuth(auth: AuthType<Schema> | undefined): ClientContract<Schema>;
1219
+ updateMany<T extends UpdateManyArgs<Schema, Model>>(args: Subset<T, UpdateManyArgs<Schema, Model>>): ZenStackPromise<Schema, BatchResult>;
1214
1220
  /**
1215
- * The Kysely query builder instance.
1221
+ * Updates multiple entities and returns them.
1222
+ * @param args - update args. Only scalar fields are allowed for data.
1223
+ * @returns the updated entities
1224
+ *
1225
+ * @example
1226
+ * ```ts
1227
+ * // update many entities and return selected fields
1228
+ * await client.user.updateManyAndReturn({
1229
+ * where: { email: { endsWith: '@zenstack.dev' } },
1230
+ * data: { role: 'ADMIN' },
1231
+ * select: { id: true, email: true }
1232
+ * }); // result: `Array<{ id: string; email: string }>`
1233
+ *
1234
+ * // limit the number of updated entities
1235
+ * await client.user.updateManyAndReturn({
1236
+ * where: { email: { endsWith: '@zenstack.dev' } },
1237
+ * data: { role: 'ADMIN' },
1238
+ * limit: 10
1239
+ * });
1240
+ * ```
1216
1241
  */
1217
- readonly $qb: ToKysely<Schema>;
1242
+ updateManyAndReturn<T extends UpdateManyAndReturnArgs<Schema, Model>>(args: Subset<T, UpdateManyAndReturnArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>[]>;
1218
1243
  /**
1219
- * The raw Kysely query builder without any ZenStack enhancements.
1244
+ * Creates or updates an entity.
1245
+ * @param args - upsert args
1246
+ * @returns the upserted entity
1247
+ *
1248
+ * @example
1249
+ * ```ts
1250
+ * // upsert an entity
1251
+ * await client.user.upsert({
1252
+ * // `where` clause is used to find the entity
1253
+ * where: { id: 1 },
1254
+ * // `create` clause is used if the entity is not found
1255
+ * create: { email: 'alex@zenstack.dev', name: 'Alex' },
1256
+ * // `update` clause is used if the entity is found
1257
+ * update: { name: 'Alex-new' },
1258
+ * // `select` and `omit` can be used to control the returned fields
1259
+ * ...
1260
+ * });
1261
+ * ```
1220
1262
  */
1221
- readonly $qbRaw: ToKysely<any>;
1263
+ upsert<T extends UpsertArgs<Schema, Model>>(args: SelectSubset<T, UpsertArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model, T>>;
1222
1264
  /**
1223
- * Starts a transaction.
1265
+ * Deletes a uniquely identifiable entity.
1266
+ * @param args - delete args
1267
+ * @returns the deleted entity. Throws `NotFoundError` if the entity is not found.
1268
+ *
1269
+ * @example
1270
+ * ```ts
1271
+ * // delete an entity
1272
+ * await client.user.delete({
1273
+ * where: { id: 1 }
1274
+ * });
1275
+ *
1276
+ * // delete an entity and return selected fields
1277
+ * await client.user.delete({
1278
+ * where: { id: 1 },
1279
+ * select: { id: true, email: true }
1280
+ * }); // result: `{ id: string; email: string }`
1281
+ * ```
1224
1282
  */
1225
- $transaction<T>(callback: (tx: ClientContract<Schema>) => Promise<T>): Promise<T>;
1283
+ delete<T extends DeleteArgs<Schema, Model>>(args: SelectSubset<T, DeleteArgs<Schema, Model>>): ZenStackPromise<Schema, ModelResult<Schema, Model>>;
1226
1284
  /**
1227
- * Returns a new client with the specified plugin installed.
1285
+ * Deletes multiple entities.
1286
+ * @param args - delete args
1287
+ * @returns count of deleted entities: `{ count: number }`
1288
+ *
1289
+ * @example
1290
+ * ```ts
1291
+ * // delete many entities
1292
+ * await client.user.deleteMany({
1293
+ * where: { email: { endsWith: '@zenstack.dev' } }
1294
+ * });
1295
+ *
1296
+ * // limit the number of deleted entities
1297
+ * await client.user.deleteMany({
1298
+ * where: { email: { endsWith: '@zenstack.dev' } },
1299
+ * limit: 10
1300
+ * });
1301
+ * ```
1228
1302
  */
1229
- $use(plugin: RuntimePlugin<Schema>): ClientContract<Schema>;
1303
+ deleteMany<T extends DeleteManyArgs<Schema, Model>>(args?: Subset<T, DeleteManyArgs<Schema, Model>>): ZenStackPromise<Schema, BatchResult>;
1230
1304
  /**
1231
- * Returns a new client with all plugins removed.
1305
+ * Counts rows or field values.
1306
+ * @param args - count args
1307
+ * @returns `number`, or an object containing count of selected relations
1308
+ *
1309
+ * @example
1310
+ * ```ts
1311
+ * // count all
1312
+ * await client.user.count();
1313
+ *
1314
+ * // count with a filter
1315
+ * await client.user.count({ where: { email: { endsWith: '@zenstack.dev' } } });
1316
+ *
1317
+ * // count rows and field values
1318
+ * await client.user.count({
1319
+ * select: { _all: true, email: true }
1320
+ * }); // result: `{ _all: number, email: number }`
1232
1321
  */
1233
- $unuseAll(): ClientContract<Schema>;
1322
+ count<T extends CountArgs<Schema, Model>>(args?: Subset<T, CountArgs<Schema, Model>>): ZenStackPromise<Schema, CountResult<Schema, Model, T>>;
1234
1323
  /**
1235
- * Disconnects the underlying Kysely instance from the database.
1324
+ * Aggregates rows.
1325
+ * @param args - aggregation args
1326
+ * @returns an object containing aggregated values
1327
+ *
1328
+ * @example
1329
+ * ```ts
1330
+ * // aggregate rows
1331
+ * await client.profile.aggregate({
1332
+ * where: { email: { endsWith: '@zenstack.dev' } },
1333
+ * _count: true,
1334
+ * _avg: { age: true },
1335
+ * _sum: { age: true },
1336
+ * _min: { age: true },
1337
+ * _max: { age: true }
1338
+ * }); // result: `{ _count: number, _avg: { age: number }, ... }`
1236
1339
  */
1237
- $disconnect(): Promise<void>;
1340
+ aggregate<T extends AggregateArgs<Schema, Model>>(args: Subset<T, AggregateArgs<Schema, Model>>): ZenStackPromise<Schema, AggregateResult<Schema, Model, T>>;
1238
1341
  /**
1239
- * Pushes the schema to the database. For testing purposes only.
1240
- * @private
1342
+ * Groups rows by columns.
1343
+ * @param args - groupBy args
1344
+ * @returns an object containing grouped values
1345
+ *
1346
+ * @example
1347
+ * ```ts
1348
+ * // group by a field
1349
+ * await client.profile.groupBy({
1350
+ * by: 'country',
1351
+ * _count: true
1352
+ * }); // result: `Array<{ country: string, _count: number }>`
1353
+ *
1354
+ * // group by multiple fields
1355
+ * await client.profile.groupBy({
1356
+ * by: ['country', 'city'],
1357
+ * _count: true
1358
+ * }); // result: `Array<{ country: string, city: string, _count: number }>`
1359
+ *
1360
+ * // group by with sorting, the `orderBy` fields must be in the `by` list
1361
+ * await client.profile.groupBy({
1362
+ * by: 'country',
1363
+ * orderBy: { country: 'desc' }
1364
+ * });
1365
+ *
1366
+ * // group by with having (post-aggregation filter), the `having` fields must
1367
+ * // be in the `by` list
1368
+ * await client.profile.groupBy({
1369
+ * by: 'country',
1370
+ * having: { country: 'US' }
1371
+ * });
1241
1372
  */
1242
- $pushSchema(): Promise<void>;
1243
- } & {
1244
- [Key in GetModels<Schema> as Uncapitalize<Key>]: ModelOperations<Schema, Key>;
1245
- } & Procedures<Schema>;
1246
- type MapType<Schema extends SchemaDef, T extends string> = T extends 'String' ? string : T extends 'Int' ? number : T extends 'Float' ? number : T extends 'BigInt' ? bigint : T extends 'Decimal' ? Decimal$1 : T extends 'Boolean' ? boolean : T extends 'DateTime' ? Date : T extends GetModels<Schema> ? ModelResult<Schema, T> : unknown;
1247
- type Procedures<Schema extends SchemaDef> = Schema['procedures'] extends Record<string, ProcedureDef> ? {
1248
- $procedures: {
1249
- [Key in keyof Schema['procedures']]: ProcedureFunc<Schema, Schema['procedures'][Key]>;
1250
- };
1251
- } : {};
1252
- type ProcedureFunc<Schema extends SchemaDef, Proc extends ProcedureDef> = (...args: MapProcedureParams<Schema, Proc['params']>) => Promise<MapType<Schema, Proc['returnType']>>;
1253
- type MapProcedureParams<Schema extends SchemaDef, Params> = {
1254
- [P in keyof Params]: Params[P] extends {
1255
- type: infer U;
1256
- } ? OrUndefinedIf<MapType<Schema, U & string>, Params[P] extends {
1257
- optional: true;
1258
- } ? true : false> : never;
1259
- };
1260
- /**
1261
- * Creates a new ZenStack client instance.
1262
- */
1263
- interface ClientConstructor {
1264
- new <Schema extends SchemaDef>(schema: HasComputedFields<Schema> extends false ? Schema : never): ClientContract<Schema>;
1265
- new <Schema extends SchemaDef>(schema: Schema, options: ClientOptions<Schema>): ClientContract<Schema>;
1373
+ groupBy<T extends GroupByArgs<Schema, Model>>(args: Subset<T, GroupByArgs<Schema, Model>>): ZenStackPromise<Schema, GroupByResult<Schema, Model, T>>;
1266
1374
  }
1267
- /**
1268
- * CRUD operations.
1269
- */
1270
- type CRUD = 'create' | 'read' | 'update' | 'delete';
1271
1375
 
1272
- export type { UpdateInput as A, BatchResult as B, ClientConstructor as C, DateTimeFilter as D, DeleteArgs as E, FindArgs as F, DeleteManyArgs as G, CountArgs as H, CountAggregateInput as I, CountResult as J, AggregateArgs as K, AggregateResult as L, ModelResult as M, NumberFilter as N, OrderBy as O, GroupByArgs as P, GroupByResult as Q, ModelOperations as R, StringFilter as S, ToKysely as T, UpdateArgs as U, RuntimePlugin as V, WhereInput as W, OnKyselyQueryArgs as X, ClientContract as a, ClientOptions as b, CliGenerator as c, CommonPrimitiveFilter as d, BytesFilter as e, BooleanFilter as f, SortOrder as g, NullsOrder as h, WhereUniqueInput as i, SelectIncludeOmit as j, Subset as k, SelectSubset as l, MapFieldType as m, OptionalFieldsForCreate as n, OppositeRelationFields as o, OppositeRelationAndFK as p, FindUniqueArgs as q, CreateArgs as r, CreateManyArgs as s, CreateManyAndReturnArgs as t, CreateInput as u, UpdateManyArgs as v, UpdateManyAndReturnArgs as w, UpsertArgs as x, UpdateScalarInput as y, UpdateRelationInput as z };
1376
+ export { type UpdateRelationInput as A, type BatchResult as B, type ClientConstructor as C, type DateTimeFilter as D, type UpdateInput as E, type FindArgs as F, type DeleteArgs as G, type DeleteManyArgs as H, type CountArgs as I, type CountAggregateInput as J, type CountResult as K, type AggregateArgs as L, type ModelResult as M, type NumberFilter as N, type OrderBy as O, type AggregateResult as P, type GroupByArgs as Q, type GroupByResult as R, type StringFilter as S, type ToKysely as T, type UpdateArgs as U, type RuntimePlugin as V, type WhereInput as W, type OnKyselyQueryArgs as X, type ClientContract as a, type ClientOptions as b, type CommonPrimitiveFilter as c, definePlugin as d, type BytesFilter as e, type BooleanFilter as f, type SortOrder as g, type NullsOrder as h, type WhereUniqueInput as i, type SelectIncludeOmit as j, type Subset as k, type SelectSubset as l, type MapFieldType as m, type OptionalFieldsForCreate as n, type OppositeRelationFields as o, type OppositeRelationAndFK as p, type FindUniqueArgs as q, type CreateArgs as r, type CreateManyArgs as s, type CreateManyAndReturnArgs as t, type CreateManyInput as u, type CreateInput as v, type UpdateManyArgs as w, type UpdateManyAndReturnArgs as x, type UpsertArgs as y, type UpdateScalarInput as z };