vsrepo 1.2.8 → 1.3.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/README.md CHANGED
@@ -30,7 +30,9 @@ O VSRepository permite criar repositories fortemente tipados com:
30
30
  - [Merge](#merge)
31
31
  - [Configurando os métodos base](#configurando-os-métodos-base)
32
32
  - [Select Models](#select-models)
33
+ - [Include Models](#include-models)
33
34
  - [Required Where](#requiredwhere)
35
+ - [Default Ordenation](#default-ordenation)
34
36
  - [Opção `see`](#opção-see)
35
37
  - [Métodos dinâmicos](#métodos-dinâmicos)
36
38
  - [Prefixos disponíveis](#prefixos-disponíveis)
@@ -463,6 +465,51 @@ const usuarioCompleto = await usuarioRepository.get(id, { selectModel: false });
463
465
 
464
466
  ---
465
467
 
468
+ ## Include Models
469
+
470
+ `includeModels` funciona de forma parecida com o `selectModels`, mas em vez de receber um `select`, ele recebe um `include` válido do Prisma.
471
+
472
+ ```ts
473
+ const usuarioRepository = setupVSRepo<Usuario, "usuario">()(({
474
+ tableName: "usuario",
475
+ pkName: "id",
476
+ selectModels: {
477
+ public: { id: true, nome: true, email: true },
478
+ },
479
+ defaultSelectModel: "public",
480
+ includeModels: {
481
+ comPosts: { posts: true },
482
+ comPostsEPerfil: { posts: true, perfil: true },
483
+ },
484
+ }).build(prisma);
485
+ ```
486
+
487
+ **Usando um `includeModel` na chamada:**
488
+
489
+ ```ts
490
+ const usuario = await usuarioRepository.get(id, { includeModel: "comPosts" });
491
+ ```
492
+
493
+ Nesse caso, o `select` padrão (`selectModels`/`defaultSelectModel`) é ignorado e apenas o `include` é enviado ao Prisma.
494
+
495
+ ### Diferenças em relação ao `selectModels`
496
+
497
+ - **Só pode ser passado na chamada do método**, via `options.includeModel`. Não existe `defaultIncludeModel` nem `defaultInclude` — não há como configurar um `includeModel` padrão no repository, diferente do que ocorre com `defaultSelectModel`.
498
+ - **`includeModel` e `selectModel` não podem ser passados juntos** na mesma chamada. Se um `includeModel` for informado, qualquer `selectModel` (incluindo o padrão) é ignorado.
499
+
500
+ ```ts
501
+ // CORRETO ✅ — apenas includeModel
502
+ await usuarioRepository.get(id, { includeModel: "comPosts" });
503
+
504
+ // CORRETO ✅ — apenas selectModel
505
+ await usuarioRepository.get(id, { selectModel: "public" });
506
+
507
+ // ERRADO ❌ — não é permitido combinar os dois
508
+ await usuarioRepository.get(id, { selectModel: "public", includeModel: "comPosts" });
509
+ ```
510
+
511
+ ---
512
+
466
513
  ## Required Where
467
514
 
468
515
  `requiredWhere` define filtros aplicados automaticamente em todas as queries do repository.
@@ -485,7 +532,47 @@ const usuario = await usuarioRepository.findByEmail("joao@email.com");
485
532
 
486
533
  ---
487
534
 
488
- ## Opção `see`
535
+ ## Default Ordenation
536
+
537
+ `defaultOrdenation` define uma ordenação padrão aplicada automaticamente em todas as queries que aceitam `orderBy`, sem precisar repetir o argumento `order` em cada chamada.
538
+
539
+ ```ts
540
+ const usuarioRepository = setupVSRepo<Usuario, "usuario">()(({
541
+ tableName: "usuario",
542
+ pkName: "id",
543
+ defaultOrdenation: { criadoEm: "desc" },
544
+ }).build(prisma);
545
+ ```
546
+
547
+ Com isso, toda query de listagem já virá ordenada por `criadoEm` decrescente:
548
+
549
+ ```ts
550
+ // Internamente: ORDER BY criadoEm DESC
551
+ const usuarios = await usuarioRepository.getAll();
552
+
553
+ // Também aplica ao getAll com pagination
554
+ const paginados = await usuarioRepository.getAll({ pagination: { take: 10 } });
555
+ ```
556
+
557
+ **A `defaultOrdenation` é ignorada quando:**
558
+
559
+ - O método usa o sufixo `Ordered`, `OrderedAndPaginated` ou `PaginatedAndOrdered` — nesses casos o argumento `order` passado na chamada tem prioridade.
560
+ - O método dinâmico tem `injectOrdenation` configurado — a ordenação fixa do método prevalece.
561
+
562
+ ```ts
563
+ methods: {
564
+ findManyPaginatedAndOrdered: { map: true }, // ordem vem do argumento → defaultOrdenation ignorada
565
+ findManyByAtivo: { map: true }, // sem Ordered → defaultOrdenation aplicada
566
+ findManyByStatus: {
567
+ map: true,
568
+ injectOrdenation: { nome: "asc" }, // injectOrdenation → defaultOrdenation ignorada
569
+ },
570
+ }
571
+ ```
572
+
573
+ > `defaultOrdenation` aceita o mesmo tipo que o `orderBy` nativo do Prisma para o modelo — incluindo arrays de ordenações encadeadas.
574
+
575
+ ---
489
576
 
490
577
  Quando `softRemovekName` está configurado, todos os métodos base aceitam a opção `see` para controlar a visibilidade de registros soft-deletados:
491
578
 
@@ -932,6 +1019,8 @@ type SeeMode = "active" | "removed" | "all";
932
1019
  import type {
933
1020
  SelectModel,
934
1021
  SelectModels,
1022
+ IncludeModel,
1023
+ IncludeModels,
935
1024
  WhereModel,
936
1025
  OrdenationModel,
937
1026
  PaginationModel,
@@ -945,14 +1034,16 @@ import type {
945
1034
  ```ts
946
1035
  import type { MethodOptions, MethodOptionsModel } from "../../generated/vsrepo";
947
1036
 
948
- // MethodOptions<S> — opções passadas nos métodos do repository
949
- type Opts = MethodOptions<"public" | "minimal">;
1037
+ // MethodOptions<S, IM> — opções passadas nos métodos do repository
1038
+ type Opts = MethodOptions<"public" | "minimal", "comPosts">;
950
1039
 
951
1040
  // MethodOptionsModel<TRepo> — derivado de uma instância VSRepository configurada
952
1041
  const usuarioVSRepo = setupVSRepo<Usuario, "usuario">()(config);
953
1042
  type OptsModel = MethodOptionsModel<typeof usuarioVSRepo>;
954
1043
  ```
955
1044
 
1045
+ > O segundo parâmetro de `MethodOptions` (`IM`) representa as chaves válidas de `includeModels`. Quando informado, `selectModel` e `includeModel` tornam-se mutuamente exclusivos no tipo — não é possível passar os dois na mesma chamada.
1046
+
956
1047
  ### Tipos de configuração
957
1048
 
958
1049
  ```ts
@@ -1005,14 +1096,16 @@ type UsuarioPatchPayload = PatchObject<Prisma.UsuarioUpdateInput, typeof usuario
1005
1096
 
1006
1097
  ```ts
1007
1098
  setupVSRepo<TPayload, TTableName>()({
1008
- tableName: Uncapitalize<M>; // Nome da tabela no Prisma
1009
- pkName: keyof T; // Nome da primary key
1010
- softRemovekName?: keyof T & string; // Campo DateTime para soft-delete (opcional)
1011
- selectModels?: SelectModels<M>; // Projeções de dados nomeadas
1012
- defaultSelectModel?: keyof SM; // Select aplicado por padrão
1013
- requiredWhere?: WhereModel<M>; // Filtros sempre aplicados
1014
- relations?: RepositoryRelations<T>; // Configuração de relações
1015
- methods?: Record<string, MethodConfig<M, SM>>; // Métodos dinâmicos
1099
+ tableName: Uncapitalize<M>; // Nome da tabela no Prisma
1100
+ pkName: keyof T; // Nome da primary key
1101
+ softRemovekName?: keyof T & string; // Campo DateTime para soft-delete (opcional)
1102
+ selectModels?: SelectModels<M>; // Projeções de dados nomeadas (select)
1103
+ defaultSelectModel?: keyof SM; // Select aplicado por padrão
1104
+ includeModels?: IncludeModels<M>; // Projeções de dados nomeadas (include) — sem default, só na chamada
1105
+ requiredWhere?: WhereModel<M>; // Filtros sempre aplicados
1106
+ defaultOrdenation?: OrdenationModel<M>; // Ordenação padrão para queries sem Ordered/injectOrdenation
1107
+ relations?: RepositoryRelations<T>; // Configuração de relações
1108
+ methods?: Record<string, MethodConfig<M, SM>>; // Métodos dinâmicos
1016
1109
  });
1017
1110
  ```
1018
1111
 
@@ -1104,6 +1197,12 @@ Para reportar problemas ou sugerir novas funcionalidades, abra uma **Issue**.
1104
1197
 
1105
1198
  **Select model retorna campos inesperados** — Verifique se o select model define exatamente os campos que o seu tipo TypeScript espera. Campos com `false` não serão retornados pelo Prisma.
1106
1199
 
1200
+ **`selectModel` e `includeModel` juntos na mesma chamada** — Não é permitido. Escolha um ou outro: se `includeModel` for informado, o `select` (incluindo o `defaultSelectModel`) é ignorado e apenas o `include` é enviado ao Prisma.
1201
+
1202
+ **`includeModel` não aparece como opção padrão do repository** — Isso é esperado. Diferente de `defaultSelectModel`, não existe `defaultIncludeModel`/`defaultInclude`. Um `includeModel` só pode ser definido na chamada do método, via `options.includeModel`.
1203
+
1107
1204
  **`softRemovekName` lança erro no build** — O campo informado deve ser do tipo `DateTime` no schema do Prisma. Tipos como `Boolean` ou `String` não são aceitos.
1108
1205
 
1109
- **`saveList`/`patchList` com `db` inválido** — O campo `db` nestes métodos aceita apenas `DbTransaction` (retorno de `prisma.$transaction`), não o cliente principal. Passar o `PrismaClient` diretamente causará comportamento inesperado.
1206
+ **`defaultOrdenation` não está sendo aplicada** — Verifique se o método não usa o sufixo `Ordered`, `OrderedAndPaginated` ou `PaginatedAndOrdered`, e se não possui `injectOrdenation` configurado. Ambos têm prioridade sobre a ordenação padrão.
1207
+
1208
+ **`saveList`/`patchList` com `db` inválido** — O campo `db` nestes métodos aceita apenas `DbTransaction` (retorno de `prisma.$transaction`), não o cliente principal. Passar o `PrismaClient` diretamente causará comportamento inesperado.
@@ -50,5 +50,5 @@ export declare class VSRepoExtendError extends VSRepoError {
50
50
  */
51
51
  export declare class VSRepoRuntimeError extends VSRepoError {
52
52
  readonly type: 'VSREPO_RUNTIME';
53
- constructor(message: string, code?: string);
53
+ constructor(message: string, code: string);
54
54
  }
@@ -195,7 +195,7 @@ type GetCreateManyInput<I> = I extends { createManyInput: infer CM } ? CM : unkn
195
195
  type GetUpdateManyInput<I> = I extends { updateManyInput: infer UM } ? UM : unknown;
196
196
  type GetWhereInput<I> = I extends { whereInput: infer W } ? NonNullable<W> : unknown;
197
197
  type GetCursorInput<I> = I extends { cursorInput: infer C } ? C : unknown;
198
- type GetOrderByInput<I> = I extends { orderByInput: infer OB } ? OB : OrderOptions;
198
+ type GetOrderByInput<I> = I extends { orderByInput: infer OB } ? NonNullable<OB> : OrderOptions;
199
199
 
200
200
  type ExtraArgs<M extends string, R extends string, I> = [
201
201
  ...(M extends 'upsertBy' ? [update: GetUpdateInput<I>, create: GetCreateInput<I>]
@@ -222,14 +222,22 @@ type PrecomputedSelects<M extends Prisma.ModelName, SelectModels> = {
222
222
  [S in keyof SelectModels]: Prisma.Result<PrismaDelegate<M>, { select: SelectModels[S] }, 'findMany'> extends Array<infer U> ? U : never
223
223
  };
224
224
 
225
- type SelectedModel<M extends Prisma.ModelName, S, SelectModels> =
226
- [S] extends [false]
227
- ? FullModelType<M>
228
- : [S] extends [never]
229
- ? FullModelType<M>
230
- : [S] extends [keyof SelectModels]
231
- ? PrecomputedSelects<M, SelectModels>[S]
232
- : FullModelType<M>;
225
+ type PrecomputedIncludes<M extends Prisma.ModelName, IncludeModels> = {
226
+ [I in keyof IncludeModels]: Prisma.Result<PrismaDelegate<M>, { include: IncludeModels[I] }, 'findMany'> extends Array<infer U> ? U : never
227
+ };
228
+
229
+ type SelectedModel<M extends Prisma.ModelName, S, SelectModels, IM = never, IncludeModels = {}> =
230
+ [IM] extends [never]
231
+ ? [S] extends [false]
232
+ ? FullModelType<M>
233
+ : [S] extends [never]
234
+ ? FullModelType<M>
235
+ : [S] extends [keyof SelectModels]
236
+ ? PrecomputedSelects<M, SelectModels>[S]
237
+ : FullModelType<M>
238
+ : IM extends keyof IncludeModels
239
+ ? PrecomputedIncludes<M, IncludeModels>[IM]
240
+ : FullModelType<M>;
233
241
 
234
242
  type CleanFields<R extends string> =
235
243
  R extends `${infer F}PaginatedAndOrdered` ? F :
@@ -242,17 +250,10 @@ type CleanFields<R extends string> =
242
250
  * Additional options accepted by repository methods.
243
251
  *
244
252
  * @template S Available keys in `selectModels`.
253
+ * @template IM Available keys in `includeModels`.
245
254
  */
246
- export type MethodOptions<S> = {
247
- /**
248
- * Select model to apply to the operation.
249
- *
250
- * @note Use `false` to return the full Prisma payload without a select.
251
- */
252
- selectModel?: S | false;
253
- /**
254
- * Prisma client or transaction to use for the operation.
255
- */
255
+ export type MethodOptions<S, IM extends PropertyKey = never> = {
256
+ /** Prisma client or transaction to use for the operation. */
256
257
  db?: ClientOrTransaction;
257
258
  /**
258
259
  * Visibility mode for records with soft-delete.
@@ -264,7 +265,17 @@ export type MethodOptions<S> = {
264
265
  * - `"all"` — returns all records, ignoring deletion status.
265
266
  */
266
267
  see?: SeeMode;
267
- };
268
+ } & (
269
+ [IM] extends [never]
270
+ ? {
271
+ /** Select model to apply to the operation. Use `false` to return the full payload. */
272
+ selectModel?: S | false;
273
+ /** Include model to apply to the operation. Cannot be used together with `selectModel`. */
274
+ includeModel?: never;
275
+ }
276
+ : | { selectModel?: S | false; includeModel?: never }
277
+ | { selectModel?: never; includeModel: IM }
278
+ );
268
279
 
269
280
  /**
270
281
  * Version of `MethodOptions` derived directly from a configured `VSRepository` instance.
@@ -277,11 +288,13 @@ export type MethodOptions<S> = {
277
288
  */
278
289
  export type MethodOptionsModel<TRepo> =
279
290
  TRepo extends VSRepository<any, any, infer Config>
280
- ? MethodOptions<keyof ExtractSelectModels<Config> | false>
291
+ ? MethodOptions<keyof ExtractSelectModels<Config> | false, keyof ExtractIncludeModels<Config>>
281
292
  : never;
282
293
 
283
- type MethodFn<MethodName extends string, T, M extends Prisma.ModelName, R extends string, SelectModels, DefaultSelect extends keyof SelectModels | false, I> =
284
- <S extends keyof SelectModels | false = DefaultSelect>(...args: [...ExtractFields<T, CleanFields<R>, I>, ...ExtraArgs<MethodName, R, I>, options?: MethodOptions<S>]) => Promise<ResolveReturnType<MethodName, SelectedModel<M, S, SelectModels>>>;
294
+ type MethodFn<MethodName extends string, T, M extends Prisma.ModelName, R extends string, SelectModels, DefaultSelect extends keyof SelectModels | false, I, IncludeModels> =
295
+ <S extends keyof SelectModels | false = DefaultSelect, IM extends keyof IncludeModels = never>(
296
+ ...args: [...ExtractFields<T, CleanFields<R>, I>, ...ExtraArgs<MethodName, R, I>, options?: MethodOptions<S, keyof IncludeModels> & ({ includeModel: IM } | { includeModel?: never })]
297
+ ) => Promise<ResolveReturnType<MethodName, SelectedModel<M, S, SelectModels, IM, IncludeModels>>>;
285
298
 
286
299
  type GetMappedMethod<K extends string, MethodConf> =
287
300
  K extends `findBy${string}` ? (MethodConf extends { fbMode: 'one' } ? 'findByOne' : 'findByList') :
@@ -332,13 +345,13 @@ type ExtractPatternBase<K extends string> =
332
345
  K extends `updateManyAndReturnWhere${infer R}` ? R :
333
346
  K extends `deleteManyWhere${infer R}` ? R : '';
334
347
 
335
- type MethodFactory<T, M extends Prisma.ModelName, K extends string, SelectModels, DefaultSelect extends keyof SelectModels | false, I, MethodConf> =
348
+ type MethodFactory<T, M extends Prisma.ModelName, K extends string, SelectModels, DefaultSelect extends keyof SelectModels | false, I, MethodConf, IncludeModels> =
336
349
  K extends `findWhere${string}`
337
350
  ? {
338
351
  /** @deprecated Use findOneWhere instead. */
339
- <S extends keyof SelectModels | false = DefaultSelect>(...args: [...ExtractFields<T, CleanFields<ExtractPatternBase<K>>, I>, ...ExtraArgs<GetMappedMethod<K, MethodConf>, ExtractPatternBase<K>, I>, options?: MethodOptions<S>]): Promise<ResolveReturnType<GetMappedMethod<K, MethodConf>, SelectedModel<M, S, SelectModels>>>;
352
+ <S extends keyof SelectModels | false = DefaultSelect, IM extends keyof IncludeModels = never>(...args: [...ExtractFields<T, CleanFields<ExtractPatternBase<K>>, I>, ...ExtraArgs<GetMappedMethod<K, MethodConf>, ExtractPatternBase<K>, I>, options?: MethodOptions<S, keyof IncludeModels> & ({ includeModel: IM } | { includeModel?: never })]): Promise<ResolveReturnType<GetMappedMethod<K, MethodConf>, SelectedModel<M, S, SelectModels, IM, IncludeModels>>>;
340
353
  }
341
- : MethodFn<GetMappedMethod<K, MethodConf>, T, M, ExtractPatternBase<K>, SelectModels, DefaultSelect, I>;
354
+ : MethodFn<GetMappedMethod<K, MethodConf>, T, M, ExtractPatternBase<K>, SelectModels, DefaultSelect, I, IncludeModels>;
342
355
 
343
356
  type ResolveSelectModel<MethodConf, GlobalConf, SelectModels> =
344
357
  MethodConf extends { selectModel: infer S } ? (S extends false ? false : S extends keyof SelectModels ? S : never) :
@@ -346,9 +359,11 @@ type ResolveSelectModel<MethodConf, GlobalConf, SelectModels> =
346
359
 
347
360
  type ExtractPkName<T, Config> = Config extends { pkName: infer PK } ? (PK extends keyof T ? PK : never) : never;
348
361
  type ExtractSelectModels<Config> = Config extends { selectModels: infer SM } ? SM : {};
362
+ type ExtractIncludeModels<Config> = Config extends { includeModels: infer IM } ? IM : {};
349
363
  type ExtractDefaultSelect<Config> = Config extends { defaultSelectModel: infer D } ? D : never;
350
364
  type ExtractRelations<Config> = Config extends { relations: infer R } ? (R extends object ? R : {}) : {};
351
365
  type ExtractSoftRemovekName<Config> = Config extends { softRemovekName: infer S } ? S : never;
366
+ type ExtractDefaultOrdenation<Config> = Config extends { defaultOrdenation: infer O } ? O : never;
352
367
 
353
368
  type AggregateMethod<M extends Prisma.ModelName> = <A extends Prisma.TypeMap['model'][M]['operations']['aggregate']['args']>(
354
369
  prismaArgs: A,
@@ -369,7 +384,7 @@ type DynamicMethods<T, M extends Prisma.ModelName, Config, I> = Config extends {
369
384
  : ResolvedKey extends 'groupBy'
370
385
  ? GroupByMethod<M>
371
386
  : ResolvedKey extends string
372
- ? MethodFactory<T, M, ResolvedKey, ExtractSelectModels<Config>, ResolveSelectModel<Methods[K], Config, ExtractSelectModels<Config>>, I, Methods[K]>
387
+ ? MethodFactory<T, M, ResolvedKey, ExtractSelectModels<Config>, ResolveSelectModel<Methods[K], Config, ExtractSelectModels<Config>>, I, Methods[K], ExtractIncludeModels<Config>>
373
388
  : never
374
389
  : never
375
390
  : never;
@@ -384,6 +399,8 @@ type DynamicMethods<T, M extends Prisma.ModelName, Config, I> = Config extends {
384
399
  export type PrismaModelInputs<M extends Prisma.ModelName> = {
385
400
  /** Type of the `select` argument used in model queries. */
386
401
  select: Prisma.TypeMap['model'][M]['operations']['findMany']['args']['select'];
402
+ /** Type of the `include` argument used in model queries. */
403
+ include: Prisma.TypeMap['model'][M]['operations']['findMany']['args']['include'];
387
404
  /** Type of the `data` used in `create`. */
388
405
  createInput: Prisma.TypeMap['model'][M]['operations']['create']['args']['data'];
389
406
  /** Type of the `data` used in `createMany`. */
@@ -414,6 +431,16 @@ export type SelectModel<M extends Prisma.ModelName> = PrismaModelInputs<M>['sele
414
431
  */
415
432
  export type SelectModels<M extends Prisma.ModelName> = Record<string, SelectModel<M>>;
416
433
 
434
+ /**
435
+ * Type of the `include` object of a Prisma model.
436
+ */
437
+ export type IncludeModel<M extends Prisma.ModelName> = PrismaModelInputs<M>['include'];
438
+
439
+ /**
440
+ * Map of named, reusable includes for a Prisma model.
441
+ */
442
+ export type IncludeModels<M extends Prisma.ModelName> = Record<string, IncludeModel<M>>;
443
+
417
444
  /**
418
445
  * Type of the `where` object of a Prisma model.
419
446
  */
@@ -451,8 +478,7 @@ export type MethodConfig<M extends Prisma.ModelName, SelectModels = any> = {
451
478
  readonly proxyTo?: ValidMethodPatterns;
452
479
  /** Adds an extra `where` on top of `requiredWhere`. */
453
480
  readonly pushWhere?: WhereModel<M>;
454
- /**
455
- * Defines whether `findBy` returns a single item (`one`) or a list (`list`).
481
+ /** * Defines whether `findBy` returns a single item (`one`) or a list (`list`).
456
482
  * @deprecated Use `findOneBy` if you want to return a single result.
457
483
  */
458
484
  readonly fbMode?: 'one' | 'list';
@@ -496,8 +522,12 @@ export type BuildConfig<TSelectKeys extends PropertyKey = string> = {
496
522
  remove?: BaseMethodConfig<TSelectKeys>;
497
523
  /** Configuration for the `save` method. */
498
524
  save?: BaseMethodConfig<TSelectKeys>;
525
+ /** Configuration for the `saveList` method (batch save via transaction). */
526
+ saveList?: BaseMethodConfig<TSelectKeys>;
499
527
  /** Configuration for the `patch` method. */
500
528
  patch?: BaseMethodConfig<TSelectKeys>;
529
+ /** Configuration for the `patchList` method (batch update via transaction). */
530
+ patchList?: BaseMethodConfig<TSelectKeys>;
501
531
  /** Configuration for the `merge` method. */
502
532
  merge?: BaseMethodConfig<TSelectKeys>;
503
533
  /** Configuration for the `removeList` method (batch deletion). Does not accept select. */
@@ -508,10 +538,6 @@ export type BuildConfig<TSelectKeys extends PropertyKey = string> = {
508
538
  total?: Omit<BaseMethodConfig<TSelectKeys>, 'defaultSelect'>;
509
539
  /** Configuration for the `has` method (existence check). Does not accept select. */
510
540
  has?: Omit<BaseMethodConfig<TSelectKeys>, 'defaultSelect'>;
511
- /** Configuration for the `saveList` method (batch save via transaction). */
512
- saveList?: BaseMethodConfig<TSelectKeys>;
513
- /** Configuration for the `patchList` method (batch update via transaction). */
514
- patchList?: BaseMethodConfig<TSelectKeys>;
515
541
  /** Configuration for the `softRemove` method. Only available if `softRemovekName` is configured. */
516
542
  softRemove?: BaseMethodConfig<TSelectKeys>;
517
543
  /** Configuration for the `softRemoveList` method. Does not accept select. Only available if `softRemovekName` is configured. */
@@ -534,12 +560,16 @@ type ResolveMethodDefaultSelect<Config, C, Method extends keyof NonNullable<Buil
534
560
  ? ExtractDefaultSelect<Config>
535
561
  : false;
536
562
 
537
- type ResolveCurrentReturn<M extends Prisma.ModelName, Models, S, D> =
538
- [S] extends [false]
539
- ? FullModelType<M>
540
- : [S] extends [never]
541
- ? ([D] extends [never] ? FullModelType<M> : SelectedModel<M, D, Models>)
542
- : SelectedModel<M, S, Models>;
563
+ type ResolveCurrentReturn<M extends Prisma.ModelName, Models, S, D, IM = never, Includes = {}> =
564
+ [IM] extends [never]
565
+ ? [S] extends [false]
566
+ ? FullModelType<M>
567
+ : [S] extends [never]
568
+ ? ([D] extends [never] ? FullModelType<M> : SelectedModel<M, D, Models>)
569
+ : SelectedModel<M, S, Models>
570
+ : IM extends keyof Includes
571
+ ? PrecomputedIncludes<M, Includes>[IM]
572
+ : FullModelType<M>;
543
573
 
544
574
  // ─── helpers reused within the mapped type ───────────────────────────────────
545
575
  // ─── relation payload types ──────────────────────────────────────────────────
@@ -602,13 +632,21 @@ type RelationUpdatePayload<TField, TRelationConfig, M extends Prisma.ModelName,
602
632
  : never;
603
633
 
604
634
  /**
605
- * Payload accepted by `patch` when the repository has configured relations.
635
+ * Payload accepted by `merge` when the repository has configured relations (uses update input).
606
636
  */
607
637
  type UpdateWithRelations<T, M extends Prisma.ModelName, TRelations> =
608
638
  DistributiveOmit<PrismaModelInputs<M>['updateInput'], keyof TRelations> & {
609
639
  [K in Extract<keyof TRelations, keyof T>]?: RelationUpdatePayload<T[K], TRelations[K], M, K>;
610
640
  };
611
641
 
642
+ /**
643
+ * Payload accepted by `patch` and `patchList` when the repository has configured relations (uses create input).
644
+ */
645
+ type PatchWithRelations<T, M extends Prisma.ModelName, TRelations> =
646
+ DistributiveOmit<PrismaModelInputs<M>['updateInput'], keyof TRelations> & {
647
+ [K in Extract<keyof TRelations, keyof T>]?: RelationPayload<T[K], TRelations[K], M, K>;
648
+ };
649
+
612
650
  /**
613
651
  * Extracts the payload type of the `save` method from a configured VSRepository instance.
614
652
  */
@@ -630,20 +668,22 @@ export type PatchObject<TInput, TRepo> =
630
668
  TRepo extends VSRepository<infer T, infer M, infer Config>
631
669
  ? (Config extends { relations: infer R } ? (R extends object ? R : {}) : {}) extends infer TRelations
632
670
  ? DistributiveOmit<TInput, keyof TRelations> & {
633
- [K in Extract<keyof TRelations, keyof T>]?: RelationUpdatePayload<T[K], TRelations[K], M, K>;
671
+ [K in Extract<keyof TRelations, keyof T>]?: RelationPayload<T[K], TRelations[K], M, K>;
634
672
  }
635
673
  : never
636
674
  : never;
637
675
 
638
676
 
639
677
  type _Pk<T, Config> = WidenField<T[ExtractPkName<T, Config> extends keyof T ? ExtractPkName<T, Config> : never]>;
640
- type _Ret<M extends Prisma.ModelName, TSelects, S, TDefault> = ResolveCurrentReturn<M, TSelects, S, TDefault>;
678
+ type _Ret<M extends Prisma.ModelName, TSelects, S, TDefault, IM = never, TIncludes = {}> = ResolveCurrentReturn<M, TSelects, S, TDefault, IM, TIncludes>;
641
679
  type _DS<Config, C, Method extends keyof NonNullable<BuildConfig['baseMethods']>, TSelects = ExtractSelectModels<Config>> =
642
680
  ResolveMethodDefaultSelect<Config, C, Method, TSelects>;
643
681
  type _Sel<Config> = ExtractSelectModels<Config>;
682
+ type _Inc<Config> = ExtractIncludeModels<Config>;
644
683
  type _Def<Config> = ExtractDefaultSelect<Config>;
645
684
  type _Rel<Config> = ExtractRelations<Config>;
646
685
  type _Soft<Config> = ExtractSoftRemovekName<Config>;
686
+ type _DOrd<Config> = ExtractDefaultOrdenation<Config>;
647
687
 
648
688
  // ─── refactored mapped type — optimized for the TS compiler ──────────────────
649
689
 
@@ -657,63 +697,70 @@ type AllBaseMethods<
657
697
  TPk = ExtractPkName<T, Config>,
658
698
  TRelations = _Rel<Config>,
659
699
  TSoftKey = _Soft<Config>,
660
- I = PrismaModelInputs<M>
700
+ I = PrismaModelInputs<M>,
701
+ TDefaultOrdenation = _DOrd<Config>,
702
+ TIncludes = _Inc<Config>
661
703
  > = {
662
704
  /** Fetches a record by its primary key (PK). */
663
- get: <S extends keyof TSelects | false = _DS<Config, C, 'get', TSelects>>(
664
- pk: _Pk<T, Config>, options?: MethodOptions<S>
665
- ) => Promise<_Ret<M, TSelects, S, TDefault> | null>;
705
+ get: <S extends keyof TSelects | false = _DS<Config, C, 'get', TSelects>, IM extends keyof TIncludes = never>(
706
+ pk: _Pk<T, Config>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
707
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes> | null>;
666
708
 
667
709
  /** Fetches a record by PK and throws `VSRepoRuntimeError` if not found. */
668
- getOrThrow: <S extends keyof TSelects | false = _DS<Config, C, 'getOrThrow', TSelects>>(
669
- pk: _Pk<T, Config>, options?: MethodOptions<S>
670
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
710
+ getOrThrow: <S extends keyof TSelects | false = _DS<Config, C, 'getOrThrow', TSelects>, IM extends keyof TIncludes = never>(
711
+ pk: _Pk<T, Config>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
712
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
671
713
 
672
714
  /** Fetches multiple records by a list of primary keys (PKs). */
673
- getList: <S extends keyof TSelects | false = _DS<Config, C, 'getList', TSelects>>(
674
- pks: _Pk<T, Config>[], options?: MethodOptions<S>
675
- ) => Promise<_Ret<M, TSelects, S, TDefault>[]>;
715
+ getList: <S extends keyof TSelects | false = _DS<Config, C, 'getList', TSelects>, IM extends keyof TIncludes = never>(
716
+ pks: _Pk<T, Config>[], options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
717
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>[]>;
676
718
 
677
719
  /** Deletes a record identified by its primary key (PK). */
678
- remove: <S extends keyof TSelects | false = _DS<Config, C, 'remove', TSelects>>(
679
- pk: _Pk<T, Config>, options?: MethodOptions<S>
680
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
720
+ remove: <S extends keyof TSelects | false = _DS<Config, C, 'remove', TSelects>, IM extends keyof TIncludes = never>(
721
+ pk: _Pk<T, Config>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
722
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
681
723
 
682
724
  /** Inserts or updates (upsert) a record. */
683
- save: <S extends keyof TSelects | false = _DS<Config, C, 'save', TSelects>>(
684
- obj: UpsertWithRelations<T, M, TRelations>, options?: MethodOptions<S>
685
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
725
+ save: <S extends keyof TSelects | false = _DS<Config, C, 'save', TSelects>, IM extends keyof TIncludes = never>(
726
+ obj: UpsertWithRelations<T, M, TRelations>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
727
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
686
728
 
687
729
  /** Saves an array of objects in a single automatic transaction. */
688
- saveList: <S extends keyof TSelects | false = _DS<Config, C, 'saveList', TSelects>>(
689
- objs: UpsertWithRelations<T, M, TRelations>[], options?: Omit<MethodOptions<S>, 'db'> & { db?: DbTransaction }
690
- ) => Promise<_Ret<M, TSelects, S, TDefault>[]>;
730
+ saveList: <S extends keyof TSelects | false = _DS<Config, C, 'saveList', TSelects>, IM extends keyof TIncludes = never>(
731
+ objs: UpsertWithRelations<T, M, TRelations>[], options?: Omit<MethodOptions<S, keyof TIncludes>, 'db'> & ({ includeModel: IM } | { includeModel?: never }) & { db?: DbTransaction }
732
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>[]>;
691
733
 
692
734
  /** Partially updates (patch) an existing record by its primary key (PK). */
693
- patch: <S extends keyof TSelects | false = _DS<Config, C, 'patch', TSelects>>(
694
- pk: _Pk<T, Config>, obj: UpdateWithRelations<T, M, TRelations>, options?: MethodOptions<S>
695
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
735
+ patch: <S extends keyof TSelects | false = _DS<Config, C, 'patch', TSelects>, IM extends keyof TIncludes = never>(
736
+ pk: _Pk<T, Config>, obj: PatchWithRelations<T, M, TRelations>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
737
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
696
738
 
697
739
  /** Partially updates multiple records via `[pk, obj]` tuples in an automatic transaction. */
698
- patchList: <S extends keyof TSelects | false = _DS<Config, C, 'patchList', TSelects>>(
699
- tuples: [pk: _Pk<T, Config>, obj: UpdateWithRelations<T, M, TRelations>][], options?: Omit<MethodOptions<S>, 'db'> & { db?: DbTransaction }
700
- ) => Promise<_Ret<M, TSelects, S, TDefault>[]>;
740
+ patchList: <S extends keyof TSelects | false = _DS<Config, C, 'patchList', TSelects>, IM extends keyof TIncludes = never>(
741
+ tuples: [pk: _Pk<T, Config>, obj: PatchWithRelations<T, M, TRelations>][], options?: Omit<MethodOptions<S, keyof TIncludes>, 'db'> & ({ includeModel: IM } | { includeModel?: never }) & { db?: DbTransaction }
742
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>[]>;
701
743
 
702
744
  /** Fetches a record by PK and deep-merges it with the provided object **in memory**. */
703
- merge: <S extends keyof TSelects | false = _DS<Config, C, 'merge', TSelects>>(
704
- pk: _Pk<T, Config>, obj: UpdateWithRelations<T, M, TRelations>, options?: MethodOptions<S>
705
- ) => Promise<_Ret<M, TSelects, S, TDefault> | null>;
745
+ merge: <S extends keyof TSelects | false = _DS<Config, C, 'merge', TSelects>, IM extends keyof TIncludes = never>(
746
+ pk: _Pk<T, Config>, obj: UpdateWithRelations<T, M, TRelations>, options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never })
747
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes> | null>;
706
748
 
707
749
  /** Deletes multiple records by their primary keys. */
708
750
  removeList: (pks: _Pk<T, Config>[], options?: { db?: ClientOrTransaction }) => Promise<{ count: number }>;
709
751
 
710
752
  /** Fetches all records (respects `requiredWhere` when set). */
711
- getAll: <S extends keyof TSelects | false = _DS<Config, C, 'getAll', TSelects>>(
712
- options?: MethodOptions<S> & {
753
+ getAll: <S extends keyof TSelects | false = _DS<Config, C, 'getAll', TSelects>, IM extends keyof TIncludes = never>(
754
+ options?: MethodOptions<S, keyof TIncludes> & ({ includeModel: IM } | { includeModel?: never }) & {
713
755
  pagination?: PaginationOptions<I extends { cursorInput: infer Curs } ? Curs : unknown>;
756
+ /**
757
+ * Ordering to apply to the query.
758
+ * When omitted and `defaultOrdenation` is configured on the repository,
759
+ * the default ordering is applied automatically.
760
+ */
714
761
  order?: I extends { orderByInput: infer OB } ? OB : OrderOptions;
715
762
  }
716
- ) => Promise<_Ret<M, TSelects, S, TDefault>[]>;
763
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>[]>;
717
764
 
718
765
  /** Returns the total number of records. */
719
766
  total: (options?: { db?: ClientOrTransaction; see?: SeeMode }) => Promise<number>;
@@ -722,17 +769,17 @@ type AllBaseMethods<
722
769
  has: (pk: _Pk<T, Config>, options?: { db?: ClientOrTransaction; see?: SeeMode }) => Promise<boolean>;
723
770
 
724
771
  /** Marks a record as deleted (soft-delete). */
725
- softRemove: <S extends keyof TSelects | false = _DS<Config, C, 'softRemove', TSelects>>(
726
- pk: _Pk<T, Config>, options?: Omit<MethodOptions<S>, 'see'>
727
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
772
+ softRemove: <S extends keyof TSelects | false = _DS<Config, C, 'softRemove', TSelects>, IM extends keyof TIncludes = never>(
773
+ pk: _Pk<T, Config>, options?: Omit<MethodOptions<S, keyof TIncludes>, 'see'> & ({ includeModel: IM } | { includeModel?: never })
774
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
728
775
 
729
776
  /** Marks multiple records as deleted (soft-delete) in batch. */
730
777
  softRemoveList: (pks: _Pk<T, Config>[], options?: { db?: ClientOrTransaction }) => Promise<{ count: number }>;
731
778
 
732
779
  /** Restores a record previously marked as deleted (soft-delete). */
733
- restore: <S extends keyof TSelects | false = _DS<Config, C, 'restore', TSelects>>(
734
- pk: _Pk<T, Config>, options?: Omit<MethodOptions<S>, 'see'>
735
- ) => Promise<_Ret<M, TSelects, S, TDefault>>;
780
+ restore: <S extends keyof TSelects | false = _DS<Config, C, 'restore', TSelects>, IM extends keyof TIncludes = never>(
781
+ pk: _Pk<T, Config>, options?: Omit<MethodOptions<S, keyof TIncludes>, 'see'> & ({ includeModel: IM } | { includeModel?: never })
782
+ ) => Promise<_Ret<M, TSelects, S, TDefault, IM, TIncludes>>;
736
783
 
737
784
  /** Restores multiple records previously marked as deleted (soft-delete) in batch. */
738
785
  restoreList: (pks: _Pk<T, Config>[], options?: { db?: ClientOrTransaction }) => Promise<{ count: number }>;
@@ -748,9 +795,11 @@ type InjectedBaseMethods<
748
795
  TPk = ExtractPkName<T, Config>,
749
796
  TRelations = _Rel<Config>,
750
797
  TSoftKey = _Soft<Config>,
751
- I = PrismaModelInputs<M>
798
+ I = PrismaModelInputs<M>,
799
+ TDefaultOrdenation = _DOrd<Config>,
800
+ TIncludes = _Inc<Config>
752
801
  > = Pick<
753
- AllBaseMethods<T, M, Config, C, TSelects, TDefault, TPk, TRelations, TSoftKey, I>,
802
+ AllBaseMethods<T, M, Config, C, TSelects, TDefault, TPk, TRelations, TSoftKey, I, TDefaultOrdenation, TIncludes>,
754
803
  | (C extends { baseMethods: { get: { active: false } } } ? never : 'get')
755
804
  | (C extends { baseMethods: { getOrThrow: { active: false } } } ? never : 'getOrThrow')
756
805
  | (C extends { baseMethods: { getList: { active: false } } } ? never : 'getList')
@@ -852,7 +901,9 @@ export type RepoConfig<T, M extends Prisma.ModelName, SM extends Record<string,
852
901
  softRemovekName?: keyof T & string;
853
902
  selectModels?: SM;
854
903
  defaultSelectModel?: Extract<keyof SM, string>;
904
+ includeModels?: IncludeModels<M>;
855
905
  requiredWhere?: WhereModel<M>;
906
+ defaultOrdenation?: OrdenationModel<M>;
856
907
  relations?: RepositoryRelations<T>;
857
908
  methods?: Record<string, MethodConfig<M, SM>>;
858
909
  };
@@ -936,12 +987,27 @@ export type ValidateRepoConfig<T extends object, M extends Prisma.ModelName, Con
936
987
  */
937
988
  defaultSelectModel?: string;
938
989
 
990
+ /**
991
+ * Defines named and reusable include projections.
992
+ * Similar to selectModels, but resolves Prisma `include` clauses.
993
+ */
994
+ includeModels?: IncludeModels<M>;
995
+
939
996
  /**
940
997
  * Defines global filters that will be automatically applied to all repository queries.
941
998
  * Useful for tenant isolation (multi-tenancy) or base restrictions (e.g., `isActive: true`).
942
999
  */
943
1000
  requiredWhere?: WhereModel<M>;
944
1001
 
1002
+ /**
1003
+ * Default ordering automatically injected into all queries that accept `orderBy`,
1004
+ * unless the method already has `injectOrdenation` configured or uses the `Ordered` suffix.
1005
+ *
1006
+ * Useful for ensuring a consistent sort order across the repository without repeating
1007
+ * the `order` argument on every call.
1008
+ */
1009
+ defaultOrdenation?: OrdenationModel<M>;
1010
+
945
1011
  /**
946
1012
  * Configures automatic relation management.
947
1013
  * When configured, allows the `save`, `saveList`, `patch`, and `patchList` methods
@@ -35,10 +35,12 @@ class VSRepository {
35
35
  pkName;
36
36
  softRemovekName;
37
37
  selectModels;
38
+ includeModels;
38
39
  defaultSelectModel;
39
40
  requiredWhere;
40
41
  relations;
41
42
  methods;
43
+ defaultOrdenation;
42
44
  constructor(config) {
43
45
  const validatedConfig = (0, constructor_config_validate_1.validateConstructorConfig)(config);
44
46
  this.vsrepocache = new Map();
@@ -46,10 +48,12 @@ class VSRepository {
46
48
  this.pkName = validatedConfig.pkName;
47
49
  this.softRemovekName = validatedConfig.softRemovekName;
48
50
  this.selectModels = validatedConfig.selectModels;
51
+ this.includeModels = validatedConfig.includeModels;
49
52
  this.defaultSelectModel = validatedConfig.defaultSelectModel;
50
53
  this.relations = validatedConfig.relations;
51
54
  this.requiredWhere = validatedConfig.requiredWhere;
52
55
  this.methods = validatedConfig.methods;
56
+ this.defaultOrdenation = validatedConfig.defaultOrdenation;
53
57
  }
54
58
  extend(extensionFunc) {
55
59
  const extension = (0, extension_validate_1.validateExtension)(extensionFunc, this);
@@ -139,6 +143,7 @@ class VSRepository {
139
143
  updatePayload: dinamicMethodInfo.updateIndex !== undefined
140
144
  ? args.at(dinamicMethodInfo.updateIndex)
141
145
  : undefined,
146
+ withOrdenationAndPagination: !dinamicMethodInfo.ignoreOrderByAndPagination,
142
147
  };
143
148
  if (!dinamicMethodInfo.ignoreWhere) {
144
149
  resolveDbAndPrismaArgsData.specificWhere = (0, specific_where_resolve_1.resolveSpecificWhere)(args, dinamicMethodWhereOps.prettyWheres);
@@ -159,7 +164,7 @@ class VSRepository {
159
164
  const missingParams = dinamicMethodInfo.whereParams
160
165
  .concat(dinamicMethodInfo.otherParams)
161
166
  .slice(args.length);
162
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${buildInstance.tableName}: runtime) Missing parameters: ${missingParams.join(", ")}`);
167
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${buildInstance.tableName}: runtime) Missing parameters: ${missingParams.join(", ")}`, "48670");
163
168
  }
164
169
  else if (args.length > dinamicMethodInfo.argsCount) {
165
170
  const optionsArg = args[args.length - 1];
@@ -21,7 +21,7 @@ function resolveBaseMethods(instance, config) {
21
21
  if (baseMethods.get.active) {
22
22
  instance.get = async (pk, options) => {
23
23
  if (pk == undefined)
24
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
24
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
25
25
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
26
26
  instance,
27
27
  baseConfig: baseMethods.get,
@@ -41,7 +41,7 @@ function resolveBaseMethods(instance, config) {
41
41
  if (baseMethods.getOrThrow.active) {
42
42
  instance.getOrThrow = async (pk, options) => {
43
43
  if (pk == undefined)
44
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
44
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
45
45
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
46
46
  instance,
47
47
  baseConfig: baseMethods.getOrThrow,
@@ -64,7 +64,7 @@ function resolveBaseMethods(instance, config) {
64
64
  if (baseMethods.getList.active) {
65
65
  instance.getList = async (pks, options) => {
66
66
  if (!Array.isArray(pks) || pks.some(pk => pk == undefined))
67
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`);
67
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`, "65706");
68
68
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
69
69
  instance,
70
70
  baseConfig: baseMethods.getList,
@@ -84,7 +84,7 @@ function resolveBaseMethods(instance, config) {
84
84
  if (baseMethods.getAll.active) {
85
85
  instance.getAll = async (options) => {
86
86
  if (options !== undefined && !(0, is_object_validate_1.isObject)(options))
87
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'options' must be a valid object.`);
87
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'options' must be a valid object.`, "65706");
88
88
  const { pagination, order, ...restOptions } = options ?? {};
89
89
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
90
90
  instance,
@@ -92,6 +92,7 @@ function resolveBaseMethods(instance, config) {
92
92
  options: restOptions,
93
93
  pagination,
94
94
  ordenation: order,
95
+ withOrdenationAndPagination: true,
95
96
  });
96
97
  const start = showWorking
97
98
  ? (0, logger_util_1.performanceLoggerStart)(tableName, "getAll", prismaArgs)
@@ -106,7 +107,7 @@ function resolveBaseMethods(instance, config) {
106
107
  if (baseMethods.remove.active) {
107
108
  instance.remove = async (pk, options) => {
108
109
  if (pk == undefined)
109
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
110
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
110
111
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
111
112
  instance,
112
113
  baseConfig: baseMethods.remove,
@@ -126,7 +127,7 @@ function resolveBaseMethods(instance, config) {
126
127
  if (baseMethods.removeList.active) {
127
128
  instance.removeList = async (pks, options) => {
128
129
  if (!Array.isArray(pks) || pks.some(pk => pk == undefined))
129
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`);
130
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`, "65706");
130
131
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
131
132
  instance,
132
133
  baseConfig: baseMethods.removeList,
@@ -165,7 +166,7 @@ function resolveBaseMethods(instance, config) {
165
166
  if (baseMethods.has.active) {
166
167
  instance.has = async (pk, options) => {
167
168
  if (pk == undefined)
168
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
169
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
169
170
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
170
171
  instance,
171
172
  baseConfig: baseMethods.has,
@@ -186,9 +187,9 @@ function resolveBaseMethods(instance, config) {
186
187
  if (baseMethods.merge.active) {
187
188
  instance.merge = async (pk, obj, options) => {
188
189
  if (pk == undefined)
189
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
190
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
190
191
  if (!(0, is_object_validate_1.isObject)(obj)) {
191
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`);
192
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`, "65706");
192
193
  }
193
194
  (0, obj_with_relations_validate_1.validateObjWithRelations)(instance, obj, relationsKeys);
194
195
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
@@ -272,7 +273,7 @@ function resolveBaseMethods(instance, config) {
272
273
  if (baseMethods.softRemove.active && softRemovekName) {
273
274
  instance.softRemove = async (pk, options) => {
274
275
  if (pk == undefined)
275
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
276
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
276
277
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
277
278
  instance,
278
279
  baseConfig: baseMethods.softRemove,
@@ -294,7 +295,7 @@ function resolveBaseMethods(instance, config) {
294
295
  if (baseMethods.softRemoveList.active && softRemovekName) {
295
296
  instance.softRemoveList = async (pks, options) => {
296
297
  if (!Array.isArray(pks) || pks.some(pk => pk == undefined))
297
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`);
298
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`, "65706");
298
299
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
299
300
  instance,
300
301
  baseConfig: baseMethods.softRemoveList,
@@ -317,7 +318,7 @@ function resolveBaseMethods(instance, config) {
317
318
  if (baseMethods.restore.active && softRemovekName) {
318
319
  instance.restore = async (pk, options) => {
319
320
  if (pk == undefined)
320
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
321
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
321
322
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
322
323
  instance,
323
324
  baseConfig: baseMethods.restore,
@@ -339,7 +340,7 @@ function resolveBaseMethods(instance, config) {
339
340
  if (baseMethods.restoreList.active && softRemovekName) {
340
341
  instance.restoreList = async (pks, options) => {
341
342
  if (!Array.isArray(pks) || pks.some(pk => pk == undefined))
342
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`);
343
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pks' must an array of primary keys.`, "65706");
343
344
  const { db, prismaArgs } = (0, dbAndPrismaArgs_resolve_1.resolveDbAndPrismaArgs)({
344
345
  instance,
345
346
  baseConfig: baseMethods.restoreList,
@@ -362,7 +363,7 @@ function resolveBaseMethods(instance, config) {
362
363
  if (baseMethods.save.active) {
363
364
  instance.save = async (obj, options) => {
364
365
  if (!(0, is_object_validate_1.isObject)(obj)) {
365
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`);
366
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`, "65706");
366
367
  }
367
368
  (0, obj_with_relations_validate_1.validateObjWithRelations)(instance, obj, relationsKeys);
368
369
  const objAny = obj;
@@ -406,7 +407,7 @@ function resolveBaseMethods(instance, config) {
406
407
  if (baseMethods.saveList.active) {
407
408
  instance.saveList = async (objs, options) => {
408
409
  if (!Array.isArray(objs) || objs.some(ob => !(0, is_object_validate_1.isObject)(ob))) {
409
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'objs' must be an array of valid objects.`);
410
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'objs' must be an array of valid objects.`, "65706");
410
411
  }
411
412
  const validatedOptions = (0, method_options_validate_1.validateMethodOptions)(options, instance);
412
413
  const argsList = [];
@@ -465,9 +466,9 @@ function resolveBaseMethods(instance, config) {
465
466
  if (baseMethods.patch.active) {
466
467
  instance.patch = async (pk, obj, options) => {
467
468
  if (pk == undefined)
468
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`);
469
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'pk' must be provided.`, "65706");
469
470
  if (!(0, is_object_validate_1.isObject)(obj)) {
470
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`);
471
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'obj' must be a valid object.`, "65706");
471
472
  }
472
473
  (0, obj_with_relations_validate_1.validateObjWithRelations)(instance, obj, relationsKeys);
473
474
  const { updatePayload } = (0, create_update_payloads_with_relations_resolve_1.resolveCreateUpdatePayloadsWithRelations)(instance, obj, relationsKeys);
@@ -492,7 +493,7 @@ function resolveBaseMethods(instance, config) {
492
493
  instance.patchList = async (tuples, options) => {
493
494
  if (!Array.isArray(tuples) ||
494
495
  tuples.some(tuple => tuple[0] == undefined || !(0, is_object_validate_1.isObject)(tuple[1]))) {
495
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'tuples' must be a valid array of tuples [pk, obj].`);
496
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${tableName}: runtime) 'tuples' must be a valid array of tuples [pk, obj].`, "65706");
496
497
  }
497
498
  const validatedOptions = (0, method_options_validate_1.validateMethodOptions)(options, instance);
498
499
  const argsList = [];
@@ -5,8 +5,8 @@ const method_options_validate_1 = require("../validation/method-options.validate
5
5
  const merge_wheres_resolve_1 = require("./merge-wheres.resolve");
6
6
  const select_resolve_1 = require("./select.resolve");
7
7
  function resolveDbAndPrismaArgs(data) {
8
- const { baseConfig, instance, options, wherePkValue, withoutSelect, withoutWhere, specificSelect, dataPayload, createPayload, updatePayload, alreadyValidatedOptions, specificWhere, pushWhere, ordenation, pagination, skipDuplicates, forceSeeMode, } = data;
9
- const validatedOptions = (alreadyValidatedOptions && options)
8
+ const { baseConfig, instance, options, wherePkValue, withoutSelect, withoutWhere, specificSelect, dataPayload, createPayload, updatePayload, alreadyValidatedOptions, specificWhere, pushWhere, ordenation, pagination, skipDuplicates, forceSeeMode, withOrdenationAndPagination, } = data;
9
+ const validatedOptions = alreadyValidatedOptions && options
10
10
  ? options
11
11
  : (0, method_options_validate_1.validateMethodOptions)(options, instance);
12
12
  const db = validatedOptions.db ?? instance.prisma;
@@ -18,9 +18,15 @@ function resolveDbAndPrismaArgs(data) {
18
18
  }, wherePkValue != undefined ? { [instance.pkName]: wherePkValue } : specificWhere, pushWhere, instance.requiredWhere, instance.softRemovekName);
19
19
  }
20
20
  if (!withoutSelect) {
21
- prismaArgs.select =
22
- specificSelect ??
23
- (0, select_resolve_1.resolveSelect)(instance, validatedOptions.selectModel, baseConfig.defaultSelect);
21
+ if (specificSelect) {
22
+ prismaArgs.select = specificSelect;
23
+ }
24
+ else if (validatedOptions.includeModel) {
25
+ prismaArgs.include = instance.includeModels?.[validatedOptions.includeModel];
26
+ }
27
+ else {
28
+ prismaArgs.select = (0, select_resolve_1.resolveSelect)(instance, validatedOptions.selectModel, baseConfig.defaultSelect);
29
+ }
24
30
  }
25
31
  if (dataPayload) {
26
32
  prismaArgs.data = dataPayload;
@@ -31,13 +37,15 @@ function resolveDbAndPrismaArgs(data) {
31
37
  if (updatePayload) {
32
38
  prismaArgs.update = updatePayload;
33
39
  }
34
- if (ordenation) {
35
- prismaArgs.orderBy = ordenation;
36
- }
37
- if (pagination) {
38
- prismaArgs.skip = pagination.skip;
39
- prismaArgs.take = pagination.take;
40
- prismaArgs.cursor = pagination.cursor;
40
+ if (withOrdenationAndPagination) {
41
+ if (instance.defaultOrdenation || ordenation) {
42
+ prismaArgs.orderBy = ordenation ?? instance.defaultOrdenation;
43
+ }
44
+ if (pagination) {
45
+ prismaArgs.skip = pagination.skip;
46
+ prismaArgs.take = pagination.take;
47
+ prismaArgs.cursor = pagination.cursor;
48
+ }
41
49
  }
42
50
  if (skipDuplicates !== undefined) {
43
51
  prismaArgs.skipDuplicates = skipDuplicates;
@@ -14,6 +14,7 @@ function validateConstructorConfig(config) {
14
14
  pkName: schemas_util_1.stringSchema,
15
15
  softRemovekName: schemas_util_1.stringSchema.optional(),
16
16
  selectModels: zod_1.default.record(schemas_util_1.stringSchema, schemas_util_1.objectSchema).optional(),
17
+ includeModels: zod_1.default.record(schemas_util_1.stringSchema, schemas_util_1.objectSchema).optional(),
17
18
  defaultSelectModel: schemas_util_1.stringSchema.optional(),
18
19
  requiredWhere: schemas_util_1.objectSchema.optional(),
19
20
  relations: zod_1.default
@@ -37,6 +38,7 @@ function validateConstructorConfig(config) {
37
38
  injectPagination: schemas_util_1.objectSchema.optional(),
38
39
  }))
39
40
  .optional(),
41
+ defaultOrdenation: schemas_util_1.objectSchema.or(zod_1.default.array(schemas_util_1.objectSchema)).optional(),
40
42
  })
41
43
  .superRefine((config, ctx) => {
42
44
  if (config.defaultSelectModel && !config.selectModels?.[config.defaultSelectModel]) {
@@ -8,19 +8,27 @@ const zod_1 = __importDefault(require("zod"));
8
8
  const schemas_util_1 = require("../utils/schemas.util");
9
9
  const vs_repo_error_1 = require("../errors/vs-repo.error");
10
10
  function validateMethodOptions(options, instance) {
11
- const optionsSchema = zod_1.default.strictObject({
11
+ const optionsSchema = zod_1.default
12
+ .strictObject({
12
13
  db: schemas_util_1.objectSchema.optional(),
13
14
  selectModel: zod_1.default
14
15
  .literal(false)
15
16
  .or(zod_1.default.enum(Object.keys(instance.selectModels ?? {})))
16
17
  .optional(),
18
+ includeModel: zod_1.default.enum(Object.keys(instance.includeModels ?? {})).optional(),
17
19
  see: zod_1.default.enum(["active", "removed", "all"]).default("active"),
20
+ })
21
+ .refine(data => {
22
+ return !(data.selectModel !== undefined && data.includeModel !== undefined);
23
+ }, {
24
+ message: "cannot be provided with 'selectModel'.",
25
+ path: ["includeModel"],
18
26
  });
19
27
  const optionsParsed = optionsSchema.safeParse(options ?? {});
20
28
  if (!optionsParsed.success) {
21
29
  const firstIssue = optionsParsed.error.issues[0];
22
30
  const path = firstIssue?.path.length ? firstIssue.path.join(".") : "options";
23
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) ${path}: ${firstIssue?.message}`);
31
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) ${path}: ${firstIssue?.message}`, "67542");
24
32
  }
25
33
  return optionsParsed.data;
26
34
  }
@@ -14,23 +14,23 @@ function validateObjWithRelations(instance, obj, relationsKeys) {
14
14
  const relation = relations[key];
15
15
  if (relation.mode === "mtm" || relation.mode === "otm") {
16
16
  if (obj[key] === null) {
17
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' cannot be 'null' when relation mode is "mtm" or "otm", use an empty array instead.`);
17
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' cannot be 'null' when relation mode is "mtm" or "otm", use an empty array instead.`, "91868");
18
18
  }
19
19
  else if (!Array.isArray(obj[key]) || obj[key].some(val => !(0, is_object_validate_1.isObject)(val))) {
20
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' must be a valid array of objects when relation mode is "mtm" or "otm".`);
20
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' must be a valid array of objects when relation mode is "mtm" or "otm".`, "91868");
21
21
  }
22
22
  }
23
23
  else {
24
24
  if (obj[key] === null) {
25
25
  if (relation.mode === "oto" && relation.restriction !== "set") {
26
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' can be 'null' only if the relation restriction is "set" and mode is "oto".`);
26
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' can be 'null' only if the relation restriction is "set" and mode is "oto".`, "91868");
27
27
  }
28
28
  else if (relation.mode === "mto" && !relation.nullable && !relation.nullAble) {
29
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' can be 'null' only if the relation 'nullable' is 'true' and mode is "mto".`);
29
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' can be 'null' only if the relation 'nullable' is 'true' and mode is "mto".`, "91868");
30
30
  }
31
31
  }
32
32
  else if (!(0, is_object_validate_1.isObject)(obj[key])) {
33
- throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' must be a valid object when relation mode is "oto" or "mto".`);
33
+ throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) '${key}' must be a valid object when relation mode is "oto" or "mto".`, "91868");
34
34
  }
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vsrepo",
3
- "version": "1.2.8",
3
+ "version": "1.3.0",
4
4
  "description": "Uma biblioteca de repository pattern para Prisma",
5
5
  "homepage": "https://github.com/jaobrabo123/VSRepository#readme",
6
6
  "repository": {