vsrepo 1.3.5 → 1.3.7

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 (28) hide show
  1. package/README.md +147 -137
  2. package/README.pt-BR.md +154 -144
  3. package/dist/DynamicRepository.d.ts +24 -7
  4. package/dist/VSRepoError.d.ts +21 -1
  5. package/dist/VSRepository.d.ts +36 -12
  6. package/dist/VSRepository.js +49 -49
  7. package/dist/internal/constants/dynamic-methods-key.constant.js +4 -0
  8. package/dist/internal/decorators/dynamic-method.decorator.js +4 -4
  9. package/dist/internal/decorators/query-method.decorator.js +3 -3
  10. package/dist/internal/entities/dynamic-method-metadata.entity.js +3 -3
  11. package/dist/internal/resolvers/base-methods.resolve.js +2 -2
  12. package/dist/internal/resolvers/dbAndPrismaArgs.resolve.js +4 -4
  13. package/dist/internal/resolvers/dynamic-method-customization.resolve.js +57 -0
  14. package/dist/internal/resolvers/dynamic-method-info.resolve.js +279 -0
  15. package/dist/internal/resolvers/dynamic-methods-metadata.resolve.js +2 -2
  16. package/dist/internal/resolvers/pretty-wheres.resolve.js +8 -8
  17. package/dist/internal/resolvers/types/dynamic-method-where-ops.type.js +2 -0
  18. package/dist/internal/utils/schemas.util.js +8 -2
  19. package/dist/internal/validation/constructor-config.validate.js +7 -4
  20. package/package.json +1 -1
  21. package/scripts/configure-prisma-import.mjs +23 -10
  22. package/scripts/copy-types.mjs +16 -16
  23. package/dist/internal/constants/dinamic-methods-key.constant.js +0 -4
  24. package/dist/internal/resolvers/dinamic-method-customization.resolve.js +0 -57
  25. package/dist/internal/resolvers/dinamic-method-info.resolve.js +0 -279
  26. /package/dist/internal/{resolvers/types/dinamic-method-customization.type.js → errors/types/vs-repo-runtime-error-code.type.js} +0 -0
  27. /package/dist/internal/resolvers/types/{dinamic-method-info.type.js → dynamic-method-customization.type.js} +0 -0
  28. /package/dist/internal/resolvers/types/{dinamic-method-where-ops.type.js → dynamic-method-info.type.js} +0 -0
