vsrepo 2.2.1 → 2.4.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 +147 -145
- package/README.pt-BR.md +183 -181
- package/dist/VSRepository.d.ts +3 -2
- package/dist/VSRepository.js +3 -2
- package/dist/VSRepository.js.map +1 -1
- package/dist/decorators/query-method.decorator.d.ts +7 -4
- package/dist/decorators/query-method.decorator.js +7 -4
- package/dist/decorators/query-method.decorator.js.map +1 -1
- package/dist/internal/enums/adapter-error-code.enum.d.ts +4 -0
- package/dist/internal/enums/adapter-error-code.enum.js +4 -0
- package/dist/internal/enums/adapter-error-code.enum.js.map +1 -1
- package/dist/internal/utils/vs-logger.util.d.ts +2 -2
- package/dist/internal/utils/vs-logger.util.js +7 -4
- package/dist/internal/utils/vs-logger.util.js.map +1 -1
- package/dist/internal/validators/vsrepo.validator.js +1 -1
- package/dist/internal/validators/vsrepo.validator.js.map +1 -1
- package/dist/types/utils/query-method-arg.type.d.ts +4 -2
- package/dist/types/vsrepo/vsrepo-options.type.d.ts +4 -1
- package/dist/types/vsrepo/vsrepo-query-options.type.d.ts +1 -1
- package/package.json +6 -2
package/README.pt-BR.md
CHANGED
|
@@ -13,16 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
🇧🇷 Você está lendo a versão em português. [🇺🇸 Read in English](./README.md)
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Biblioteca de repository pattern **agnóstica de ORM**, com suporte completo a **TypeScript** e **type inference** automático. O VSRepository v2 é uma reescrita da biblioteca [v1](https://github.com/jaobrabo123/VSRepository/tree/v1): em vez de falar diretamente com o Prisma, o núcleo agora delega toda operação a um **adapter** plugável, permitindo que a mesma API de repository funcione com Prisma, TypeORM ou qualquer outro ORM/banco que implemente o contrato de adapter.
|
|
16
|
+
Biblioteca de repository pattern **agnóstica de ORM**, com suporte completo a **TypeScript** e **type inference** automático. O VSRepository v2 é uma reescrita da biblioteca [v1](https://github.com/jaobrabo123/VSRepository/tree/v1): em vez de falar diretamente com o Prisma, o núcleo agora delega toda operação a um **adapter** plugável, permitindo que a mesma API de repository funcione com Prisma, Drizzle ou qualquer outro ORM/banco que implemente o contrato de adapter.
|
|
19
17
|
|
|
20
18
|
O VSRepository permite criar repositories fortemente tipados com:
|
|
21
19
|
|
|
22
20
|
- **Métodos base** automáticos: `get`, `getOrThrow`, `getList`, `save`, `saveList`, `remove`, `removeList`, `patch`, `merge`, `getAll`, `total`, `has`
|
|
23
21
|
- **Soft-delete nativo**: `softRemove`, `softRemoveList`, `restore`, `restoreList`
|
|
24
22
|
- **Métodos dinâmicos** inferidos a partir do nome de um campo `declare` via o decorador `@DynamicMethod`: `findByEmail`, `findManyByStatusPaginated`, `updateById`
|
|
25
|
-
- **Métodos de query SQL raw** através do
|
|
23
|
+
- **Métodos de query SQL raw** através do decorador `@QueryMethod`, ignorando totalmente o engine de parsing por nome
|
|
26
24
|
- **`select`/`relations`** ad-hoc em cada chamada — sem mais projeções nomeadas pré-declaradas
|
|
27
25
|
- **Type safety** em 100% das operações
|
|
28
26
|
- **Transações** nativas do ORM, compartilhadas entre repositories
|
|
@@ -71,20 +69,20 @@ Se você vem do código/docs da [v1](https://github.com/jaobrabo123/VSRepository
|
|
|
71
69
|
|
|
72
70
|
| Área | v1 | v2 |
|
|
73
71
|
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
74
|
-
| Acesso ao banco | Fala diretamente com o **Prisma**, embutido no pacote core | Fala com um **`VSRepoAdapter`**; o suporte a cada ORM é distribuído em pacotes separados (`@vsrepo/prisma7-adapter`, `@vsrepo/
|
|
72
|
+
| Acesso ao banco | Fala diretamente com o **Prisma**, embutido no pacote core | Fala com um **`VSRepoAdapter`**; o suporte a cada ORM é distribuído em pacotes separados (`@vsrepo/prisma7-adapter`, `@vsrepo/drizzle-adapter`, ...) em vez de vir embutido no pacote core `vsrepo` |
|
|
75
73
|
| Definindo um repository | `setupVSRepo<T, M>()({...}).build(prisma)` funcional, **ou** uma classe `DynamicRepository` | Uma única API **baseada em classes**: `extends VSRepository<Entity, PKType, OrmTypes>` |
|
|
76
74
|
| Métodos dinâmicos | Objeto de config `methods: { findByEmail: { map: true } }` | Decorador `@DynamicMethod()` em um campo `declare` |
|
|
77
75
|
| Projeções de dados | `selectModels` + `defaultSelectModel` nomeados e reutilizáveis | `select`/`relations` ad-hoc passados em cada chamada (sem modelos nomeados) |
|
|
78
76
|
| Eager loading | `include`/`includeModels` (específico do Prisma) | Option `relations` agnóstica de ORM |
|
|
79
|
-
| Filtros globais | `requiredWhere`
|
|
77
|
+
| Filtros globais | `requiredWhere` e `pushWhere` | **Removidos**; Agora aceita apenas `softRemoveKey` + `see: "active" \| "removed" \| "all"` |
|
|
80
78
|
| Sufixo de filtro case-insensitive | `Insensitive` | `IgnoreCase` |
|
|
81
79
|
| Ordenação inline no nome do método | Não suportado (`order` tinha que ser passado como argumento via `Ordered`/`Paginated`) | Cadeias `OrderBy<Campo>Asc`/`OrderBy<Campo>Desc` embutidas diretamente no nome do método |
|
|
82
80
|
| Tratamento de duplicatas no `createMany` | Sufixo `SkipDuplicates` | Sufixo `IgnoreConflicts` |
|
|
83
|
-
| `aggregate` / `groupBy` | Suportado (passthrough nativo do Prisma) | **
|
|
81
|
+
| `aggregate` / `groupBy` | Suportado (passthrough nativo do Prisma) | `groupBy` **não está planejado** para a v2. Um prefixo `aggregate` separado também dificilmente será implementado: as operações mais comuns já são cobertas por métodos base dedicados (`sum`, `average`, `min`, `max`, `increment`, `decrement`, `multiply`, `divide`) — veja [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação). Para qualquer coisa mais complexa, use `@QueryMethod`. |
|
|
84
82
|
| Tipos de erro | `VSRepoError` + subclasses (`VSRepoConfigError`, `VSRepoBuildError`, `VSRepoExtendError`, `VSRepoRuntimeError`) | Uma classe base `VSRepoError` com um campo `type: VSRepoErrorType` (`DECORATOR`, `RESOLVER`, `DYNAMIC`, `VALIDATOR`, `BASE`, `ADAPTER`), além de uma subclasse `VSRepoAdapterError` que carrega um `AdapterErrorCode` e o erro original do ORM |
|
|
85
83
|
| Log de debug | Boolean `showWorking: true` | `logLevel: VSLogLevel` (`DEBUG`/`INFO`/`WARN`/`ERROR`) + `logSlowThresholdMs` para avisos de queries lentas |
|
|
86
84
|
| CLI `vsrepo generate` (etapa de geração de tipos) | Obrigatória antes de usar | Não faz parte do núcleo da v2 — os tipos vêm diretamente das suas entidades/tipos do ORM |
|
|
87
|
-
| Extras de CRUD | `patchList`, `options.select`/`options.include` raw | `select`/`relations` já são o padrão (sempre "raw"); `patch`/`merge` mantêm a mesma semântica. **`patchList` foi removido** — para uma atualização parcial em lote, use um dynamic method `updateManyBy`/`updateManyWhere`
|
|
85
|
+
| Extras de CRUD | `patchList`, `options.select`/`options.include` raw | `select`/`relations` já são o padrão (sempre "raw"); `patch`/`merge` mantêm a mesma semântica. **`patchList` foi removido** — para uma atualização parcial em lote, use um dynamic method `updateManyBy`/`updateManyWhere` |
|
|
88
86
|
|
|
89
87
|
---
|
|
90
88
|
|
|
@@ -97,16 +95,16 @@ O VSRepository v2 é **agnóstico de ORM por design**. O pacote core (`vsrepo`)
|
|
|
97
95
|
- `@vsrepo/typeorm-adapter`
|
|
98
96
|
- `@vsrepo/drizzle-adapter`
|
|
99
97
|
|
|
100
|
-
O adapter do Prisma 7 já foi publicado no npm como `@vsrepo/prisma7-adapter
|
|
98
|
+
O adapter do Prisma 7 já foi publicado no npm como `@vsrepo/prisma7-adapter`. O adapter do Drizzle está disponível em versão **alpha** — instale com `npm i @vsrepo/drizzle-adapter@alpha`. Os adapters para outros ORMs estão **planejados**, mas ainda não foram publicados. Até que exista um pacote `@vsrepo/*-adapter` oficial para o seu ORM, você pode escrever o seu próprio para o seu projeto e, se quiser, publicá-lo e abrir um PR para ajudar a fazer o ecossistema crescer — contribuições nesse sentido são muito bem-vindas.
|
|
101
99
|
|
|
102
|
-
| Adapter
|
|
103
|
-
|
|
|
104
|
-
| Prisma 7 (`@vsrepo/prisma7-adapter`)
|
|
105
|
-
|
|
|
106
|
-
| Outros ORMs (Prisma 8,
|
|
107
|
-
| Adapters customizados
|
|
100
|
+
| Adapter | Status |
|
|
101
|
+
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
102
|
+
| Prisma 7 (`@vsrepo/prisma7-adapter`) | 🟢 **Lançado** — publicado no npm, implementa o contrato de `VSRepoAdapter` (CRUD, relations, transactions, `merge`, logging) com testes; veja o [`VSRepoPrisma7Adapter`](https://github.com/jaobrabo123/VSRepoPrisma7Adapter) para o código-fonte e docs. **Nota:** os métodos atômicos/de agregação (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — veja [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação)) foram adicionados ao contrato do `VSRepoAdapter` depois do último release desse adapter; confirme no changelog/versão dele se já implementam esses métodos antes de depender de `increment`/`sum`/etc. contra o Prisma 7. |
|
|
103
|
+
| Drizzle (`@vsrepo/drizzle-adapter`) | 🔵 **Alpha** — uma versão inicial já está disponível no npm; instale com `npm i @vsrepo/drizzle-adapter@alpha`. A API ainda pode mudar antes do release estável. Veja o repositório do [`DrizzleAdapter`](https://github.com/jaobrabo123/VSRepoDrizzleAdapter) para o estado atual e limitações conhecidas, e sinta-se à vontade para contribuir. |
|
|
104
|
+
| Outros ORMs (Prisma 8, TypeORM, etc.) | 🟡 **Planejados, ainda não publicados.** Nenhum pacote oficial existe ainda — por enquanto, escreva o seu próprio adapter (veja [Escrevendo seu próprio adapter](#escrevendo-seu-próprio-adapter)) e considere publicá-lo/contribuir de volta com o projeto. |
|
|
105
|
+
| Adapters customizados | 🟢 Totalmente suportados hoje — implemente você mesmo a classe abstrata [`VSRepoAdapter`](#escrevendo-seu-próprio-adapter) para qualquer ORM/banco que precisar, no seu próprio projeto ou pacote, seguindo o mesmo formato esperado dos `@vsrepo/*-adapter`. |
|
|
108
106
|
|
|
109
|
-
Resumindo: a classe de repository, os decoradores `@DynamicMethod`/`@QueryMethod`, o engine de parsing de nomes, o tratamento de erros e o logging já funcionam de ponta a ponta, e o suporte ao Prisma 7 agora é um adapter lançado e publicado. Adapters oficiais para os demais ORMs estão no roadmap e serão distribuídos como pacotes `@vsrepo/*-adapter` separados, e não como parte do pacote core `vsrepo` — mas você não precisa esperar por isso: escrever (e opcionalmente publicar) o seu próprio adapter enquanto isso é uma forma totalmente suportada de usar a v2 hoje e de contribuir de volta com o projeto.
|
|
107
|
+
Resumindo: a classe de repository, os decoradores `@DynamicMethod`/`@QueryMethod`, o engine de parsing de nomes, o tratamento de erros e o logging já funcionam de ponta a ponta, e o suporte ao Prisma 7 agora é um adapter lançado e publicado. O adapter do Drizzle está disponível em alpha. Adapters oficiais para os demais ORMs estão no roadmap e serão distribuídos como pacotes `@vsrepo/*-adapter` separados, e não como parte do pacote core `vsrepo` — mas você não precisa esperar por isso: escrever (e opcionalmente publicar) o seu próprio adapter enquanto isso é uma forma totalmente suportada de usar a v2 hoje e de contribuir de volta com o projeto.
|
|
110
108
|
|
|
111
109
|
---
|
|
112
110
|
|
|
@@ -172,6 +170,7 @@ export default new UserRepository();
|
|
|
172
170
|
> A API do core (`VSRepository`, `VSRepoAdapter`, `DynamicMethod`, `QueryMethod`, `VSRepoError`, enums e tipos) é importada do entry point único `vsrepo`. O adapter concreto vem de um pacote **separado** (`@vsrepo/*-adapter`). No Prisma 7, instale o [`@vsrepo/prisma7-adapter`](https://github.com/jaobrabo123/VSRepoPrisma7Adapter) já publicado (o construtor dele recebe um objeto de config — `tableName`, `pkName`, `relations`/`logLevel` opcionais — como no exemplo acima). Adapters oficiais para outros ORMs estão planejados, mas ainda não publicados; até lá, você pode implementar o contrato `VSRepoAdapter` você mesmo (veja [Escrevendo seu próprio adapter](#escrevendo-seu-próprio-adapter)) — e publicá-lo para ajudar o projeto é muito bem-vindo.
|
|
173
171
|
|
|
174
172
|
> **O terceiro generic (`OrmTypes`):** `VSRepository<Entity, PKType, OrmTypes>` aceita um terceiro type parameter opcional descrevendo os tipos de client/transaction do seu ORM, via `VSRepoOrmTypes` (`{ dbClient; dbTransaction }`). Ao fornecê-lo, `getDbClient()`, o callback de `transaction()` e a option `db` de todo método passam a ser tipados corretamente, em vez de `any`:
|
|
173
|
+
>
|
|
175
174
|
> ```typescript
|
|
176
175
|
> type PrismaOrmTypes = { dbClient: PrismaClient; dbTransaction: Prisma.TransactionClient };
|
|
177
176
|
>
|
|
@@ -179,6 +178,7 @@ export default new UserRepository();
|
|
|
179
178
|
> // getDbClient() agora retorna PrismaClient, e transaction(fn) tipa `tx` como Prisma.TransactionClient
|
|
180
179
|
> }
|
|
181
180
|
> ```
|
|
181
|
+
>
|
|
182
182
|
> Se omitido, o padrão é `VSRepoOrmTypes` (`dbClient`/`dbTransaction` como `any`).
|
|
183
183
|
|
|
184
184
|
### Usando o repository
|
|
@@ -206,14 +206,14 @@ await userRepository.remove(usuario.id);
|
|
|
206
206
|
|
|
207
207
|
`VSRepoOptions<T, K>`, passado para o `super(...)` dentro do construtor do seu repository:
|
|
208
208
|
|
|
209
|
-
| Option | Tipo
|
|
210
|
-
| -------------------- |
|
|
211
|
-
| `adapter` | `VSRepoAdapter<T>`
|
|
212
|
-
| `pkName` | `keyof T`
|
|
213
|
-
| `softRemoveKey` | `keyof T`
|
|
214
|
-
| `defaultOrdering` | `Ordering<T>`
|
|
215
|
-
| `logLevel` | `VSLogLevel`
|
|
216
|
-
| `logSlowThresholdMs` | `number`
|
|
209
|
+
| Option | Tipo | Descrição |
|
|
210
|
+
| -------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
211
|
+
| `adapter` | `VSRepoAdapter<T>` | **Obrigatório.** A instância do adapter que traduz as chamadas do repository em chamadas contra o ORM/banco por trás dele. |
|
|
212
|
+
| `pkName` | `keyof T` | **Obrigatório.** Nome do campo que representa a primary key da entidade. |
|
|
213
|
+
| `softRemoveKey` | `keyof T` | Opcional. Quando definido, habilita `softRemove`, `softRemoveList`, `restore` e `restoreList`. |
|
|
214
|
+
| `defaultOrdering` | `Ordering<T>` | Opcional. Ordenação padrão aplicada automaticamente em queries que aceitam `order`, a menos que seja sobrescrita em uma chamada específica. |
|
|
215
|
+
| `logLevel` | `VSLogLevel` | Opcional. Severidade mínima impressa pelo logger interno. Padrão: `VSLogLevel.WARN`. |
|
|
216
|
+
| `logSlowThresholdMs` | `number \| boolean` | Opcional. Duração (ms) acima da qual uma operação concluída é logada como `WARN`. Padrão: 300ms. Passe `false` para desabilitar completamente os avisos de operação lenta; passe `true` para usar explicitamente o threshold padrão de 300ms. |
|
|
217
217
|
|
|
218
218
|
---
|
|
219
219
|
|
|
@@ -221,31 +221,31 @@ await userRepository.remove(usuario.id);
|
|
|
221
221
|
|
|
222
222
|
Disponíveis automaticamente em toda subclasse de `VSRepository`:
|
|
223
223
|
|
|
224
|
-
| Método
|
|
225
|
-
|
|
|
226
|
-
| `get(pk, options?)`
|
|
227
|
-
| `getOrThrow(pk, options?)`
|
|
228
|
-
| `getList(pks, options?)`
|
|
229
|
-
| `getAll(options?)`
|
|
230
|
-
| `save(obj, options?)`
|
|
231
|
-
| `saveList(objs, options?)`
|
|
232
|
-
| `patch(pk, obj, options?)`
|
|
233
|
-
| `merge(pk, obj, options?)`
|
|
234
|
-
| `remove(pk, options?)`
|
|
235
|
-
| `removeList(pks, options?)`
|
|
236
|
-
| `total(options?)`
|
|
237
|
-
| `has(pk, options?)`
|
|
238
|
-
| `increment(pk, field, value, options?)` | Adiciona `value` a um campo numérico de forma atômica. Veja [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação).
|
|
239
|
-
| `decrement(pk, field, value, options?)` | Subtrai `value` de um campo numérico de forma atômica.
|
|
240
|
-
| `multiply(pk, field, value, options?)` | Multiplica um campo numérico por `value` de forma atômica.
|
|
241
|
-
| `divide(pk, field, value, options?)` | Divide um campo numérico por `value` de forma atômica.
|
|
242
|
-
| `sum(field, where?, options?)` | Soma um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater.
|
|
243
|
-
| `average(field, where?, options?)` | Média aritmética de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater.
|
|
244
|
-
| `min(field, where?, options?)` | Valor mínimo de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater.
|
|
245
|
-
| `max(field, where?, options?)` | Valor máximo de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater.
|
|
246
|
-
| `transaction(fn, options?)`
|
|
247
|
-
| `getDbClient()`
|
|
248
|
-
| `query<T>(query, options?)`
|
|
224
|
+
| Método | Descrição |
|
|
225
|
+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
226
|
+
| `get(pk, options?)` | Busca um registro pela primary key. |
|
|
227
|
+
| `getOrThrow(pk, options?)` | Busca um registro pela primary key, lançando erro se não encontrar. |
|
|
228
|
+
| `getList(pks, options?)` | Busca vários registros por uma lista de primary keys. |
|
|
229
|
+
| `getAll(options?)` | Busca todos os registros; aceita `pagination` e `order` em `options`. |
|
|
230
|
+
| `save(obj, options?)` | Cria ou atualiza (upsert) um único registro. |
|
|
231
|
+
| `saveList(objs, options?)` | Cria ou atualiza (upsert) vários registros em uma única chamada. |
|
|
232
|
+
| `patch(pk, obj, options?)` | Atualiza parcialmente um registro pela primary key. |
|
|
233
|
+
| `merge(pk, obj, options?)` | Busca um registro e o retorna mesclado (deep-merge), em memória, com o objeto informado — **não** persiste nada. |
|
|
234
|
+
| `remove(pk, options?)` | Remove um registro pela primary key. |
|
|
235
|
+
| `removeList(pks, options?)` | Remove vários registros pela primary key, retornando `{ count }`. |
|
|
236
|
+
| `total(options?)` | Retorna o total de registros. |
|
|
237
|
+
| `has(pk, options?)` | Verifica se um registro existe, retornando `boolean`. |
|
|
238
|
+
| `increment(pk, field, value, options?)` | Adiciona `value` a um campo numérico de forma atômica. Veja [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação). |
|
|
239
|
+
| `decrement(pk, field, value, options?)` | Subtrai `value` de um campo numérico de forma atômica. |
|
|
240
|
+
| `multiply(pk, field, value, options?)` | Multiplica um campo numérico por `value` de forma atômica. |
|
|
241
|
+
| `divide(pk, field, value, options?)` | Divide um campo numérico por `value` de forma atômica. |
|
|
242
|
+
| `sum(field, where?, options?)` | Soma um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater. |
|
|
243
|
+
| `average(field, where?, options?)` | Média aritmética de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater. |
|
|
244
|
+
| `min(field, where?, options?)` | Valor mínimo de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater. |
|
|
245
|
+
| `max(field, where?, options?)` | Valor máximo de um campo numérico em todos os registros que baterem no filtro; `null` se nenhum bater. |
|
|
246
|
+
| `transaction(fn, options?)` | Executa `fn` dentro de uma transação nativa do ORM. |
|
|
247
|
+
| `getDbClient()` | Retorna a instância do client do ORM. |
|
|
248
|
+
| `query<T>(query, options?)` | Executa uma instrução SQL raw diretamente contra o banco. Veja [Queries raw pontuais com `query()`](#queries-raw-pontuais-com-query). |
|
|
249
249
|
|
|
250
250
|
A maioria dos métodos acima aceita um objeto `MethodOptions<Entity, OrmTypes>` como último argumento (`select`, `relations`, `see`, `db`). Alguns — `total`, `has`, `removeList`, `sum`, `average`, `min`, `max`, e os métodos em lote de soft-delete (`softRemoveList`/`restoreList`) — não retornam/moldam uma `Entity`, então aceitam o tipo mais restrito `RestrictMethodOptions<Entity, OrmTypes>` (só `see`, `db`; sem `select`/`relations`). `transaction`, `query` e `getDbClient` recebem options próprias ou nenhuma.
|
|
251
251
|
|
|
@@ -253,7 +253,7 @@ A maioria dos métodos acima aceita um objeto `MethodOptions<Entity, OrmTypes>`
|
|
|
253
253
|
|
|
254
254
|
## Soft-delete
|
|
255
255
|
|
|
256
|
-
O soft-delete
|
|
256
|
+
O soft-delete é um **conceito nativo de primeira classe**. Configure `softRemoveKey` uma vez no repository:
|
|
257
257
|
|
|
258
258
|
```typescript
|
|
259
259
|
super({
|
|
@@ -286,7 +286,7 @@ await userRepository.getAll({ see: "all" }); // todos, ignorando o soft-delete
|
|
|
286
286
|
|
|
287
287
|
Toda subclasse de `VSRepository` ganha 8 métodos extras para trabalhar com campos numéricos, divididos em dois grupos:
|
|
288
288
|
|
|
289
|
-
**Updates atômicos** — avaliados no servidor contra o valor
|
|
289
|
+
**Updates atômicos** — avaliados no servidor contra o valor _atual_ da linha (`UPDATE ... SET field = field + value`), não um read-modify-write feito no client:
|
|
290
290
|
|
|
291
291
|
```typescript
|
|
292
292
|
await userRepository.increment("user-1", "balance", 50); // balance = balance + 50
|
|
@@ -334,7 +334,7 @@ Vale notar que vários ORMs (Drizzle, MikroORM, TypeORM) representam colunas `de
|
|
|
334
334
|
|
|
335
335
|
### Escrevendo um adapter
|
|
336
336
|
|
|
337
|
-
O `VSRepoAdapter` espelha as mesmas 8 operações (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — veja [Escrevendo seu próprio adapter](#escrevendo-seu-próprio-adapter)). Cada adapter traduz isso para o que o ORM/banco considera "nativo": o Prisma tem um formato de update embutido (`{ field: { increment: value } }`) e uma chamada `aggregate()`; outros ORMs em geral precisam de um `QueryBuilder`/expressão `sql` raw (ex.: `SET field = field * :value`, `SELECT SUM(field) ...`). Os métodos atômicos precisam retornar o registro refletindo o estado
|
|
337
|
+
O `VSRepoAdapter` espelha as mesmas 8 operações (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — veja [Escrevendo seu próprio adapter](#escrevendo-seu-próprio-adapter)). Cada adapter traduz isso para o que o ORM/banco considera "nativo": o Prisma tem um formato de update embutido (`{ field: { increment: value } }`) e uma chamada `aggregate()`; outros ORMs em geral precisam de um `QueryBuilder`/expressão `sql` raw (ex.: `SET field = field * :value`, `SELECT SUM(field) ...`). Os métodos atômicos precisam retornar o registro refletindo o estado _depois_ do write — se a API de update atômico do ORM só retorna a quantidade de linhas afetadas, faça uma leitura extra em vez de devolver uma cópia desatualizada que já estava em memória.
|
|
338
338
|
|
|
339
339
|
---
|
|
340
340
|
|
|
@@ -360,14 +360,6 @@ const usuarioComEndereco = await userRepository.get(id, {
|
|
|
360
360
|
>
|
|
361
361
|
> O core apenas repassa `MethodOptions.select` e `MethodOptions.relations` ao adapter — cada adapter decide como traduzi-los para o ORM subjacente:
|
|
362
362
|
>
|
|
363
|
-
> - **TypeORM (`@vsrepo/typeorm-adapter`)** — `relations` é **obrigatório** para carregar qualquer relação, mesmo quando você quer apenas uma projeção aninhada via `select`. O TypeORM não fará JOIN/carregar a relação a menos que ela esteja listada em `relations`:
|
|
364
|
-
> ```typescript
|
|
365
|
-
> // TypeORM: apenas select NÃO é suficiente
|
|
366
|
-
> await userRepository.get(id, {
|
|
367
|
-
> select: { id: true, address: { city: true } },
|
|
368
|
-
> relations: { address: true }, // ← obrigatório no TypeORM
|
|
369
|
-
> });
|
|
370
|
-
> ```
|
|
371
363
|
> - **Prisma 7 (`@vsrepo/prisma7-adapter` / `VSRepoPrisma7Adapter`)** — `relations` é convertido para `include` do Prisma (`parsePrismaInclude`). **Se `select` estiver presente, `relations` é ignorado** porque o Prisma não permite `select` + `include` na mesma query:
|
|
372
364
|
> ```typescript
|
|
373
365
|
> // Prisma7: relations é ignorado quando select existe
|
|
@@ -388,7 +380,7 @@ Métodos dinâmicos são declarados como um campo `declare` anotado com `@Dynami
|
|
|
388
380
|
```typescript
|
|
389
381
|
class UserRepository extends VSRepository<User, string> {
|
|
390
382
|
@DynamicMethod()
|
|
391
|
-
declare findByEmail: (email: string) => Promise<User[]>;
|
|
383
|
+
declare findByEmail: (email: string, options?: MethodOptions<User>) => Promise<User[]>;
|
|
392
384
|
|
|
393
385
|
@DynamicMethod()
|
|
394
386
|
declare findOneByEmail: (email: string) => Promise<User | null>;
|
|
@@ -404,12 +396,11 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
404
396
|
options?: MethodOptions<User>,
|
|
405
397
|
) => Promise<User[]>;
|
|
406
398
|
|
|
407
|
-
//
|
|
399
|
+
// filtros de campo, depois pagination, depois MethodOptions
|
|
408
400
|
@DynamicMethod()
|
|
409
401
|
declare findByNameIgnoreCaseOrAgeBetweenOrderByCreatedAtAscPaginated: (
|
|
410
402
|
name: string,
|
|
411
403
|
age: [number, number],
|
|
412
|
-
order: Ordering<User>,
|
|
413
404
|
pagination: Pagination,
|
|
414
405
|
options?: MethodOptions<User>,
|
|
415
406
|
) => Promise<User[]>;
|
|
@@ -418,40 +409,40 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
418
409
|
|
|
419
410
|
### Prefixos disponíveis
|
|
420
411
|
|
|
421
|
-
| Prefixo | Método do adapter | Observações
|
|
422
|
-
| -------------------------- | --------------------- |
|
|
423
|
-
| `findBy` | `findMany` | Filtros de campo seguem o prefixo.
|
|
424
|
-
| `findOneBy` | `findOne` | Filtros de campo seguem o prefixo; resultado único.
|
|
425
|
-
| `findOneOrThrowBy` | `findOneOrThrow` | Lança erro se não encontrar.
|
|
426
|
-
| `findOneOrThrow` | `findOneOrThrow` | Sem filtros de campo; aplica só soft-delete/`see`.
|
|
427
|
-
| `findOneOrThrowWhere` | `findOneOrThrow` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
428
|
-
| `findWhere` | `findMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
429
|
-
| `findOneWhere` | `findOne` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
430
|
-
| `findOne` | `findOne` | Sem filtros de campo; aplica só soft-delete/`see`.
|
|
431
|
-
| `countBy` | `count` | Filtros de campo seguem o prefixo.
|
|
432
|
-
| `countWhere` | `count` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
433
|
-
| `count` | `count` | Sem filtros de campo.
|
|
434
|
-
| `existsBy` | `exists` | Retorna `boolean`.
|
|
435
|
-
| `existsWhere` | `exists` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
436
|
-
| `create` | `create` | Recebe `
|
|
437
|
-
| `createMany` | `createMany` | Recebe `
|
|
438
|
-
| `createManyReturning` | `createManyReturning` | Recebe `
|
|
439
|
-
| `updateBy` | `update` | Filtros de campo + `
|
|
440
|
-
| `updateWhere` | `update` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `
|
|
441
|
-
| `updateManyBy` | `updateMany` | Filtros de campo + `
|
|
442
|
-
| `updateManyWhere` | `updateMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `
|
|
443
|
-
| `updateManyReturningBy` | `updateManyReturning` | Filtros de campo + `
|
|
444
|
-
| `updateManyReturningWhere` | `updateManyReturning` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `
|
|
445
|
-
| `upsertBy` | `upsert` | Filtros de campo + payloads `create`/`update`.
|
|
446
|
-
| `upsertWhere` | `upsert` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois os payloads `create`/`update`.
|
|
447
|
-
| `deleteBy` | `delete` | Filtros de campo seguem o prefixo.
|
|
448
|
-
| `deleteWhere` | `delete` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
449
|
-
| `deleteManyBy` | `deleteMany` | Filtros de campo seguem o prefixo.
|
|
450
|
-
| `deleteManyWhere` | `deleteMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento.
|
|
451
|
-
| `deleteManyReturningBy` | `deleteManyReturning` | Filtros de campo seguem o prefixo; retorna os registros removidos.
|
|
452
|
-
| `deleteManyReturningWhere` | `deleteManyReturning` | Recebe um `VSRepoWhere<T>` como primeiro argumento; retorna os registros removidos.
|
|
453
|
-
|
|
454
|
-
> `aggregate`
|
|
412
|
+
| Prefixo | Método do adapter | Observações |
|
|
413
|
+
| -------------------------- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
414
|
+
| `findBy` | `findMany` | Filtros de campo seguem o prefixo. |
|
|
415
|
+
| `findOneBy` | `findOne` | Filtros de campo seguem o prefixo; resultado único. |
|
|
416
|
+
| `findOneOrThrowBy` | `findOneOrThrow` | Lança erro se não encontrar. |
|
|
417
|
+
| `findOneOrThrow` | `findOneOrThrow` | Sem filtros de campo; aplica só soft-delete/`see`. |
|
|
418
|
+
| `findOneOrThrowWhere` | `findOneOrThrow` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
419
|
+
| `findWhere` | `findMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
420
|
+
| `findOneWhere` | `findOne` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
421
|
+
| `findOne` | `findOne` | Sem filtros de campo; aplica só soft-delete/`see`. |
|
|
422
|
+
| `countBy` | `count` | Filtros de campo seguem o prefixo. |
|
|
423
|
+
| `countWhere` | `count` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
424
|
+
| `count` | `count` | Sem filtros de campo. |
|
|
425
|
+
| `existsBy` | `exists` | Retorna `boolean`. |
|
|
426
|
+
| `existsWhere` | `exists` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
427
|
+
| `create` | `create` | Recebe `DeepPartial<Entity>` como argumento. |
|
|
428
|
+
| `createMany` | `createMany` | Recebe `DeepPartial<Entity>[]` como argumento; suporta `IgnoreConflicts`. |
|
|
429
|
+
| `createManyReturning` | `createManyReturning` | Recebe `DeepPartial<Entity>[]` como argumento; suporta `IgnoreConflicts`; retorna os registros criados (`T[]`), em vez de `CountResult`. |
|
|
430
|
+
| `updateBy` | `update` | Filtros de campo + `DeepPartial<Entity>` como argumento. |
|
|
431
|
+
| `updateWhere` | `update` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `DeepPartial<Entity>`. |
|
|
432
|
+
| `updateManyBy` | `updateMany` | Filtros de campo + `DeepPartial<Entity>`. |
|
|
433
|
+
| `updateManyWhere` | `updateMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `DeepPartial<Entity>`. |
|
|
434
|
+
| `updateManyReturningBy` | `updateManyReturning` | Filtros de campo + `DeepPartial<Entity>`; retorna os registros atualizados. |
|
|
435
|
+
| `updateManyReturningWhere` | `updateManyReturning` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois `DeepPartial<Entity>`; retorna os registros atualizados. |
|
|
436
|
+
| `upsertBy` | `upsert` | Filtros de campo + payloads `create`/`update`. |
|
|
437
|
+
| `upsertWhere` | `upsert` | Recebe um `VSRepoWhere<T>` como primeiro argumento, depois os payloads `create`/`update`. |
|
|
438
|
+
| `deleteBy` | `delete` | Filtros de campo seguem o prefixo. |
|
|
439
|
+
| `deleteWhere` | `delete` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
440
|
+
| `deleteManyBy` | `deleteMany` | Filtros de campo seguem o prefixo. |
|
|
441
|
+
| `deleteManyWhere` | `deleteMany` | Recebe um `VSRepoWhere<T>` como primeiro argumento. |
|
|
442
|
+
| `deleteManyReturningBy` | `deleteManyReturning` | Filtros de campo seguem o prefixo; retorna os registros removidos. |
|
|
443
|
+
| `deleteManyReturningWhere` | `deleteManyReturning` | Recebe um `VSRepoWhere<T>` como primeiro argumento; retorna os registros removidos. |
|
|
444
|
+
|
|
445
|
+
> `groupBy` **não está planejado** para a v2 — ele não se encaixa bem no contrato agnóstico de ORM. Um prefixo `aggregate` separado também dificilmente será implementado: as operações de agregação mais comuns (`sum`, `average`, `min`, `max`, `increment`, `decrement`, `multiply`, `divide`) já estão disponíveis como métodos base dedicados — veja [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação). Para qualquer coisa mais complexa, use um `@QueryMethod` com SQL raw.
|
|
455
446
|
|
|
456
447
|
### Filtros de campo
|
|
457
448
|
|
|
@@ -582,6 +573,11 @@ declare findOne: (options?: MethodOptions<User>) => Promise<User | null>;
|
|
|
582
573
|
| `injectOrdering` | `Ordering<T>` | Ordenação fixa injetada automaticamente, sobrescrevendo o `defaultOrdering` do repository. |
|
|
583
574
|
|
|
584
575
|
```typescript
|
|
576
|
+
// proxyTo: dá um nome customizado ao método reutilizando um padrão existente
|
|
577
|
+
@DynamicMethod<User>({ proxyTo: "findByEmail" })
|
|
578
|
+
declare buscarPorEmail: (email: string, options?: MethodOptions<User>) => Promise<User[]>;
|
|
579
|
+
|
|
580
|
+
// injectOrdering: sempre ordena por createdAt desc, sobrescrevendo o defaultOrdering
|
|
585
581
|
@DynamicMethod<User>({ injectOrdering: { createdAt: "desc" } })
|
|
586
582
|
declare findByStatus: (status: string) => Promise<User[]>;
|
|
587
583
|
```
|
|
@@ -590,7 +586,7 @@ declare findByStatus: (status: string) => Promise<User[]>;
|
|
|
590
586
|
|
|
591
587
|
## Query methods (SQL raw)
|
|
592
588
|
|
|
593
|
-
`@QueryMethod` ignora totalmente o engine de parsing por nome e executa uma instrução SQL raw através do método `query()` do adapter. Use placeholders
|
|
589
|
+
`@QueryMethod` ignora totalmente o engine de parsing por nome e executa uma instrução SQL raw através do método `query()` do adapter. Use placeholders para os valores passados via `args` — nunca interpole valores diretamente na string SQL. **A sintaxe dos placeholders depende do banco/driver usado pelo seu adapter:** o estilo `$1`, `$2`, ... usado nos exemplos abaixo é a convenção do PostgreSQL — o MySQL, por exemplo, usa `?`. Consulte a documentação do seu adapter para saber a sintaxe exata.
|
|
594
590
|
|
|
595
591
|
```typescript
|
|
596
592
|
class UserRepository extends VSRepository<User, string> {
|
|
@@ -607,9 +603,9 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
607
603
|
}
|
|
608
604
|
```
|
|
609
605
|
|
|
610
|
-
| Option | Tipo | Padrão | Descrição
|
|
611
|
-
| -------------- | --------- | ------- |
|
|
612
|
-
| `modifying` | `boolean` | `false` | Quando `true`,
|
|
606
|
+
| Option | Tipo | Padrão | Descrição |
|
|
607
|
+
| -------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
608
|
+
| `modifying` | `boolean` | `false` | Quando `true`, o método resolve para o número de linhas afetadas. Quando `false`, executa como query de leitura e resolve para o tipo de retorno declarado. |
|
|
613
609
|
| `singleResult` | `boolean` | `false` | Quando `true`, transforma um resultado em array no seu primeiro elemento (`null` se vazio), permitindo declarar o tipo de retorno como um objeto único em vez de array. Não tem efeito em resultados que não são array (ex.: o número de linhas afetadas de uma query `modifying`). |
|
|
614
610
|
|
|
615
611
|
Query methods aceitam `{ args, db? }` na chamada — `db` permite que participem de um bloco `transaction()`, assim como os métodos base e dinâmicos.
|
|
@@ -626,6 +622,10 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
626
622
|
declare findByEmailAndType: (
|
|
627
623
|
...args: QueryArgs<[email: string, userType: string]>
|
|
628
624
|
) => Promise<User[]>;
|
|
625
|
+
|
|
626
|
+
// Ao invés de usar o `QueryArgs`, você também pode simplesmente definir `DbArg` como último parâmetro
|
|
627
|
+
@QueryMethod('SELECT * FROM "user" WHERE id = $1', { spreadArgs: true })
|
|
628
|
+
declare findById: (id: string, db?: DbArg) => Promise<User[]>;
|
|
629
629
|
}
|
|
630
630
|
|
|
631
631
|
const admins = await userRepository.findByEmailAndType("joao@email.com", "admin");
|
|
@@ -634,7 +634,7 @@ const admins = await userRepository.findByEmailAndType("joao@email.com", "admin"
|
|
|
634
634
|
Para rodar a query com um client ou transação específico em vez do client padrão do repository, passe `withDb(tx)` como argumento final — ele embrulha `tx` em um `DbArg`, que o resolver reconhece via `instanceof`, então nunca é confundido com um argumento posicional comum, mesmo que esse argumento seja um objeto:
|
|
635
635
|
|
|
636
636
|
```typescript
|
|
637
|
-
await userRepository.transaction(async
|
|
637
|
+
await userRepository.transaction(async tx => {
|
|
638
638
|
await userRepository.findByEmailAndType("joao@email.com", "admin", withDb(tx));
|
|
639
639
|
});
|
|
640
640
|
```
|
|
@@ -661,18 +661,18 @@ const linhasAfetadas = await userRepository.query<number>(
|
|
|
661
661
|
|
|
662
662
|
// Aqui só se espera uma linha, então `singleResult` transforma o array
|
|
663
663
|
// em um único objeto (ou `null` quando nenhuma linha corresponde).
|
|
664
|
-
const user = await userRepository.query<User | null>(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
);
|
|
664
|
+
const user = await userRepository.query<User | null>('SELECT * FROM "user" WHERE id = $1 LIMIT 1', {
|
|
665
|
+
args: ["123"],
|
|
666
|
+
singleResult: true,
|
|
667
|
+
});
|
|
668
668
|
```
|
|
669
669
|
|
|
670
|
-
| Option | Tipo | Padrão | Descrição
|
|
671
|
-
| -------------- | --------- |
|
|
672
|
-
| `args` | `any[]` | `undefined`
|
|
673
|
-
| `db` | `any` | Client padrão do repository
|
|
674
|
-
| `modifying` | `boolean` | `false`
|
|
675
|
-
| `singleResult` | `boolean` | `false`
|
|
670
|
+
| Option | Tipo | Padrão | Descrição |
|
|
671
|
+
| -------------- | --------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
672
|
+
| `args` | `any[]` | `undefined` | Parâmetros posicionais injetados nos placeholders do SQL — a sintaxe dos placeholders depende do banco/driver usado pelo seu adapter. Nunca interpole valores diretamente na string SQL. |
|
|
673
|
+
| `db` | `any` | Client padrão do repository | Client ou transação do banco em que essa query deve rodar. |
|
|
674
|
+
| `modifying` | `boolean` | `false` | Quando `true`, retorna o número de linhas afetadas. |
|
|
675
|
+
| `singleResult` | `boolean` | `false` | Quando `true`, transforma um resultado em array no seu primeiro elemento (`null` se vazio). Não tem efeito em resultados que não são array (ex.: o número de linhas afetadas de uma query `modifying`). |
|
|
676
676
|
|
|
677
677
|
Assim como os métodos base, dinâmicos e query, `query()` aceita `db` em `options` para participar de um bloco `transaction()`.
|
|
678
678
|
|
|
@@ -711,10 +711,10 @@ await userRepository.transaction(
|
|
|
711
711
|
);
|
|
712
712
|
```
|
|
713
713
|
|
|
714
|
-
| Option | Type
|
|
715
|
-
|
|
|
714
|
+
| Option | Type | Descrição |
|
|
715
|
+
| ---------------- | --------------------------- | ---------------------------------------------------------------------------------- |
|
|
716
716
|
| `isolationLevel` | `TransactionIsolationLevel` | Nível de isolamento usado na transação. O padrão é o default do ORM por trás dela. |
|
|
717
|
-
| `timeoutMs`
|
|
717
|
+
| `timeoutMs` | `number` | Tempo máximo (em ms) que a transação pode rodar antes de ser abortada. |
|
|
718
718
|
|
|
719
719
|
`TransactionIsolationLevel` espelha os níveis de isolamento SQL padrão: `READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`. O suporte a um determinado nível depende do adapter/ORM e do banco de dados por trás dele.
|
|
720
720
|
|
|
@@ -749,26 +749,26 @@ import type {
|
|
|
749
749
|
} from "vsrepo";
|
|
750
750
|
```
|
|
751
751
|
|
|
752
|
-
| Tipo | Descrição
|
|
753
|
-
| --------------------------------------------------- |
|
|
754
|
-
| `MethodOptions<T, K>` | Options aceitas como último argumento pela maioria dos métodos base
|
|
755
|
-
| `RestrictMethodOptions<T, K>` | `MethodOptions<T, K>` restrito, expondo só `see`/`db` — usado pelos métodos que não retornam/moldam uma `Entity` (`total`, `has`, `sum`, `average`, `min`, `max`, `removeList`, `softRemoveList`, `restoreList`).
|
|
756
|
-
| `Pagination` | `{ limit?, offset? }` aceito por `getAll` e pelos métodos dinâmicos com `Paginated`.
|
|
757
|
-
| `Ordering<T>` / `OrderByField<T>` / `SortDirection` | Formato de ordenação aceito por `getAll`, `defaultOrdering` e `injectOrdering`, e pelos métodos dinâmicos com `Ordered`. Pode ser um único objeto ou um array encadeado; objetos aninhados ordenam relações to-one.
|
|
758
|
-
| `SeeMode` | `"active" \| "removed" \| "all"` — controla a visibilidade de registros com soft-delete.
|
|
759
|
-
| `DeepPartial<T>` | Torna todas as propriedades de `T` opcionais recursivamente, incluindo objetos aninhados e elementos de array.
|
|
760
|
-
| `CountResult` | `{ count: number }` — o formato retornado por operações em lote.
|
|
761
|
-
| `QueryMethodArg<T>` | `{ args?: T, db? }` — parâmetros posicionais do SQL (`$1`, `$2`, ...) e cliente de transação para o `@QueryMethod`.
|
|
762
|
-
| `QueryArgs<T, O>` | Tipa a lista de parâmetros via spread de um `@QueryMethod` declarado com `{ spreadArgs: true }`: os valores de `T`, em ordem, seguidos de um `DbArg<O>` opcional construído via `withDb()`.
|
|
763
|
-
| `KeysOfType<T, K>` | Extrai as chaves de `T` cujo tipo de valor é atribuível a `K`.
|
|
764
|
-
| `NumericKeys<T>` | Extrai as chaves de `T` cujo tipo de valor (ignorando `null`/`undefined`) é atribuível a `NumericLike`. Campos numéricos nullable (`number \| null`) são incluídos.
|
|
765
|
-
| `NumericLike` | `number \| bigint \| DecimalLike`.
|
|
766
|
-
| `DecimalLike` | Formato estrutural de um valor decimal de precisão arbitrária (`{ toNumber(): number; decimalPlaces(): number }`), compatível com o `Prisma.Decimal` do Prisma sem precisar importá-lo diretamente.
|
|
767
|
-
| `Primitive` | União de tipos escalares (`string \| number \| boolean \| bigint \| symbol \| undefined \| null \| Date`) tratados como valores-folha — e não relações — ao percorrer o formato de uma entidade.
|
|
768
|
-
| `VSRepoWhere<T>` | Tipo de filtro agnóstico de ORM aceito pelos métodos dinâmicos `*Where` (ex.: `findWhere`, `findOneWhere`, `updateWhere`). Suporta filtros de campo, operadores lógicos (`AND`/`OR`/`NOT`) e filtros de relação.
|
|
752
|
+
| Tipo | Descrição | Usado por |
|
|
753
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
754
|
+
| `MethodOptions<T, K>` | Options aceitas como último argumento por todos os métodos dinâmicos e pela maioria dos métodos base: `select`, `relations`, `see`, `db`. | [Métodos base](#métodos-base), [Métodos Dinâmicos](#métodos-dinâmicos). |
|
|
755
|
+
| `RestrictMethodOptions<T, K>` | `MethodOptions<T, K>` restrito, expondo só `see`/`db` — usado pelos métodos que não retornam/moldam uma `Entity` (`total`, `has`, `sum`, `average`, `min`, `max`, `removeList`, `softRemoveList`, `restoreList`). | [Métodos base](#métodos-base), [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação). |
|
|
756
|
+
| `Pagination` | `{ limit?, offset? }` aceito por `getAll` e pelos métodos dinâmicos com `Paginated`. | [Métodos base](#métodos-base), [Ordenação, paginação e distinct](#ordenação-paginação-e-distinct). |
|
|
757
|
+
| `Ordering<T>` / `OrderByField<T>` / `SortDirection` | Formato de ordenação aceito por `getAll`, `defaultOrdering` e `injectOrdering`, e pelos métodos dinâmicos com `Ordered`. Pode ser um único objeto ou um array encadeado; objetos aninhados ordenam relações to-one. | [Options do construtor](#options-do-construtor), [Options do decorador](#options-do-decorador), [Ordenação, paginação e distinct](#ordenação-paginação-e-distinct). |
|
|
758
|
+
| `SeeMode` | `"active" \| "removed" \| "all"` — controla a visibilidade de registros com soft-delete. | [Soft-delete](#soft-delete). |
|
|
759
|
+
| `DeepPartial<T>` | Torna todas as propriedades de `T` opcionais recursivamente, incluindo objetos aninhados e elementos de array. | `save`, `saveList`, `patch`, `merge`, e todo os métodos dinâmicos de escrita. |
|
|
760
|
+
| `CountResult` | `{ count: number }` — o formato retornado por operações em lote. | `removeList`, `softRemoveList`, `restoreList`, `createManyIgnoreConflicts`. |
|
|
761
|
+
| `QueryMethodArg<T>` | `{ args?: T, db? }` — parâmetros posicionais do SQL (a sintaxe dos placeholders depende do banco/driver usado pelo seu adapter: `$1`, `$2`, ... para PostgreSQL, `?` para MySQL) e cliente de transação para o `@QueryMethod`. | [Query methods (SQL raw)](#query-methods-sql-raw). |
|
|
762
|
+
| `QueryArgs<T, O>` | Tipa a lista de parâmetros via spread de um `@QueryMethod` declarado com `{ spreadArgs: true }`: os valores de `T`, em ordem, seguidos de um `DbArg<O>` opcional construído via `withDb()`. | [Argumentos via spread com `spreadArgs`](#argumentos-via-spread-com-spreadargs). |
|
|
763
|
+
| `KeysOfType<T, K>` | Extrai as chaves de `T` cujo tipo de valor é atribuível a `K`. | Restringe `pkName`, em [Options do construtor](#options-do-construtor), aos campos da entidade compatíveis com o tipo de chave primária configurado. |
|
|
764
|
+
| `NumericKeys<T>` | Extrai as chaves de `T` cujo tipo de valor (ignorando `null`/`undefined`) é atribuível a `NumericLike`. Campos numéricos nullable (`number \| null`) são incluídos. | Restringe `field` em [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação) (`increment`, `sum`, etc). |
|
|
765
|
+
| `NumericLike` | `number \| bigint \| DecimalLike`. | [Métodos atômicos e de agregação](#métodos-atômicos-e-de-agregação). |
|
|
766
|
+
| `DecimalLike` | Formato estrutural de um valor decimal de precisão arbitrária (`{ toNumber(): number; decimalPlaces(): number }`), compatível com o `Prisma.Decimal` do Prisma sem precisar importá-lo diretamente. | [Quais campos são elegíveis](#quais-campos-são-elegíveis). |
|
|
767
|
+
| `Primitive` | União de tipos escalares (`string \| number \| boolean \| bigint \| symbol \| undefined \| null \| Date \| DecimalLike`) tratados como valores-folha — e não relações — ao percorrer o formato de uma entidade. | Usado por `Ordering<T>` para distinguir campos escalares de campos de relação. |
|
|
768
|
+
| `VSRepoWhere<T>` | Tipo de filtro agnóstico de ORM aceito pelos métodos dinâmicos `*Where` (ex.: `findWhere`, `findOneWhere`, `updateWhere`). Suporta filtros de campo, operadores lógicos (`AND`/`OR`/`NOT`) e filtros de relação. | [Prefixos `findWhere`, `findOneWhere` e demais `*Where`](#prefixos-disponíveis). |
|
|
769
769
|
| `VSRepoOrmTypes` | `{ dbClient; dbTransaction }` — descreve os tipos de client/transaction do seu ORM. Passado como terceiro generic de `VSRepository<Entity, PKType, OrmTypes>` para tipar `getDbClient()`, `transaction()` e a option `db` em vez de `any`. | [Criando um repository](#criando-um-repository). |
|
|
770
|
-
| `VSRepoTransactionOptions` | `{ isolationLevel?, timeoutMs? }` — options aceitas como segundo argumento de `transaction()`.
|
|
771
|
-
| `TransactionIsolationLevel` | Enum dos níveis de isolamento SQL padrão (`READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`) aceitos por `VSRepoTransactionOptions.isolationLevel`.
|
|
770
|
+
| `VSRepoTransactionOptions` | `{ isolationLevel?, timeoutMs? }` — options aceitas como segundo argumento de `transaction()`. | [Transações](#transações). |
|
|
771
|
+
| `TransactionIsolationLevel` | Enum dos níveis de isolamento SQL padrão (`READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`) aceitos por `VSRepoTransactionOptions.isolationLevel`. | [Transações](#transações). |
|
|
772
772
|
|
|
773
773
|
### `DeepPartial<T>`
|
|
774
774
|
|
|
@@ -947,13 +947,13 @@ export class MyOrmAdapter<T> extends VSRepoAdapter<T> {
|
|
|
947
947
|
}
|
|
948
948
|
```
|
|
949
949
|
|
|
950
|
-
| Método
|
|
951
|
-
|
|
|
952
|
-
| `new VSLogger(logLevel, name, slowThresholdMs?)`
|
|
953
|
-
| `logDebug/logInfo/logWarn(text, obj?)`
|
|
954
|
-
| `logError(text, err?)`
|
|
955
|
-
| `startPerformLog(operation)` / `endPerformLog(data)` | Envolve um trecho de código para logar sua duração, escalando pra `WARN` se ultrapassar `slowThresholdMs`.
|
|
956
|
-
| `getLogLevel()`
|
|
950
|
+
| Método | Descrição |
|
|
951
|
+
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
952
|
+
| `new VSLogger(logLevel, name, slowThresholdMs?)` | Cria um logger; `name` prefixa cada linha. `slowThresholdMs` controla o threshold de operação lenta: um `number` define o valor em ms (padrão 300), `false` desabilita os avisos de operação lenta completamente, `true` ou omitido usa o padrão de 300ms. |
|
|
953
|
+
| `logDebug/logInfo/logWarn(text, obj?)` | Loga no nível dado se `logLevel` permitir; `obj` é anexado como JSON formatado. |
|
|
954
|
+
| `logError(text, err?)` | Loga em `ERROR`; se `err` for uma `Error`, só `name`/`message`/`stack`/`cause` são logados. |
|
|
955
|
+
| `startPerformLog(operation)` / `endPerformLog(data)` | Envolve um trecho de código para logar sua duração, escalando pra `WARN` se ultrapassar `slowThresholdMs`. |
|
|
956
|
+
| `getLogLevel()` | Retorna o `VSLogLevel` configurado do logger. |
|
|
957
957
|
|
|
958
958
|
Isso é puramente uma conveniência para autores de adapters — nada no core exige que seu adapter o utilize.
|
|
959
959
|
|
|
@@ -979,7 +979,7 @@ try {
|
|
|
979
979
|
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
980
980
|
| `DECORATOR` | Argumentos inválidos foram passados para `@DynamicMethod` ou `@QueryMethod`. |
|
|
981
981
|
| `RESOLVER` | A biblioteca falhou ao resolver a configuração de um método dinâmico/de query em um método chamável (ex.: um nome de método desconhecido). |
|
|
982
|
-
| `DYNAMIC` | Um dynamic/query method já resolvido falhou em tempo de execução (ex.: argumentos faltando).
|
|
982
|
+
| `DYNAMIC` | Um dynamic/query method já resolvido falhou em tempo de execução (ex.: argumentos faltando). |
|
|
983
983
|
| `VALIDATOR` | Options ou argumentos de método inválidos foram detectados durante a validação. |
|
|
984
984
|
| `BASE` | Uso inválido de um método base (`get`, `save`, `remove`, etc). |
|
|
985
985
|
| `ADAPTER` | Um `VSRepoAdapter` falhou ao falar com o ORM/banco subjacente — sempre é lançado como `VSRepoAdapterError`. |
|
|
@@ -1034,41 +1034,42 @@ import { AdapterErrorCode } from "vsrepo";
|
|
|
1034
1034
|
console.log(AdapterErrorCode.UNIQUE_CONSTRAINT_VIOLATION); // "UNIQUE_CONSTRAINT_VIOLATION"
|
|
1035
1035
|
```
|
|
1036
1036
|
|
|
1037
|
-
| Código | Significado
|
|
1038
|
-
| ----------------------------- |
|
|
1039
|
-
| `UNKNOWN` | Erro não classificado/desconhecido; o fallback quando nenhum código mais específico corresponde.
|
|
1040
|
-
| `
|
|
1041
|
-
| `
|
|
1042
|
-
| `
|
|
1043
|
-
| `
|
|
1044
|
-
| `
|
|
1045
|
-
| `
|
|
1046
|
-
| `
|
|
1047
|
-
| `
|
|
1048
|
-
| `
|
|
1049
|
-
| `
|
|
1050
|
-
| `
|
|
1051
|
-
| `
|
|
1052
|
-
| `
|
|
1053
|
-
| `
|
|
1054
|
-
| `
|
|
1055
|
-
| `
|
|
1056
|
-
| `
|
|
1057
|
-
| `
|
|
1058
|
-
| `
|
|
1059
|
-
| `
|
|
1060
|
-
| `
|
|
1061
|
-
| `
|
|
1062
|
-
| `
|
|
1063
|
-
| `
|
|
1064
|
-
| `
|
|
1065
|
-
| `
|
|
1066
|
-
| `
|
|
1067
|
-
| `
|
|
1068
|
-
| `
|
|
1069
|
-
| `
|
|
1070
|
-
| `
|
|
1071
|
-
| `
|
|
1037
|
+
| Código | Significado |
|
|
1038
|
+
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
1039
|
+
| `UNKNOWN` | Erro não classificado/desconhecido; o fallback quando nenhum código mais específico corresponde. |
|
|
1040
|
+
| `TRANSACTION_ROLLED_BACK` | Alguns adapters podem usar esse código para rollbacks forçados de transações (como o `tx.rollback()` do Drizzle) |
|
|
1041
|
+
| `MISSING_DB_CLIENT` | Cliente de banco (ou pool de conexões) não fornecido ou que não pôde ser resolvido. |
|
|
1042
|
+
| `CONNECTION_FAILED` | Não foi possível alcançar/conectar ao banco, ou uma conexão estabelecida foi perdida/terminada. |
|
|
1043
|
+
| `CONNECTION_POOL_EXHAUSTED` | Pool de conexões esgotado/depletado — nenhuma conexão disponível, todas ocupadas ou o limite foi atingido. |
|
|
1044
|
+
| `TIMEOUT` | O banco não respondeu a tempo; uma query excedeu o timeout permitido. |
|
|
1045
|
+
| `UNIQUE_CONSTRAINT_VIOLATION` | Violação de constraint unique (chave duplicada). Ex.: Postgres/SQLite `23505`, MySQL `1062`. |
|
|
1046
|
+
| `FOREIGN_KEY_VIOLATION` | Violação de constraint de foreign key (linha referenciada não existe). |
|
|
1047
|
+
| `NOT_NULL_VIOLATION` | Violação de constraint NOT NULL. |
|
|
1048
|
+
| `CHECK_VIOLATION` | Violação de constraint CHECK. |
|
|
1049
|
+
| `CONSTRAINT_VIOLATION` | Violação geral de integridade/constraint não coberta por um código mais específico. |
|
|
1050
|
+
| `NOT_FOUND` | Registro solicitado não encontrado (ex.: uma operação tipo `findOneOrThrow`). |
|
|
1051
|
+
| `INVALID_DATA` | Valor de campo inválido para o tipo/tamanho, ou um valor obrigatório ausente. |
|
|
1052
|
+
| `VALUE_TOO_LONG` | Valor fornecido excede o limite de tamanho da coluna/campo. |
|
|
1053
|
+
| `CONVERSION_ERROR` | Um valor não pôde ser convertido/convertido para o tipo alvo. Ex.: Postgres `22P02`, MySQL `1366`. |
|
|
1054
|
+
| `INVALID_QUERY` | A query/stored procedure SQL está malformada ou é inválida. |
|
|
1055
|
+
| `TABLE_OR_COLUMN_NOT_FOUND` | A tabela/coluna/relação referenciada não existe. |
|
|
1056
|
+
| `DEADLOCK` | Operação abortada por timeout de lock ou deadlock entre transações concorrentes. |
|
|
1057
|
+
| `LOCK_TIMEOUT` | Não foi possível adquirir um lock de banco obrigatório a tempo. |
|
|
1058
|
+
| `LOCKED` | O registro está travado e não pode ser modificado. |
|
|
1059
|
+
| `ACCESS_DENIED` | O usuário/role atual não tem permissão para a operação. |
|
|
1060
|
+
| `INVALID_CREDENTIALS` | Credenciais de conexão inválidas (host/usuário/senha). |
|
|
1061
|
+
| `ROW_NOT_ALLOWED` | O usuário autenticado não é dono do registro / a segurança em nível de linha rejeitou. |
|
|
1062
|
+
| `MODEL_NOT_FOUND` | Entidade/modelo ou tabela não definida/mapeada no ORM, ou o adapter não tem os metadados do modelo. |
|
|
1063
|
+
| `FIELD_NOT_FOUND` | Nome de campo/coluna nos dados ou no `where` não existe na entidade/modelo. |
|
|
1064
|
+
| `TRANSACTION_CLOSED` | Transação usada depois de commit/rollback. |
|
|
1065
|
+
| `TRANSACTION_ALREADY_STARTED` | Uma transação aninhada não pôde ser aberta (ex.: chamadas `transaction()` aninhadas). |
|
|
1066
|
+
| `TRANSACTION_CONFLICT` | Uma transação falhou ao commitar e foi desfeita. |
|
|
1067
|
+
| `TRANSACTION_NOT_STARTED` | Nenhuma transação ativa quando uma era obrigatória. |
|
|
1068
|
+
| `CONNECTION_CLOSED` | Conexão fechada/terminada enquanto uma transação ou query estava em andamento. |
|
|
1069
|
+
| `INVALID_PARTIAL` | `merge`/`upsert`/`update` recebeu um objeto parcial inválido ou faltando chaves obrigatórias. |
|
|
1070
|
+
| `NOT_SUPPORTED` | Feature/operação não suportada solicitada ao adapter (ex.: `query()` bruto não suportado). |
|
|
1071
|
+
| `INVALID_ADAPTER_CONFIG` | Configuração do adapter inválida ou incompleta (options obrigatórias ausentes, ou com tipo/valor inválido). |
|
|
1072
|
+
| `INTERNAL` | Bug interno do adapter ou estado irrecuperável; deve raramente ser usado — prefira um código mais específico. |
|
|
1072
1073
|
|
|
1073
1074
|
#### `VSRepoError` vs. erros brutos do ORM
|
|
1074
1075
|
|
|
@@ -1087,7 +1088,8 @@ super({
|
|
|
1087
1088
|
pkName: "id",
|
|
1088
1089
|
adapter,
|
|
1089
1090
|
logLevel: VSLogLevel.DEBUG,
|
|
1090
|
-
logSlowThresholdMs: 200,
|
|
1091
|
+
logSlowThresholdMs: 200, // avisa se qualquer operação levar mais de 200ms
|
|
1092
|
+
// logSlowThresholdMs: false, // desabilita os avisos de operação lenta completamente
|
|
1091
1093
|
});
|
|
1092
1094
|
```
|
|
1093
1095
|
|
|
@@ -1149,11 +1151,11 @@ Observações:
|
|
|
1149
1151
|
|
|
1150
1152
|
## Contribuindo
|
|
1151
1153
|
|
|
1152
|
-
Contribuições são bem-vindas, especialmente para
|
|
1154
|
+
Contribuições são bem-vindas, especialmente para melhorar o adapter do Prisma e finalizar o do Drizzle! (**[Repositório do GitHub](https://github.com/jaobrabo123/VSRepository)**):
|
|
1153
1155
|
|
|
1154
1156
|
1. Faça um **Fork** do projeto.
|
|
1155
|
-
2. Crie uma branch
|
|
1157
|
+
2. Crie uma branch para sua alteração: `git checkout -b v2-minha-alteracao`.
|
|
1156
1158
|
3. Faça o push da sua branch: `git push origin v2-minha-alteracao`.
|
|
1157
|
-
4. Abra um **Pull Request
|
|
1159
|
+
4. Abra um **Pull Request**.
|
|
1158
1160
|
|
|
1159
1161
|
Para reportar problemas ou sugerir funcionalidades, abra uma **Issue**.
|