vsrepo 1.1.3 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|

|
|
5
|
+

|
|
5
6
|
|
|
6
7
|
Biblioteca de repository pattern para projetos que usam **Prisma**, com suporte completo a **TypeScript** e **type inference** automático.
|
|
7
8
|
|
|
@@ -70,21 +71,21 @@ Equivale a:
|
|
|
70
71
|
|
|
71
72
|
```bash
|
|
72
73
|
npx vsrepo generate \
|
|
73
|
-
--output
|
|
74
|
-
--prisma
|
|
74
|
+
--output generated/vsrepo \
|
|
75
|
+
--prisma generated/prisma
|
|
75
76
|
```
|
|
76
77
|
|
|
77
78
|
**Flags disponíveis:**
|
|
78
79
|
|
|
79
80
|
| Flag | Alias | Padrão |
|
|
80
81
|
| ---------- | ----- | ---------------------- |
|
|
81
|
-
| `--output` | `-o` | `
|
|
82
|
-
| `--prisma` | `-p` | `
|
|
82
|
+
| `--output` | `-o` | `generated/vsrepo` |
|
|
83
|
+
| `--prisma` | `-p` | `generated/prisma` |
|
|
83
84
|
|
|
84
85
|
**Arquivos gerados:**
|
|
85
86
|
|
|
86
87
|
```
|
|
87
|
-
|
|
88
|
+
generated/vsrepo/
|
|
88
89
|
├── VSRepoError.ts
|
|
89
90
|
├── VSRepoError.types.d.ts
|
|
90
91
|
├── VSRepository.ts
|
|
@@ -96,7 +97,7 @@ Após gerar, importe sempre a partir da pasta gerada:
|
|
|
96
97
|
|
|
97
98
|
```ts
|
|
98
99
|
// CORRETO ✅
|
|
99
|
-
import { setupVSRepo } from "
|
|
100
|
+
import { setupVSRepo } from "../../generated/vsrepo";
|
|
100
101
|
|
|
101
102
|
// ERRADO ❌
|
|
102
103
|
import { setupVSRepo } from "vsrepo";
|
|
@@ -110,7 +111,7 @@ import { setupVSRepo } from "vsrepo";
|
|
|
110
111
|
|
|
111
112
|
```ts
|
|
112
113
|
// src/configs/db.ts
|
|
113
|
-
import { PrismaClient } from '
|
|
114
|
+
import { PrismaClient } from '../../generated/prisma/client';
|
|
114
115
|
import { PrismaPg } from '@prisma/adapter-pg';
|
|
115
116
|
import 'dotenv/config';
|
|
116
117
|
|
|
@@ -125,8 +126,8 @@ export default prisma;
|
|
|
125
126
|
```ts
|
|
126
127
|
// src/repositories/usuarioRepository.ts
|
|
127
128
|
import prisma from "../configs/db";
|
|
128
|
-
import { setupVSRepo } from "
|
|
129
|
-
import type { Usuario } from "
|
|
129
|
+
import { setupVSRepo } from "../../generated/vsrepo";
|
|
130
|
+
import type { Usuario } from "../../generated/prisma/client";
|
|
130
131
|
|
|
131
132
|
const usuarioRepository = setupVSRepo<Usuario, "usuario">()({
|
|
132
133
|
tableName: "usuario",
|
|
@@ -172,11 +173,11 @@ O VSRepository pode ser facilmente integrado em projetos NestJS através de prov
|
|
|
172
173
|
### Configurando o repository como provider
|
|
173
174
|
|
|
174
175
|
```ts
|
|
175
|
-
// src/
|
|
176
|
+
// src/resources/user/user.repository.ts
|
|
176
177
|
import { Provider } from "@nestjs/common";
|
|
177
178
|
import { PrismaService } from "../../database/prisma.service";
|
|
178
|
-
import { UserGetPayload } from "
|
|
179
|
-
import { setupVSRepo } from "
|
|
179
|
+
import { UserGetPayload } from "../../../generated/prisma/models";
|
|
180
|
+
import { setupVSRepo } from "../../../generated/vsrepo";
|
|
180
181
|
|
|
181
182
|
const userVSRepo = setupVSRepo<
|
|
182
183
|
UserGetPayload<{ include: { profile: true } }>,
|
|
@@ -242,9 +243,9 @@ export const UserRepositoryProvider: Provider = {
|
|
|
242
243
|
### Registrando o provider no módulo
|
|
243
244
|
|
|
244
245
|
```ts
|
|
245
|
-
// src/
|
|
246
|
+
// src/resources/user/user.module.ts
|
|
246
247
|
import { Module } from "@nestjs/common";
|
|
247
|
-
import { UserRepositoryProvider } from "
|
|
248
|
+
import { UserRepositoryProvider } from "./user.repository";
|
|
248
249
|
import { UserService } from "./user.service";
|
|
249
250
|
import { UserController } from "./user.controller";
|
|
250
251
|
|
|
@@ -260,9 +261,9 @@ export class UserModule {}
|
|
|
260
261
|
### Utilizando o repository em um serviço
|
|
261
262
|
|
|
262
263
|
```ts
|
|
263
|
-
// src/
|
|
264
|
+
// src/resources/user/user.service.ts
|
|
264
265
|
import { Injectable, Inject } from "@nestjs/common";
|
|
265
|
-
import { USER_REPOSITORY, UserRepository } from "
|
|
266
|
+
import { USER_REPOSITORY, UserRepository } from "./user.repository";
|
|
266
267
|
|
|
267
268
|
@Injectable()
|
|
268
269
|
export class UserService {
|
|
@@ -292,7 +293,7 @@ export class UserService {
|
|
|
292
293
|
### Usando em um controller
|
|
293
294
|
|
|
294
295
|
```ts
|
|
295
|
-
// src/
|
|
296
|
+
// src/resources/user/user.controller.ts
|
|
296
297
|
import { Controller, Get, Post, Body, Param, Patch, Delete } from "@nestjs/common";
|
|
297
298
|
import { UserService } from "./user.service";
|
|
298
299
|
|
|
@@ -723,7 +724,7 @@ methods: {
|
|
|
723
724
|
Configure relações para que o `save` as gerencie automaticamente. Para que as relações apareçam no autocomplete, o tipo genérico deve incluir as relações usando `GetPayload`:
|
|
724
725
|
|
|
725
726
|
```ts
|
|
726
|
-
import type { Prisma } from "
|
|
727
|
+
import type { Prisma } from "../../generated/prisma/client";
|
|
727
728
|
|
|
728
729
|
type Usuario = Prisma.usuarioGetPayload<{
|
|
729
730
|
include: { perfil: true; postagens: true };
|
|
@@ -818,7 +819,7 @@ const usuarioRepository = setupVSRepo<Usuario, "usuario">()({
|
|
|
818
819
|
O VSRepository lança `VSRepoError` e suas subclasses em situações específicas (OBS: Erros do Prisma não são sobrescritos como `VSRepoError`):
|
|
819
820
|
|
|
820
821
|
```ts
|
|
821
|
-
import { VSRepoError } from "
|
|
822
|
+
import { VSRepoError } from "../../generated/vsrepo";
|
|
822
823
|
|
|
823
824
|
try {
|
|
824
825
|
const usuario = await usuarioRepository.get();
|
|
@@ -847,7 +848,7 @@ O VSRepository exporta os seguintes tipos para uso nas suas aplicações:
|
|
|
847
848
|
### Tipos de cliente
|
|
848
849
|
|
|
849
850
|
```ts
|
|
850
|
-
import type { DbClient, DbTransaction, ClientOrTransaction } from "
|
|
851
|
+
import type { DbClient, DbTransaction, ClientOrTransaction } from "../../generated/vsrepo";
|
|
851
852
|
|
|
852
853
|
type DbClient = PrismaClient;
|
|
853
854
|
type DbTransaction = Prisma.TransactionClient;
|
|
@@ -864,7 +865,7 @@ import type {
|
|
|
864
865
|
OrdenationModel,
|
|
865
866
|
PaginationModel,
|
|
866
867
|
ModelUpsertInput,
|
|
867
|
-
} from "
|
|
868
|
+
} from "../../generated/vsrepo";
|
|
868
869
|
|
|
869
870
|
// Select de um campo específico
|
|
870
871
|
type UsuarioSelect = SelectModel<"usuario">;
|
|
@@ -888,7 +889,7 @@ type UsuarioUpsertInput = ModelUpsertInput<"usuario">;
|
|
|
888
889
|
### Todos os inputs do modelo
|
|
889
890
|
|
|
890
891
|
```ts
|
|
891
|
-
import type { PrismaModelInputs } from "
|
|
892
|
+
import type { PrismaModelInputs } from "../../generated/vsrepo";
|
|
892
893
|
|
|
893
894
|
type UsuarioInputs = PrismaModelInputs<"usuario">;
|
|
894
895
|
// Contém:
|
|
@@ -899,7 +900,7 @@ type UsuarioInputs = PrismaModelInputs<"usuario">;
|
|
|
899
900
|
### Tipos de opções de método
|
|
900
901
|
|
|
901
902
|
```ts
|
|
902
|
-
import type { MethodOptions, MethodOptionsModel } from "
|
|
903
|
+
import type { MethodOptions, MethodOptionsModel } from "../../generated/vsrepo";
|
|
903
904
|
|
|
904
905
|
// MethodOptions<S> — opções passadas nos métodos do repository
|
|
905
906
|
// S = chave do select model ou false
|
|
@@ -919,7 +920,7 @@ import type {
|
|
|
919
920
|
RepositoryRelations,
|
|
920
921
|
ExtractRelationConfig,
|
|
921
922
|
UpsertWithRelations,
|
|
922
|
-
} from "
|
|
923
|
+
} from "../../generated/vsrepo";
|
|
923
924
|
|
|
924
925
|
// Configuração de um método dinâmico
|
|
925
926
|
type MeuMethodConfig = MethodConfig<"usuario", typeof meuSelectModels>;
|
|
@@ -943,7 +944,7 @@ type UsuarioComRelacoes = UpsertWithRelations<Usuario, "usuario", typeof relatio
|
|
|
943
944
|
### Tipo do repository construído
|
|
944
945
|
|
|
945
946
|
```ts
|
|
946
|
-
import type { BuiltRepository, RepositoryOf } from "
|
|
947
|
+
import type { BuiltRepository, RepositoryOf } from "../../generated/vsrepo";
|
|
947
948
|
|
|
948
949
|
// Tipo completo de um repository construído
|
|
949
950
|
type MeuRepo = BuiltRepository<Usuario, "usuario", typeof config, typeof buildConfig>;
|
|
@@ -970,7 +971,7 @@ type UsuarioRepositoryExtended = RepositoryOf<typeof usuarioVSRepo, undefined, t
|
|
|
970
971
|
### Tipo auxiliar
|
|
971
972
|
|
|
972
973
|
```ts
|
|
973
|
-
import type { DistributiveOmit } from "
|
|
974
|
+
import type { DistributiveOmit } from "../../generated/vsrepo";
|
|
974
975
|
|
|
975
976
|
// Omit distributivo — preserva unions ao omitir propriedades
|
|
976
977
|
type SemEmail = DistributiveOmit<Usuario | Perfil, "email">;
|
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import z from "zod";
|
|
2
2
|
import { VSRepoConfigError, VSRepoBuildError } from "./VSRepoError.js";
|
|
3
3
|
|
|
4
|
+
export function mergeWheres(currentWhere, restrictWhere) {
|
|
5
|
+
const restrictWhereKeys = Object.keys(restrictWhere);
|
|
6
|
+
for (let i = 0; i < restrictWhereKeys.length; i++) {
|
|
7
|
+
const restrictWhereKey = restrictWhereKeys[i];
|
|
8
|
+
const restrictWhereField = restrictWhere[restrictWhereKey];
|
|
9
|
+
|
|
10
|
+
if (restrictWhereField === null || typeof restrictWhereField !== "object") {
|
|
11
|
+
currentWhere[restrictWhereKey] = restrictWhereField;
|
|
12
|
+
} else if (Array.isArray(restrictWhereField)) {
|
|
13
|
+
currentWhere[restrictWhereKey] = Array.isArray(currentWhere[restrictWhereKey]) ?
|
|
14
|
+
restrictWhereField.concat(currentWhere[restrictWhereKey]) :
|
|
15
|
+
restrictWhereField;
|
|
16
|
+
} else {
|
|
17
|
+
currentWhere[restrictWhereKey] =
|
|
18
|
+
currentWhere[restrictWhereKey] != null &&
|
|
19
|
+
typeof currentWhere[restrictWhereKey] === "object" &&
|
|
20
|
+
!Array.isArray(currentWhere[restrictWhereKey]) ?
|
|
21
|
+
Object.assign(currentWhere[restrictWhereKey], restrictWhereField) :
|
|
22
|
+
restrictWhereField;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
4
27
|
const stringSchema = z.string().trim().nonempty();
|
|
5
28
|
const objectSchema = z.looseObject({});
|
|
6
29
|
const booleanSchema = z.boolean();
|
|
@@ -9,7 +9,7 @@ export * from "./VSRepoError.js";
|
|
|
9
9
|
|
|
10
10
|
// * Importando classes de erro
|
|
11
11
|
import { VSRepoBuildError, VSRepoExtendError, VSRepoRuntimeError } from "./VSRepoError.js";
|
|
12
|
-
import { validateBuildConfig, validateConfig } from "./VSRepoUtils.js";
|
|
12
|
+
import { mergeWheres, validateBuildConfig, validateConfig } from "./VSRepoUtils.js";
|
|
13
13
|
|
|
14
14
|
// * Essa é a classe pincipal, é a partir dela que serão criados os objetos dos repositories
|
|
15
15
|
export class VSRepository {
|
|
@@ -593,15 +593,11 @@ export class VSRepository {
|
|
|
593
593
|
const assignWhere = (where) => {
|
|
594
594
|
if(whereType==='extending' && buildInstance.requiredWhere) {
|
|
595
595
|
let safeRequiredWhere = structuredClone(buildInstance.requiredWhere);
|
|
596
|
-
|
|
597
|
-
if(where.AND && safeRequiredWhere.AND) safeRequiredWhere.AND = safeRequiredWhere.AND.concat(where.AND)
|
|
598
|
-
Object.assign(where, safeRequiredWhere);
|
|
596
|
+
mergeWheres(where, safeRequiredWhere);
|
|
599
597
|
}
|
|
600
598
|
if(pushWhere !== undefined) {
|
|
601
599
|
let safePushWhere = structuredClone(pushWhere);
|
|
602
|
-
|
|
603
|
-
if(where.AND && safePushWhere.AND) safePushWhere.AND = safePushWhere.AND.concat(where.AND)
|
|
604
|
-
Object.assign(where, safePushWhere);
|
|
600
|
+
mergeWheres(where, safePushWhere);
|
|
605
601
|
}
|
|
606
602
|
}
|
|
607
603
|
|
package/package.json
CHANGED
|
@@ -8,8 +8,8 @@ const workspaceRoot = process.cwd();
|
|
|
8
8
|
const args = process.argv.slice(2);
|
|
9
9
|
const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
|
-
const DEFAULT_OUTPUT = '
|
|
12
|
-
const DEFAULT_PRISMA = '
|
|
11
|
+
const DEFAULT_OUTPUT = 'generated/vsrepo';
|
|
12
|
+
const DEFAULT_PRISMA = 'generated/prisma';
|
|
13
13
|
const GENERATED_HEADER = `/**
|
|
14
14
|
* ! THIS FILE IS AUTO-GENERATED.
|
|
15
15
|
* ! DO NOT EDIT MANUALLY.
|
|
@@ -55,7 +55,7 @@ if (prismaArg.startsWith('-')) {
|
|
|
55
55
|
const outputDir = path.resolve(workspaceRoot, outputArg);
|
|
56
56
|
|
|
57
57
|
const prismaTargetPath = stripKnownExtension(
|
|
58
|
-
path.resolve(workspaceRoot, prismaArg, 'client')
|
|
58
|
+
path.resolve(workspaceRoot, prismaArg, prismaArg.endsWith('client') ? '' : 'client')
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
const installedNodeModulesPath = path.join(workspaceRoot, 'node_modules/vsrepo');
|
|
@@ -186,7 +186,7 @@ const readmeTarget = path.join(outputDir, 'README.md');
|
|
|
186
186
|
|
|
187
187
|
if (fs.existsSync(readmeSource)) {
|
|
188
188
|
fs.copyFileSync(readmeSource, readmeTarget);
|
|
189
|
-
console.log(`
|
|
189
|
+
console.log(`Gerado: ${path.relative(workspaceRoot, readmeTarget)}`);
|
|
190
190
|
} else {
|
|
191
191
|
console.warn(`README.md do VSRepository nao encontrado em: ${path.relative(workspaceRoot, readmeSource)}. Ignorando a copia.`);
|
|
192
192
|
}
|