package/README.pt-BR.md CHANGED
@@ -39,7 +39,7 @@ O VSRepository permite criar repositórios fortemente tipados com:
39
39
  - [Include Models](#include-models)
40
40
  - [Include bruto (options.include)](#include-bruto-optionsinclude)
41
41
  - [Required Where](#required-where)
42
- - [Ordenação padrão (Default Ordenation)](#ordenação-padrão-default-ordenation)
42
+ - [Ordenação padrão (Default Ordering)](#ordenação-padrão-default-ordering)
43
43
  - [Opção `see`](#opção-see)
44
44
  - [Métodos dinâmicos](#métodos-dinâmicos)
45
45
  - [Prefixos disponíveis](#prefixos-disponíveis)
@@ -96,14 +96,14 @@ npx vsrepo generate \
96
96
 
97
97
  **Flags disponíveis:**
98
98
 
99
- | Flag | Atalho | Padrão |
99
+ | Flag | Atalho | Padrão |
100
100
  | ---------- | ------ | -------------------- |
101
101
  | `--output` | `-o` | `generated/vsrepo` |
102
102
  | `--prisma` | `-p` | `generated/prisma` |
103
103
 
104
104
  **Arquivos gerados:**
105
105
 
106
- ```
106
+ ```text
107
107
  generated/vsrepo/
108
108
  ├── DynamicRepository.ts
109
109
  ├── DynamicRepository.types.d.ts
@@ -334,18 +334,18 @@ export class UserService {
334
334
 
335
335
  Ao chamar `.build(prisma)`, os métodos base abaixo ficam automaticamente disponíveis:
336
336
 
337
- | Método | Descrição |
338
- | -------------------------- | -------------------------------------------------------------------------------------------------------------|
339
- | `get(pk)` | Busca um registro pela sua chave primária |
337
+ | Método | Descrição |
338
+ | ------------------------- | -------------------------------------------------------------------------------------------------------------- |
339
+ | `get(pk)` | Busca um registro pela sua chave primária |
340
340
  | `getOrThrow(pk)` | Busca um registro pela sua chave primária; lança `VSRepoRuntimeError` (código `"20727"`) se não for encontrado |
341
341
  | `getList(pks)` | Busca múltiplos registros a partir de uma lista de chaves primárias |
342
342
  | `save(obj)` | Cria ou atualiza — se o objeto tiver uma `pk`, realiza um `upsert`; caso contrário, um `create` |
343
343
  | `saveList(objs)` | Salva um array de objetos em uma única transação automática |
344
344
  | `patch(pk, obj)` | Atualiza parcialmente um registro pela sua chave primária |
345
- | `patchList(tuples)` | Atualiza parcialmente múltiplos registros via um array de tuplas `[pk, obj]` em uma transação automática |
345
+ | `patchList(tuples)` | Atualiza parcialmente múltiplos registros via um array de tuplas `[pk, obj]` em uma transação automática |
346
346
  | `merge(pk, obj)` | Busca um registro e faz um deep merge em memória — **não persiste**, retorna o objeto mesclado |
347
347
  | `remove(pk)` | Remove um registro pela sua chave primária |
348
- | `removeList(pks)` | Remove vários registros a partir de uma lista de chaves primárias — retorna `{ count }` |
348
+ | `removeList(pks)` | Remove vários registros a partir de uma lista de chaves primárias — retorna `{ count }` |
349
349
  | `getAll()` | Retorna todos os registros (aceita `pagination` e `order` em `options`) |
350
350
  | `total()` | Retorna o número total de registros |
351
351
  | `has(pk)` | Verifica se um registro existe pela sua chave primária — retorna `boolean` |
@@ -356,12 +356,12 @@ Todos eles aceitam `options` como último argumento.
356
356
 
357
357
  Quando `softRemovekName` está configurado no repositório, os métodos adicionais abaixo ficam disponíveis:
358
358
 
359
- | Método | Descrição |
360
- | ---------------------------- | ---------------------------------------------------------------------------------------|
361
- | `softRemove(pk)` | Marca um registro como removido, preenchendo `softRemovekName` com a data atual |
362
- | `softRemoveList(pks)` | Marca múltiplos registros como removidos em lote — retorna `{ count }` |
363
- | `restore(pk)` | Restaura um registro com soft-delete, limpando o campo `softRemovekName` |
364
- | `restoreList(pks)` | Restaura múltiplos registros com soft-delete em lote — retorna `{ count }` |
359
+ | Método | Descrição |
360
+ | --------------------------- | ---------------------------------------------------------------------------------- |
361
+ | `softRemove(pk)` | Marca um registro como removido, preenchendo `softRemovekName` com a data atual |
362
+ | `softRemoveList(pks)` | Marca múltiplos registros como removidos em lote — retorna `{ count }` |
363
+ | `restore(pk)` | Restaura um registro com soft-delete, limpando o campo `softRemovekName` |
364
+ | `restoreList(pks)` | Restaura múltiplos registros com soft-delete em lote — retorna `{ count }` |
365
365
 
366
366
  ```ts
367
367
  const userRepository = setupVSRepo<User, "user">()(({
@@ -661,15 +661,15 @@ const user = await userRepository.findByEmail("john@email.com");
661
661
 
662
662
  ---
663
663
 
664
- ## Ordenação padrão (Default Ordenation)
664
+ ## Ordenação padrão (Default Ordering)
665
665
 
666
- `defaultOrdenation` define uma ordenação padrão que é aplicada automaticamente em toda query que aceita `orderBy`, sem precisar repetir o argumento `order` em cada chamada.
666
+ `defaultOrdering` define uma ordenação padrão que é aplicada automaticamente em toda query que aceita `orderBy`, sem precisar repetir o argumento `order` em cada chamada.
667
667
 
668
668
  ```ts
669
669
  const userRepository = setupVSRepo<User, "user">()(({
670
670
  tableName: "user",
671
671
  pkName: "id",
672
- defaultOrdenation: { createdAt: "desc" },
672
+ defaultOrdering: { createdAt: "desc" },
673
673
  }).build(prisma);
674
674
  ```
675
675
 
@@ -683,23 +683,23 @@ const users = await userRepository.getAll();
683
683
  const paginated = await userRepository.getAll({ pagination: { take: 10 } });
684
684
  ```
685
685
 
686
- **`defaultOrdenation` é ignorado quando:**
686
+ **`defaultOrdering` é ignorado quando:**
687
687
 
688
688
  - O método usa o sufixo `Ordered`, `OrderedAndPaginated` ou `PaginatedAndOrdered` — nesses casos, o argumento `order` passado na chamada tem prioridade.
689
- - O método dinâmico tem `injectOrdenation` configurado — a ordenação fixa do método tem precedência.
689
+ - O método dinâmico tem `injectOrdering` configurado — a ordenação fixa do método tem precedência.
690
690
 
691
691
  ```ts
692
692
  methods: {
693
- findManyPaginatedAndOrdered: { map: true }, // order vem do argumento → defaultOrdenation ignorado
694
- findManyByActive: { map: true }, // sem Ordered → defaultOrdenation aplicado
693
+ findManyPaginatedAndOrdered: { map: true }, // order vem do argumento → defaultOrdering ignorado
694
+ findManyByActive: { map: true }, // sem Ordered → defaultOrdering aplicado
695
695
  findManyByStatus: {
696
696
  map: true,
697
- injectOrdenation: { name: "asc" }, // injectOrdenation → defaultOrdenation ignorado
697
+ injectOrdering: { name: "asc" }, // injectOrdering → defaultOrdering ignorado
698
698
  },
699
699
  }
700
700
  ```
701
701
 
702
- > `defaultOrdenation` aceita o mesmo tipo do `orderBy` nativo do Prisma para o modelo — incluindo arrays de ordenações encadeadas.
702
+ > `defaultOrdering` aceita o mesmo tipo do `orderBy` nativo do Prisma para o modelo — incluindo arrays de ordenações encadeadas.
703
703
 
704
704
  ---
705
705
 
@@ -708,10 +708,10 @@ methods: {
708
708
  Quando `softRemovekName` está configurado, todo método aceita a opção `see` para controlar a visibilidade de registros com soft-delete:
709
709
 
710
710
  | Valor | Comportamento |
711
- | ----------- | -----------------------------------------------------------------|
712
- | `"active"` | Retorna apenas registros que **não** foram removidos (padrão) |
713
- | `"removed"` | Retorna apenas registros removidos |
714
- | `"all"` | Retorna todos os registros, independente do status |
711
+ | ----------- | -------------------------------------------------------------- |
712
+ | `"active"` | Retorna apenas registros que **não** foram removidos (padrão) |
713
+ | `"removed"` | Retorna apenas registros removidos |
714
+ | `"all"` | Retorna todos os registros, independente do status |
715
715
 
716
716
  ```ts
717
717
  // Retorna apenas usuários ativos (padrão)
@@ -747,39 +747,39 @@ methods: {
747
747
 
748
748
  O prefixo do nome do método determina qual operação do Prisma será chamada e quais argumentos são esperados.
749
749
 
750
- | Prefixo | Operação do Prisma | Retorno | Observações |
751
- | ---------------------------- | ---------------------------- | ------------------------ | -----------------------------------------------------------------------------|
752
- | `findOneBy` | `findFirst` | `T \| null` | Retorno único. |
753
- | `findBy` | `findMany` / `findFirst` | `T[]` ou `T \| null` | Padrão é lista; use `fbMode: "one"` para retorno único (**deprecated**, use `findOneBy`) |
754
- | `findUniqueBy` | `findUnique` | `T \| null` | |
755
- | `findUniqueOrThrowBy` | `findUniqueOrThrow` | `T` | Lança um erro se não encontrado |
756
- | `findFirstBy` | `findFirst` | `T \| null` | Aceita campos como filtro |
757
- | `findFirstOrThrowBy` | `findFirstOrThrow` | `T` | Aceita campos como filtro; lança um erro se não encontrado |
758
- | `findFirst` | `findFirst` | `T \| null` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
759
- | `findFirstOrThrow` | `findFirstOrThrow` | `T` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere`; lança um erro se não encontrado |
760
- | `findManyBy` | `findMany` | `T[]` | Aceita campos como filtro |
761
- | `findMany` | `findMany` | `T[]` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
762
- | `findOneWhere` | `findFirst` | `T \| null` | Recebe um objeto `where` explícito como argumento |
763
- | `findListWhere` | `findMany` | `T[]` | Recebe um objeto `where` explícito como argumento |
764
- | `existsBy` | `findFirst` | `boolean` | Retorna `true` se encontrado, `false` caso contrário |
765
- | `existsWhere` | `findFirst` | `boolean` | Recebe um objeto `where` explícito e retorna se existe |
766
- | `countBy` | `count` | `number` | Aceita campos como filtro |
767
- | `countWhere` | `count` | `number` | Recebe um objeto `where` explícito como argumento |
768
- | `count` | `count` | `number` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
769
- | `create` | `create` | `T` | Recebe `data` como argumento |
770
- | `createMany` | `createMany` | `{ count: number }` | Recebe `data` como argumento; suporta `SkipDuplicates` |
771
- | `createManyAndReturn` | `createManyAndReturn` | `T[]` | Recebe `data` como argumento; suporta `SkipDuplicates` |
772
- | `updateBy` | `update` | `T` | Recebe `data` como argumento |
773
- | `updateManyBy` | `updateMany` | `{ count: number }` | Recebe `data` como argumento |
774
- | `updateManyWhere` | `updateMany` | `{ count: number }` | Recebe um objeto `where` e um objeto `data` como argumentos |
775
- | `updateManyAndReturnBy` | `updateManyAndReturn` | `T[]` | Recebe `data` como argumento |
776
- | `updateManyAndReturnWhere` | `updateManyAndReturn` | `T[]` | Recebe um objeto `where` e um objeto `data` como argumentos |
777
- | `upsertBy` | `upsert` | `T` | Recebe `update` e `create` como argumentos |
778
- | `deleteBy` | `delete` | `T` | |
779
- | `deleteManyBy` | `deleteMany` | `{ count: number }` | |
780
- | `deleteManyWhere` | `deleteMany` | `{ count: number }` | Recebe um objeto `where` explícito como argumento |
781
- | `aggregate` | `aggregate` | `Dynamic` | O nome deve ser exato; recebe argumentos nativos do Prisma; ignora `selectModels`, `pushWhere` e `requiredWhere` |
782
- | `groupBy` | `groupBy` | `Dynamic[]` | O nome deve ser exato; recebe argumentos nativos do Prisma; ignora `selectModels`, `pushWhere` e `requiredWhere` |
750
+ | Prefixo | Operação do Prisma | Retorno | Observações |
751
+ | ---------------------------- | --------------------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------- |
752
+ | `findOneBy` | `findFirst` | `T \| null` | Retorno único. |
753
+ | `findBy` | `findMany` / `findFirst` | `T[]` ou `T \| null` | Padrão é lista; use `fbMode: "one"` para retorno único (**deprecated**, use `findOneBy`) |
754
+ | `findUniqueBy` | `findUnique` | `T \| null` | |
755
+ | `findUniqueOrThrowBy` | `findUniqueOrThrow` | `T` | Lança um erro se não encontrado |
756
+ | `findFirstBy` | `findFirst` | `T \| null` | Aceita campos como filtro |
757
+ | `findFirstOrThrowBy` | `findFirstOrThrow` | `T` | Aceita campos como filtro; lança um erro se não encontrado |
758
+ | `findFirst` | `findFirst` | `T \| null` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
759
+ | `findFirstOrThrow` | `findFirstOrThrow` | `T` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere`; lança um erro se não encontrado |
760
+ | `findManyBy` | `findMany` | `T[]` | Aceita campos como filtro |
761
+ | `findMany` | `findMany` | `T[]` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
762
+ | `findOneWhere` | `findFirst` | `T \| null` | Recebe um objeto `where` explícito como argumento |
763
+ | `findListWhere` | `findMany` | `T[]` | Recebe um objeto `where` explícito como argumento |
764
+ | `existsBy` | `findFirst` | `boolean` | Retorna `true` se encontrado, `false` caso contrário |
765
+ | `existsWhere` | `findFirst` | `boolean` | Recebe um objeto `where` explícito e retorna se existe |
766
+ | `countBy` | `count` | `number` | Aceita campos como filtro |
767
+ | `countWhere` | `count` | `number` | Recebe um objeto `where` explícito como argumento |
768
+ | `count` | `count` | `number` | Sem filtros de campo; aplica apenas `requiredWhere` e `pushWhere` |
769
+ | `create` | `create` | `T` | Recebe `data` como argumento |
770
+ | `createMany` | `createMany` | `{ count: number }` | Recebe `data` como argumento; suporta `SkipDuplicates` |
771
+ | `createManyAndReturn` | `createManyAndReturn` | `T[]` | Recebe `data` como argumento; suporta `SkipDuplicates` |
772
+ | `updateBy` | `update` | `T` | Recebe `data` como argumento |
773
+ | `updateManyBy` | `updateMany` | `{ count: number }` | Recebe `data` como argumento |
774
+ | `updateManyWhere` | `updateMany` | `{ count: number }` | Recebe um objeto `where` e um objeto `data` como argumentos |
775
+ | `updateManyAndReturnBy` | `updateManyAndReturn` | `T[]` | Recebe `data` como argumento |
776
+ | `updateManyAndReturnWhere` | `updateManyAndReturn` | `T[]` | Recebe um objeto `where` e um objeto `data` como argumentos |
777
+ | `upsertBy` | `upsert` | `T` | Recebe `update` e `create` como argumentos |
778
+ | `deleteBy` | `delete` | `T` | |
779
+ | `deleteManyBy` | `deleteMany` | `{ count: number }` | |
780
+ | `deleteManyWhere` | `deleteMany` | `{ count: number }` | Recebe um objeto `where` explícito como argumento |
781
+ | `aggregate` | `aggregate` | `Dynamic` | O nome deve ser exato; recebe argumentos nativos do Prisma; ignora `selectModels`, `pushWhere` e `requiredWhere` |
782
+ | `groupBy` | `groupBy` | `Dynamic[]` | O nome deve ser exato; recebe argumentos nativos do Prisma; ignora `selectModels`, `pushWhere` e `requiredWhere` |
783
783
 
784
784
  ---
785
785
 
@@ -788,28 +788,28 @@ O prefixo do nome do método determina qual operação do Prisma será chamada e
788
788
  Filtros são sufixos aplicados ao nome do campo dentro do método. O próprio campo vem capitalizado logo após o prefixo (ou após `By`).
789
789
 
790
790
  | Sufixo | Operador Prisma | Argumento obrigatório |
791
- | ---------------------- | ----------------------- | -----------------------------|
792
- | *(sem sufixo)* | igualdade (`=`) | sim |
793
- | `Not` | `not` | sim |
794
- | `In` | `in` | sim (array) |
795
- | `NotIn` | `notIn` | sim (array) |
796
- | `Contains` | `contains` | sim |
797
- | `NotContains` | `not.contains` | sim |
798
- | `StartsWith` | `startsWith` | sim |
799
- | `NotStartsWith` | `not.startsWith` | sim |
800
- | `EndsWith` | `endsWith` | sim |
801
- | `NotEndsWith` | `not.endsWith` | sim |
802
- | `GreaterThan` | `gt` | sim |
803
- | `GreaterThanEqual` | `gte` | sim |
804
- | `LessThan` | `lt` | sim |
805
- | `LessThanEqual` | `lte` | sim |
806
- | `Between` | `gte` + `lte` | sim (tupla `[min, max]`) |
807
- | `NotBetween` | `not.gte` + `not.lte` | sim (tupla `[min, max]`) |
808
- | `IsNull` | `null` | não |
809
- | `IsNotNull` | `not: null` | não |
810
- | `IsTrue` | `true` | não |
811
- | `IsFalse` | `false` | não |
812
- | `Insensitive` | `mode: 'insensitive'` | combinador |
791
+ | --------------------- | ---------------------- | --------------------------- |
792
+ | *(sem sufixo)* | igualdade (`=`) | sim |
793
+ | `Not` | `not` | sim |
794
+ | `In` | `in` | sim (array) |
795
+ | `NotIn` | `notIn` | sim (array) |
796
+ | `Contains` | `contains` | sim |
797
+ | `NotContains` | `not.contains` | sim |
798
+ | `StartsWith` | `startsWith` | sim |
799
+ | `NotStartsWith` | `not.startsWith` | sim |
800
+ | `EndsWith` | `endsWith` | sim |
801
+ | `NotEndsWith` | `not.endsWith` | sim |
802
+ | `GreaterThan` | `gt` | sim |
803
+ | `GreaterThanEqual` | `gte` | sim |
804
+ | `LessThan` | `lt` | sim |
805
+ | `LessThanEqual` | `lte` | sim |
806
+ | `Between` | `gte` + `lte` | sim (tupla `[min, max]`) |
807
+ | `NotBetween` | `not.gte` + `not.lte` | sim (tupla `[min, max]`) |
808
+ | `IsNull` | `null` | não |
809
+ | `IsNotNull` | `not: null` | não |
810
+ | `IsTrue` | `true` | não |
811
+ | `IsFalse` | `false` | não |
812
+ | `Insensitive` | `mode: 'insensitive'` | combinador |
813
813
 
814
814
  `Insensitive` é um combinador e pode ser usado junto com outro filtro de texto:
815
815
 
@@ -844,10 +844,10 @@ findByNameOptionalAndEmail // name é opcional, email é obrigatório
844
844
  ### Operadores lógicos
845
845
 
846
846
  | Operador | Uso no nome | Exemplo |
847
- | --------- | ---------------------------------- | -------------------------------------|
848
- | `And` | entre dois campos | `findOneByIdAndEmail` |
849
- | `Or` | entre dois campos | `findByNameOrEmail` |
850
- | `AND` | separa um bloco final de `AND` | `findByEmailOrNameANDActiveStatus` |
847
+ | --------- | -------------------------------- | ---------------------------------- |
848
+ | `And` | entre dois campos | `findOneByIdAndEmail` |
849
+ | `Or` | entre dois campos | `findByNameOrEmail` |
850
+ | `AND` | separa um bloco final de `AND` | `findByEmailOrNameANDActiveStatus` |
851
851
 
852
852
  `AND` (em maiúsculas) tem uma regra específica:
853
853
 
@@ -927,22 +927,23 @@ Gera (`findByEmailOrNameANDActiveStatusAndAgeGreaterThan`):
927
927
  Permitem filtrar por campos de modelos relacionados.
928
928
 
929
929
  > [!IMPORTANT]
930
+ >
930
931
  > - **Tipagem de relação**: Para que o TypeScript reconheça os tipos dos campos de relação nos métodos dinâmicos, o tipo genérico da entidade passado para `setupVSRepo` deve incluir as relações estruturadas (ex.: usando o `UserGetPayload<{ include: { profile: true, posts: true } }>` do Prisma).
931
932
  > - **Compatibilidade de sufixos**:
932
933
  > - Os sufixos `Some`, `Every` e `None` só funcionam em relações **to-many** (`many-to-many` e `one-to-many`).
933
934
  > - Os sufixos `With` e `Without` só funcionam em relações **to-one** (`one-to-one` e `many-to-one`).
934
935
 
935
- | Sufixo de relação | Operador Prisma | Observação |
936
- | -------------------------- | ----------------- | ---------------------------------------------------------|
937
- | `Some` | `some: {}` | A relação tem *algum* registro |
938
- | `SomeField` | `some.field` | Filtra dentro dos registros da relação |
939
- | `EveryField` | `every.field` | Filtra dentro dos registros da relação |
940
- | `None` | `none: {}` | A relação não tem *nenhum* registro |
941
- | `NoneField` | `none.field` | Filtra dentro dos registros da relação |
942
- | `With` | `is: {}` | A relação existe (não é nula) |
943
- | `WithField` | `is.field` | Filtra um campo dentro da relação |
944
- | `Without` | `isNot: {}` | A relação não existe (é nula) |
945
- | `WithoutField` | `isNot.field` | Filtra um campo dentro da relação com negação |
936
+ | Sufixo de relação | Operador Prisma | Observação |
937
+ | ---------------------- | ---------------- | ------------------------------------------------- |
938
+ | `Some` | `some: {}` | A relação tem *algum* registro |
939
+ | `SomeField` | `some.field` | Filtra dentro dos registros da relação |
940
+ | `EveryField` | `every.field` | Filtra dentro dos registros da relação |
941
+ | `None` | `none: {}` | A relação não tem *nenhum* registro |
942
+ | `NoneField` | `none.field` | Filtra dentro dos registros da relação |
943
+ | `With` | `is: {}` | A relação existe (não é nula) |
944
+ | `WithField` | `is.field` | Filtra um campo dentro da relação |
945
+ | `Without` | `isNot: {}` | A relação não existe (é nula) |
946
+ | `WithoutField` | `isNot.field` | Filtra um campo dentro da relação com negação |
946
947
 
947
948
  Considerando `user` com uma relação to-one `profile` e uma relação to-many `posts`:
948
949
 
@@ -1022,18 +1023,18 @@ Gera (`findByProfileWithout`):
1022
1023
 
1023
1024
  Aplicados no **final** do nome do método, injetam automaticamente os argumentos de paginação e ordenação.
1024
1025
 
1025
- | Sufixo | Argumentos adicionais |
1026
- | -------------------------- | ----------------------------------|
1027
- | `Paginated` | `(pagination)` |
1028
- | `Ordered` | `(order)` |
1029
- | `OrderedAndPaginated` | `(order, pagination)` |
1030
- | `PaginatedAndOrdered` | `(pagination, order)` |
1026
+ | Sufixo | Argumentos adicionais |
1027
+ | ------------------------ | ---------------------------- |
1028
+ | `Paginated` | `(pagination)` |
1029
+ | `Ordered` | `(order)` |
1030
+ | `OrderedAndPaginated` | `(order, pagination)` |
1031
+ | `PaginatedAndOrdered` | `(pagination, order)` |
1031
1032
 
1032
1033
  Para `createMany` e `createManyAndReturn`, o sufixo `SkipDuplicates` está disponível:
1033
1034
 
1034
- | Sufixo | Efeito |
1035
- | --------------------- | -----------------------------------------------|
1036
- | `SkipDuplicates` | Ignora registros duplicados durante a inserção |
1035
+ | Sufixo | Efeito |
1036
+ | ---------------------| ---------------------------------------------- |
1037
+ | `SkipDuplicates` | Ignora registros duplicados durante a inserção |
1037
1038
 
1038
1039
  ---
1039
1040
 
@@ -1077,17 +1078,17 @@ await userRepository.findManyByNameDistinctRole("John");
1077
1078
 
1078
1079
  Cada entrada em `methods` aceita as seguintes opções:
1079
1080
 
1080
- | Opção | Tipo | Padrão | Descrição |
1081
- | ---------------------- | ----------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------|
1082
- | `map` | `boolean` | — | **Obrigatório.** Define se o método será exposto no repositório. |
1083
- | `whereType` | `'extending'` \| `'overwrite'` | `extending` | `extending` combina com `requiredWhere`. `overwrite` ignora `requiredWhere`. |
1084
- | `selectModel` | `keyof SelectModels \| false` | — | Sobrescreve o `defaultSelectModel` para este método. |
1085
- | `fbMode` | `'one'` \| `'list'` | `'list'` | (**Deprecated. Use `findOneBy`**) Apenas para `findBy`. `'one'` retorna `T \| null`; `'list'` retorna `T[]`. |
1086
- | `proxyTo` | `Padrão de método válido` | — | Delega a lógica para outro padrão de método válido. |
1087
- | `pushWhere` | `WhereModel<M>` | — | `where` extra adicionado à query além do `requiredWhere`. |
1088
- | `injectOrdenation` | `OrdenationModel<M>` | — | Ordenação fixa injetada automaticamente na query. |
1089
- | `injectPagination` | `PaginationModel<M>` | — | Paginação fixa injetada automaticamente na query. |
1090
- | `query` | `{ value: string; modifying?: boolean }` | — | Transforma o método em um **Query Method** (SQL bruto). Ignora todas as outras opções acima — veja [Query Methods](#query-methods). |
1081
+ | Opção | Tipo | Padrão | Descrição |
1082
+ | --------------------- | ---------------------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
1083
+ | `map` | `boolean` | — | **Obrigatório.** Define se o método será exposto no repositório. |
1084
+ | `whereType` | `'extending'` \| `'overwrite'` | `extending` | `extending` combina com `requiredWhere`. `overwrite` ignora `requiredWhere`. |
1085
+ | `selectModel` | `keyof SelectModels \| false` | — | Sobrescreve o `defaultSelectModel` para este método. |
1086
+ | `fbMode` | `'one'` \| `'list'` | `'list'` | (**Deprecated. Use `findOneBy`**) Apenas para `findBy`. `'one'` retorna `T \| null`; `'list'` retorna `T[]`. |
1087
+ | `proxyTo` | `Padrão de método válido` | — | Delega a lógica para outro padrão de método válido. |
1088
+ | `pushWhere` | `WhereModel<M>` | — | `where` extra adicionado à query além do `requiredWhere`. |
1089
+ | `injectOrdering` | `OrderingModel<M>` | — | Ordenação fixa injetada automaticamente na query. |
1090
+ | `injectPagination` | `PaginationModel<M>` | — | Paginação fixa injetada automaticamente na query. |
1091
+ | `query` | `{ value: string; modifying?: boolean }` | — | Transforma o método em um **Query Method** (SQL bruto). Ignora todas as outras opções acima — veja [Query Methods](#query-methods). |
1091
1092
 
1092
1093
  ---
1093
1094
 
@@ -1169,13 +1170,13 @@ await userRepository.prisma.$transaction(async (tx) => {
1169
1170
  });
1170
1171
  ```
1171
1172
 
1172
- | Opção | Tipo | Padrão | Descrição |
1173
- | ------------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
1174
- | `value` | `string` | — | **Obrigatório.** SQL bruto a ser executado. Use `$1`, `$2`, ... para os placeholders dos valores em `args`. |
1173
+ | Opção | Tipo | Padrão | Descrição |
1174
+ | ------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1175
+ | `value` | `string` | — | **Obrigatório.** SQL bruto a ser executado. Use `$1`, `$2`, ... para os placeholders dos valores em `args`. |
1175
1176
  | `modifying` | `boolean` | `false` | Quando `true`, executa via `$executeRawUnsafe` e o método sempre resolve para `number`. Quando `false`, executa via `$queryRawUnsafe` e o método resolve para `TReturn` (`any` por padrão, inferível via generic na chamada). |
1176
1177
 
1177
1178
  > [!NOTE]
1178
- > Diferente dos demais métodos dinâmicos, Query Methods **ignoram completamente** `selectModels`, `requiredWhere`, `pushWhere`, `whereType`, `injectOrdenation`, `injectPagination` e `proxyTo` — nada disso se aplica, já que não há parsing de nome nem montagem de `where`/`select` pelo VSRepository. Nomes de métodos livres (fora dos padrões de `findBy`, `updateBy`, etc.) também **não** exigem `proxyTo`.
1179
+ > Diferente dos demais métodos dinâmicos, Query Methods **ignoram completamente** `selectModels`, `requiredWhere`, `pushWhere`, `whereType`, `injectOrdering`, `injectPagination` e `proxyTo` — nada disso se aplica, já que não há parsing de nome nem montagem de `where`/`select` pelo VSRepository. Nomes de métodos livres (fora dos padrões de `findBy`, `updateBy`, etc.) também **não** exigem `proxyTo`.
1179
1180
 
1180
1181
  A mesma funcionalidade está disponível na abordagem baseada em classes através do decorator `@QueryMethod` — veja o [README-DynamicRepo.pt-BR.md](./README-DynamicRepo.pt-BR.md#o-decorator-querymethod).
1181
1182
 
@@ -1213,29 +1214,29 @@ const userRepository = setupVSRepo<User, "user">()(({
1213
1214
 
1214
1215
  **Modos de relação:**
1215
1216
 
1216
- | Modo | Relação |
1217
+ | Modo | Relação |
1217
1218
  | ----- | ------------------ |
1218
- | `oto` | um-para-um |
1219
- | `otm` | um-para-muitos |
1220
- | `mto` | muitos-para-um |
1221
- | `mtm` | muitos-para-muitos |
1219
+ | `oto` | um-para-um |
1220
+ | `otm` | um-para-muitos |
1221
+ | `mto` | muitos-para-um |
1222
+ | `mtm` | muitos-para-muitos |
1222
1223
 
1223
1224
  **Restrições:**
1224
1225
 
1225
- | Restrição | Comportamento na atualização |
1226
- | ------------ | -------------------------------------------------------------------|
1227
- | `set` | Substitui totalmente (remove os que não foram enviados) |
1228
- | `add` | Adiciona/atualiza sem remover os existentes |
1226
+ | Restrição | Comportamento na atualização |
1227
+ | ----------- | ----------------------------------------------------------- |
1228
+ | `set` | Substitui totalmente (remove os que não foram enviados) |
1229
+ | `add` | Adiciona/atualiza sem remover os existentes |
1229
1230
 
1230
1231
  > [!WARNING]
1231
1232
  > **`set` significa coisas diferentes dependendo do `mode` da relação — e isso pode causar perda de dados se você não tomar cuidado.**
1232
1233
  >
1233
1234
  > Em relações onde o registro relacionado **pertence** ao registro pai (`oto` e `otm`), "remover os que não foram enviados" significa **apagar o registro do banco de dados** (`delete`/`deleteMany`). Em relações onde o registro relacionado é **independente** (`mto` e `mtm`), "remover" significa apenas **desvincular** (`disconnect`/`set: []`) — o registro relacionado continua existindo no banco, apenas deixa de apontar para o pai (ou de estar na tabela de junção).
1234
1235
  >
1235
- > | Modo | `restriction: "set"` quando um item é omitido | O item continua existindo no banco de dados? |
1236
- > | ----- | ------------------------------------------------ | -----------------------------------------------------|
1236
+ > | Modo | `restriction: "set"` quando um item é omitido | O item continua existindo no banco de dados? |
1237
+ > | ----- | ------------------------------------------------ | ----------------------------------------------------- |
1237
1238
  > | `oto` | Passar `null` no campo → **apaga** o registro relacionado (`delete: true`) | Não |
1238
- > | `otm` | Itens fora da lista enviada → **apagados** (`deleteMany` com `notIn`) | Não |
1239
+ > | `otm` | Itens fora da lista enviada → **apagados** (`deleteMany` com `notIn`) | Não |
1239
1240
  > | `mto` | Passar `null` no campo (com `nullable: true`) → **desvincula** (`disconnect: true`) | Sim |
1240
1241
  > | `mtm` | Itens fora da lista enviada → **desvinculados** da tabela de junção (`set: []`) | Sim |
1241
1242
  >
@@ -1338,14 +1339,23 @@ try {
1338
1339
 
1339
1340
  **Subclasses disponíveis:**
1340
1341
 
1341
- | Classe | Quando é lançada |
1342
- | ------------------------ | ---------------------------------------------------------------------------|
1343
- | `VSRepoConfigError` | Configuração inválida em `setupVSRepo` |
1344
- | `VSRepoBuildError` | Nome de método, tipo de campo ou configuração inválida em `build` |
1345
- | `VSRepoExtendError` | Argumento inválido em `extend` |
1346
- | `VSRepoRuntimeError` | Erro em tempo de execução durante uma operação |
1342
+ | Classe | Quando é lançada |
1343
+ | ------------------------- | -------------------------------------------------------------------- |
1344
+ | `VSRepoConfigError` | Configuração inválida em `setupVSRepo` |
1345
+ | `VSRepoBuildError` | Nome de método, tipo de campo ou configuração inválida em `build` |
1346
+ | `VSRepoExtendError` | Argumento inválido em `extend` |
1347
+ | `VSRepoDecoratorError` | Argumento inválido passado para `@DynamicMethod` ou `@QueryMethod` |
1348
+ | `VSRepoRuntimeError` | Erro em tempo de execução durante uma operação |
1347
1349
 
1348
- `VSRepoRuntimeError` tem uma propriedade `code` para identificação programática. O código `"20727"`, por exemplo, é lançado por `getOrThrow` quando o registro não é encontrado.
1350
+ `VSRepoRuntimeError` tem uma propriedade `code: VSRepoRuntimeErrorCode` para identificação programática, sem precisar fazer parsing da mensagem (legível por humanos, e possivelmente localizada):
1351
+
1352
+ | Código | Significado |
1353
+ | ------ | ----------- |
1354
+ | `"65706"` | Um argumento obrigatório está ausente ou tem formato inválido — ex.: `pk` ausente, `pks`/`objs`/`tuples` que não são um array, ou `options`/`obj` que não são um objeto válido. |
1355
+ | `"20727"` | Nenhum registro foi encontrado para a primary key informada (`getOrThrow` ao buscar o registro base). |
1356
+ | `"67542"` | A validação (zod) de `options` de um método, ou de um argumento de `@QueryMethod`, falhou. |
1357
+ | `"91868"` | Uma relação passada em `save`/`patch`/`merge` tem formato inválido para o `mode`/`restriction` configurados (ex.: `null` numa relação `mtm`/`otm`, ou um array numa relação `oto`/`mto`). |
1358
+ | `"48670"` | Um método dinâmico (`config.methods`) foi chamado com menos argumentos posicionais do que os campos do `where` exigem. |
1349
1359
 
1350
1360
  ---
1351
1361
 
@@ -1378,7 +1388,7 @@ import type {
1378
1388
  IncludeModel,
1379
1389
  IncludeModels,
1380
1390
  WhereModel,
1381
- OrdenationModel,
1391
+ OrderingModel,
1382
1392
  PaginationModel,
1383
1393
  ModelUpsertInput,
1384
1394
  PrismaModelInputs,
@@ -1461,7 +1471,7 @@ setupVSRepo<TPayload, TTableName>()({
1461
1471
  defaultSelectModel?: keyof SM; // Select aplicado por padrão
1462
1472
  includeModels?: IncludeModels<M>; // Projeções de dados nomeadas (include) — sem padrão, apenas na chamada
1463
1473
  requiredWhere?: WhereModel<M>; // Filtros sempre aplicados
1464
- defaultOrdenation?: OrdenationModel<M>; // Ordenação padrão para queries sem Ordered/injectOrdenation
1474
+ defaultOrdering?: OrderingModel<M>; // Ordenação padrão para queries sem Ordered/injectOrdering
1465
1475
  relations?: RepositoryRelations<T>; // Configuração de relações
1466
1476
  methods?: Record<string, MethodConfig<M, SM>>; // Métodos dinâmicos
1467
1477
  });
@@ -1512,7 +1522,7 @@ repo.extend((repo) => ({
1512
1522
 
1513
1523
  Além deste README, o repositório tem uma pasta **[`examples/`](https://github.com/jaobrabo123/VSRepository/tree/main/examples)** com exemplos práticos, comentados e prontos para executar — é o melhor lugar para ver o VSRepository sendo usado em cenários reais.
1514
1524
 
1515
- ```
1525
+ ```text
1516
1526
  examples/
1517
1527
  ├── prisma.ts # Instância do PrismaClient usada pelos exemplos
1518
1528
  ├── repositories.ts # Configuração dos repositórios (User, Address, Product) com setupVSRepo
@@ -1583,7 +1593,7 @@ Para reportar problemas ou sugerir novas funcionalidades, abra uma **Issue**.
1583
1593
 
1584
1594
  **`softRemovekName` lança um 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.
1585
1595
 
1586
- **`defaultOrdenation` não está sendo aplicado** — Verifique se o método usa o sufixo `Ordered`, `OrderedAndPaginated` ou `PaginatedAndOrdered`, e se tem `injectOrdenation` configurado. Ambos têm prioridade sobre a ordenação padrão.
1596
+ **`defaultOrdering` não está sendo aplicado** — Verifique se o método usa o sufixo `Ordered`, `OrderedAndPaginated` ou `PaginatedAndOrdered`, e se tem `injectOrdering` configurado. Ambos têm prioridade sobre a ordenação padrão.
1587
1597
 
1588
1598
  **Sufixo `Distinct` não é reconhecido** — `Distinct` só é resolvido em prefixos de leitura (`findMany`, `findFirst`, `findBy`, `existsBy`, etc). Em métodos como `count`, `createMany`, `updateMany` ou `deleteMany` o sufixo é ignorado.
1589
1599
 
@@ -8,7 +8,7 @@ import {
8
8
  ExtractNestedUpdateInput,
9
9
  IncludeModel,
10
10
  ModelUpsertInput,
11
- OrdenationModel,
11
+ OrderingModel,
12
12
  PaginationModel,
13
13
  PaginationOptions,
14
14
  PrismaModelInputs,
@@ -224,12 +224,23 @@ export interface DynamicRepositoryConstructorConfig<T, U extends PrismaModelName
224
224
 
225
225
  /**
226
226
  * Default ordering automatically injected into all queries that accept `orderBy`,
227
- * unless the method already has `injectOrdenation` configured or uses the `Ordered` suffix.
227
+ * unless the method already has `injectOrdering` configured or uses the `Ordered` suffix.
228
228
  *
229
229
  * Useful for ensuring a consistent sort order across the repository without repeating
230
230
  * the `order` argument on every call.
231
231
  */
232
- defaultOrdenation?: OrdenationModel<U>;
232
+ defaultOrdering?: OrderingModel<U>;
233
+
234
+ /**
235
+ * Default ordering automatically injected into all queries that accept `orderBy`,
236
+ * unless the method already has `injectOrdering` configured or uses the `Ordered` suffix.
237
+ *
238
+ * Useful for ensuring a consistent sort order across the repository without repeating
239
+ * the `order` argument on every call.
240
+ *
241
+ * @deprecated Use `defaultOrdering` instead.
242
+ */
243
+ defaultOrdenation?: OrderingModel<U>;
233
244
 
234
245
  /**
235
246
  * Configures automatic relation management.
@@ -336,10 +347,10 @@ export declare abstract class DynamicRepository<
336
347
  pagination?: PaginationOptions;
337
348
  /**
338
349
  * Ordering to apply to the query.
339
- * When omitted and `defaultOrdenation` is configured on the repository,
350
+ * When omitted and `defaultOrdering` is configured on the repository,
340
351
  * the default ordering is applied automatically.
341
352
  */
342
- order?: OrdenationModel<UName>;
353
+ order?: OrderingModel<UName>;
343
354
  },
344
355
  ): Promise<TEntity[]>;
345
356
 
@@ -385,7 +396,13 @@ export type DynamicMethodConfig<M extends PrismaModelName = PrismaModelName> = {
385
396
  fbMode?: "one" | "list";
386
397
 
387
398
  /** Injects a fixed ordering automatically into the query. */
388
- injectOrdenation?: OrdenationModel<M>;
399
+ injectOrdering?: OrderingModel<M>;
400
+
401
+ /**
402
+ * Injects a fixed ordering automatically into the query.
403
+ * @deprecated Use `injectOrdering` instead.
404
+ */
405
+ injectOrdenation?: OrderingModel<M>;
389
406
 
390
407
  /** Injects a fixed pagination automatically into the query. */
391
408
  injectPagination?: PaginationModel<M>;
@@ -406,7 +423,7 @@ export type DynamicMethodConfig<M extends PrismaModelName = PrismaModelName> = {
406
423
  * `@DynamicMethod()`
407
424
  * declare findOneByEmail: (email: string) => Promise<User | null>;
408
425
  *
409
- * @DynamicMethod<"User">({ injectOrdenation: { createdAt: "desc" } })
426
+ * @DynamicMethod<"User">({ injectOrdering: { createdAt: "desc" } })
410
427
  * declare findByAge: (email: number) => Promise<User[]>;
411
428
  * }
412
429
  * ```