vsrepo 1.1.4 → 1.1.6
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 +45 -10
- package/VSRepository/VSRepoUtils.js +23 -0
- package/VSRepository/VSRepository.d.ts +19 -1
- package/VSRepository/VSRepository.js +259 -114
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# VSRepository
|
|
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
|
|
|
@@ -34,7 +35,7 @@ O VSRepository permite criar repositories fortemente tipados com:
|
|
|
34
35
|
- [Configuração de métodos](#configuração-de-métodos)
|
|
35
36
|
- [Relações no save](#relações-no-save)
|
|
36
37
|
- [Transações](#transações)
|
|
37
|
-
- [
|
|
38
|
+
- [Estendendo um repository](#estendendo-um-repository)
|
|
38
39
|
- [Tratamento de erros](#tratamento-de-erros)
|
|
39
40
|
- [Tipos utilitários](#tipos-utilitários)
|
|
40
41
|
- [API Reference](#api-reference)
|
|
@@ -333,6 +334,7 @@ Ao chamar `.build(prisma)` os métodos base abaixo são automaticamente disponib
|
|
|
333
334
|
| `get(pk)` | Busca um registro pela primary key |
|
|
334
335
|
| `getOrThrow(pk)` | Busca um registro pela primary key e lança erro se não encontrar |
|
|
335
336
|
| `save(obj)` | Cria ou atualiza (se o objeto passado tiver a `pk` faz `upsert`, se não faz `create`) |
|
|
337
|
+
| `patch(pk, obj)` | Atualiza parcialmente um registro pela primary key (equivalente ao `update` com payload parcial) |
|
|
336
338
|
| `remove(pk)` | Remove um registro pela primary key |
|
|
337
339
|
| `removeList(pks)` | Remove vários registros pela lista de primary keys — retorna `{ count }` |
|
|
338
340
|
| `getAll()` | Retorna todos os registros (aceita `pagination` e `order` no `options`) |
|
|
@@ -356,9 +358,13 @@ usuarioVSRepo.build(prisma, {
|
|
|
356
358
|
remove: {
|
|
357
359
|
active: true,
|
|
358
360
|
defaultSelect: "minimal",
|
|
361
|
+
ignoreRequiredWhere: false, // Aplica o requiredWhere no remove (padrão = false)
|
|
359
362
|
},
|
|
360
363
|
save: {
|
|
361
|
-
ignoreRequiredWhere: true,
|
|
364
|
+
ignoreRequiredWhere: true, // Não aplica requiredWhere no save
|
|
365
|
+
},
|
|
366
|
+
patch: {
|
|
367
|
+
defaultSelect: "minimal",
|
|
362
368
|
},
|
|
363
369
|
has: {
|
|
364
370
|
active: false, // Desativa o 'has' (padrão = true)
|
|
@@ -720,7 +726,7 @@ methods: {
|
|
|
720
726
|
|
|
721
727
|
## Relações no save
|
|
722
728
|
|
|
723
|
-
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`:
|
|
729
|
+
Configure relações para que o `save` as gerencie automaticamente. Essas mesmas relações também são usadas no `patch`. Para que as relações apareçam no autocomplete, o tipo genérico deve incluir as relações usando `GetPayload`:
|
|
724
730
|
|
|
725
731
|
```ts
|
|
726
732
|
import type { Prisma } from "../../generated/prisma/client";
|
|
@@ -742,12 +748,39 @@ const usuarioRepository = setupVSRepo<Usuario, "usuario">()({
|
|
|
742
748
|
postagens: {
|
|
743
749
|
pk: "id",
|
|
744
750
|
mode: "otm",
|
|
745
|
-
restriction: "
|
|
751
|
+
restriction: "add",
|
|
746
752
|
},
|
|
747
753
|
},
|
|
748
754
|
}).build(prisma);
|
|
749
755
|
```
|
|
750
756
|
|
|
757
|
+
Exemplos de uso com relações:
|
|
758
|
+
|
|
759
|
+
```ts
|
|
760
|
+
await usuarioRepository.save({
|
|
761
|
+
nome: "Maria",
|
|
762
|
+
email: "maria@email.com",
|
|
763
|
+
senha: "password",
|
|
764
|
+
perfil: {
|
|
765
|
+
id: 1,
|
|
766
|
+
bio: "Bio da Maria",
|
|
767
|
+
},
|
|
768
|
+
postagens: [
|
|
769
|
+
{ titulo: "Primeiro post", conteudo: "Olá!" },
|
|
770
|
+
],
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
await usuarioRepository.patch(1, {
|
|
774
|
+
perfil: {
|
|
775
|
+
id: 1,
|
|
776
|
+
bio: "Bio atualizada",
|
|
777
|
+
},
|
|
778
|
+
postagens: [
|
|
779
|
+
{ id: 10, titulo: "Post revisado", conteudo: "Conteúdo ajustado" },
|
|
780
|
+
],
|
|
781
|
+
});
|
|
782
|
+
```
|
|
783
|
+
|
|
751
784
|
> **Dica:** Se o tipo genérico não incluir `include: { relação: true }`, o VSRepository ainda funcionará, mas o autocomplete não sugerirá as relações no `save`. O tipo recomendado é sempre `GetPayload<{ include: { /* suas relações */ } }>` para melhor experiência de desenvolvimento.
|
|
752
785
|
|
|
753
786
|
**Modos de relação:**
|
|
@@ -773,23 +806,24 @@ const usuarioRepository = setupVSRepo<Usuario, "usuario">()({
|
|
|
773
806
|
Todos os métodos aceitam `options.db` para participar de uma transação:
|
|
774
807
|
|
|
775
808
|
```ts
|
|
776
|
-
await prisma.$transaction(async (tx) => {
|
|
809
|
+
await usuarioRepository.prisma.$transaction(async (tx) => {
|
|
777
810
|
const usuario = await usuarioRepository.save(
|
|
778
811
|
{ nome: "Maria", email: "maria@email.com", senha: "password" },
|
|
779
812
|
{ db: tx }
|
|
780
813
|
);
|
|
781
814
|
|
|
782
|
-
await
|
|
783
|
-
usuario.id,
|
|
784
|
-
{ ativo: true },
|
|
815
|
+
await usuarioLogsRepository.save(
|
|
816
|
+
{ acao: "Cadastro de usuário", data: { usuarioCadastrado: usuario.id } },
|
|
785
817
|
{ db: tx }
|
|
786
818
|
);
|
|
787
819
|
});
|
|
788
820
|
```
|
|
789
821
|
|
|
822
|
+
Observe que é possível diferentes repositories participarem da mesma transação.
|
|
823
|
+
|
|
790
824
|
---
|
|
791
825
|
|
|
792
|
-
##
|
|
826
|
+
## Estendendo um repository
|
|
793
827
|
|
|
794
828
|
```ts
|
|
795
829
|
const usuarioRepository = setupVSRepo<Usuario, "usuario">()({
|
|
@@ -1010,6 +1044,7 @@ vsRepo.build(prisma, {
|
|
|
1010
1044
|
getOrThrow?:{ active?: boolean; defaultSelect?: string; ignoreRequiredWhere?: boolean };
|
|
1011
1045
|
remove?: { active?: boolean; defaultSelect?: string; ignoreRequiredWhere?: boolean };
|
|
1012
1046
|
save?: { active?: boolean; defaultSelect?: string; ignoreRequiredWhere?: boolean };
|
|
1047
|
+
patch?: { active?: boolean; defaultSelect?: string; ignoreRequiredWhere?: boolean };
|
|
1013
1048
|
getAll?: { active?: boolean; defaultSelect?: string; ignoreRequiredWhere?: boolean };
|
|
1014
1049
|
|
|
1015
1050
|
// Métodos que NÃO aceitam `defaultSelect`
|
|
@@ -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();
|
|
@@ -372,6 +372,8 @@ export type BuildConfig<TSelectKeys extends PropertyKey = string> = {
|
|
|
372
372
|
remove?: BaseMethodConfig<TSelectKeys>;
|
|
373
373
|
/** Configuração do método `save`. */
|
|
374
374
|
save?: BaseMethodConfig<TSelectKeys>;
|
|
375
|
+
/** Configuração do método `patch`. */
|
|
376
|
+
patch?: BaseMethodConfig<TSelectKeys>;
|
|
375
377
|
/** Configuração do método `removeList` (exclusão em lote). Não aceita select. */
|
|
376
378
|
removeList?: Omit<BaseMethodConfig<TSelectKeys>, 'defaultSelect'>;
|
|
377
379
|
/** Configuração do método `getAll` (listagem total). */
|
|
@@ -383,7 +385,7 @@ export type BuildConfig<TSelectKeys extends PropertyKey = string> = {
|
|
|
383
385
|
};
|
|
384
386
|
};
|
|
385
387
|
|
|
386
|
-
type ResolveMethodDefaultSelect<Config, C, Method extends 'get' | 'getOrThrow' | 'remove' | 'save' | 'getAll', TSelects = ExtractSelectModels<Config>> =
|
|
388
|
+
type ResolveMethodDefaultSelect<Config, C, Method extends 'get' | 'getOrThrow' | 'remove' | 'save' | 'getAll' | 'patch', TSelects = ExtractSelectModels<Config>> =
|
|
387
389
|
C extends { baseMethods?: { [_ in Method]?: { defaultSelect?: infer D } } }
|
|
388
390
|
? D extends keyof TSelects
|
|
389
391
|
? D
|
|
@@ -483,6 +485,21 @@ type InjectedSave<
|
|
|
483
485
|
): Promise<RefineSaveResult<ResolveCurrentReturn<M, TSelects, S, TDefault>, O>>;
|
|
484
486
|
};
|
|
485
487
|
|
|
488
|
+
type InjectedPatch<
|
|
489
|
+
T, M extends Prisma.ModelName, Config, C extends BuildConfig<any> | undefined,
|
|
490
|
+
TSelects = ExtractSelectModels<Config>,
|
|
491
|
+
TDefault = ExtractDefaultSelect<Config>,
|
|
492
|
+
TPk = ExtractPkName<T, Config>,
|
|
493
|
+
I = PrismaModelInputs<M>
|
|
494
|
+
> = C extends { baseMethods: { patch: { active: false } } } ? {} : {
|
|
495
|
+
/** Atualiza parcialmente um registro existente através da sua chave primária (PK). */
|
|
496
|
+
patch<S extends keyof TSelects | false = ResolveMethodDefaultSelect<Config, C, 'patch', TSelects>>(
|
|
497
|
+
pk: T[TPk extends keyof T ? TPk : never],
|
|
498
|
+
obj: I extends { updateInput: infer U } ? U : Record<string, any>,
|
|
499
|
+
options?: MethodOptions<S>
|
|
500
|
+
): Promise<ResolveCurrentReturn<M, TSelects, S, TDefault>>;
|
|
501
|
+
};
|
|
502
|
+
|
|
486
503
|
type InjectedRemoveList<
|
|
487
504
|
T, M extends Prisma.ModelName, Config, C extends BuildConfig<any> | undefined,
|
|
488
505
|
TPk = ExtractPkName<T, Config>
|
|
@@ -532,6 +549,7 @@ type InjectedBaseMethods<T, M extends Prisma.ModelName, Config, C extends BuildC
|
|
|
532
549
|
InjectedGetOrThrow<T, M, Config, C> &
|
|
533
550
|
InjectedRemove<T, M, Config, C> &
|
|
534
551
|
InjectedSave<T, M, Config, C> &
|
|
552
|
+
InjectedPatch<T, M, Config, C> &
|
|
535
553
|
InjectedRemoveList<T, M, Config, C> &
|
|
536
554
|
InjectedGetAll<T, M, Config, C> &
|
|
537
555
|
InjectedTotal<T, M, Config, C> &
|
|
@@ -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
|
|
|
@@ -1059,138 +1055,287 @@ export class VSRepository {
|
|
|
1059
1055
|
console.log(`[VSRepository] (runtime) Fatal error when trying to save on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1060
1056
|
throw err;
|
|
1061
1057
|
}
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
if(config.baseMethods?.removeList?.active !== false) {
|
|
1061
|
+
buildInstance.removeList = async (pks, options = {}) => {
|
|
1062
|
+
let db = options?.db ?? prisma;
|
|
1063
|
+
const prismaArgs = {};
|
|
1064
|
+
|
|
1065
|
+
const where = { [buildInstance.pkName]: { in: pks } };
|
|
1066
|
+
if(buildInstance.requiredWhere && !config.baseMethods?.removeList?.ignoreRequiredWhere) {
|
|
1067
|
+
Object.assign(where, buildInstance.requiredWhere);
|
|
1068
|
+
}
|
|
1069
|
+
prismaArgs.where = where;
|
|
1073
1070
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
}
|
|
1086
|
-
return result;
|
|
1087
|
-
} catch (err) {
|
|
1088
|
-
console.log(`[VSRepository] (runtime) Fatal error when trying to removeList on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1089
|
-
throw err;
|
|
1071
|
+
let start;
|
|
1072
|
+
if(showWorking){
|
|
1073
|
+
console.log(`[VSRepository] (runtime) Executing removeList on ${buildInstance.tableName}.`);
|
|
1074
|
+
console.log(`[VSRepository] (runtime) Built arguments to removeList on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1075
|
+
start = performance.now();
|
|
1076
|
+
}
|
|
1077
|
+
try {
|
|
1078
|
+
const result = await db[buildInstance.tableName].deleteMany(prismaArgs);
|
|
1079
|
+
if(showWorking) {
|
|
1080
|
+
const end = performance.now();
|
|
1081
|
+
console.log(`[VSRepository] (runtime) Executed removeList on ${buildInstance.tableName} (took: ${(end - start).toFixed(2)}ms).`);
|
|
1090
1082
|
}
|
|
1083
|
+
return result;
|
|
1084
|
+
} catch (err) {
|
|
1085
|
+
console.log(`[VSRepository] (runtime) Fatal error when trying to removeList on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1086
|
+
throw err;
|
|
1091
1087
|
}
|
|
1092
1088
|
}
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1089
|
+
}
|
|
1090
|
+
if(config.baseMethods?.getAll?.active !== false) {
|
|
1091
|
+
buildInstance.getAll = async (options = {}) => {
|
|
1092
|
+
let db = options?.db ?? prisma;
|
|
1093
|
+
const prismaArgs = {};
|
|
1097
1094
|
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1095
|
+
if(buildInstance.requiredWhere && !config.baseMethods?.getAll?.ignoreRequiredWhere) {
|
|
1096
|
+
prismaArgs.where = { ...buildInstance.requiredWhere };
|
|
1097
|
+
}
|
|
1101
1098
|
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1099
|
+
let selectModelKey = options?.selectModel ?? config.baseMethods?.getAll?.defaultSelect ?? buildInstance.defaultSelectModel;
|
|
1100
|
+
if(selectModelKey){
|
|
1101
|
+
prismaArgs.select = buildInstance.selectModels[selectModelKey];
|
|
1102
|
+
}
|
|
1106
1103
|
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1104
|
+
if(options.pagination) {
|
|
1105
|
+
prismaArgs.skip = options.pagination.skip;
|
|
1106
|
+
prismaArgs.take = options.pagination.take;
|
|
1107
|
+
prismaArgs.cursor = options.pagination.cursor;
|
|
1108
|
+
}
|
|
1109
|
+
if(options.order) {
|
|
1110
|
+
prismaArgs.orderBy = options.order;
|
|
1111
|
+
}
|
|
1115
1112
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
}
|
|
1128
|
-
return result;
|
|
1129
|
-
} catch (err) {
|
|
1130
|
-
console.log(`[VSRepository] (runtime) Fatal error when trying to getAll on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1131
|
-
throw err;
|
|
1113
|
+
let start;
|
|
1114
|
+
if(showWorking){
|
|
1115
|
+
console.log(`[VSRepository] (runtime) Executing getAll on ${buildInstance.tableName}.`);
|
|
1116
|
+
console.log(`[VSRepository] (runtime) Built arguments to getAll on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1117
|
+
start = performance.now();
|
|
1118
|
+
}
|
|
1119
|
+
try {
|
|
1120
|
+
const result = await db[buildInstance.tableName].findMany(prismaArgs);
|
|
1121
|
+
if(showWorking) {
|
|
1122
|
+
const end = performance.now();
|
|
1123
|
+
console.log(`[VSRepository] (runtime) Executed getAll on ${buildInstance.tableName} (took: ${(end - start).toFixed(2)}ms).`);
|
|
1132
1124
|
}
|
|
1125
|
+
return result;
|
|
1126
|
+
} catch (err) {
|
|
1127
|
+
console.log(`[VSRepository] (runtime) Fatal error when trying to getAll on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1128
|
+
throw err;
|
|
1133
1129
|
}
|
|
1134
1130
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1131
|
+
}
|
|
1132
|
+
if(config.baseMethods?.total?.active !== false) {
|
|
1133
|
+
buildInstance.total = async (options = {}) => {
|
|
1134
|
+
let db = options?.db ?? prisma;
|
|
1135
|
+
const prismaArgs = {};
|
|
1139
1136
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1137
|
+
if(buildInstance.requiredWhere && !config.baseMethods?.total?.ignoreRequiredWhere) {
|
|
1138
|
+
prismaArgs.where = { ...buildInstance.requiredWhere };
|
|
1139
|
+
}
|
|
1143
1140
|
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1141
|
+
let start;
|
|
1142
|
+
if(showWorking){
|
|
1143
|
+
console.log(`[VSRepository] (runtime) Executing total on ${buildInstance.tableName}.`);
|
|
1144
|
+
console.log(`[VSRepository] (runtime) Built arguments to total on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1145
|
+
start = performance.now();
|
|
1146
|
+
}
|
|
1147
|
+
try {
|
|
1148
|
+
const result = await db[buildInstance.tableName].count(prismaArgs);
|
|
1149
|
+
if(showWorking) {
|
|
1150
|
+
const end = performance.now();
|
|
1151
|
+
console.log(`[VSRepository] (runtime) Executed total on ${buildInstance.tableName} (took: ${(end - start).toFixed(2)}ms).`);
|
|
1149
1152
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1153
|
+
return result;
|
|
1154
|
+
} catch (err) {
|
|
1155
|
+
console.log(`[VSRepository] (runtime) Fatal error when trying to total on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1156
|
+
throw err;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
if(config.baseMethods?.has?.active !== false) {
|
|
1161
|
+
buildInstance.has = async (pk, options = {}) => {
|
|
1162
|
+
let db = options?.db ?? prisma;
|
|
1163
|
+
const prismaArgs = {};
|
|
1164
|
+
|
|
1165
|
+
const where = { [buildInstance.pkName]: pk };
|
|
1166
|
+
if(buildInstance.requiredWhere && !config.baseMethods?.has?.ignoreRequiredWhere) {
|
|
1167
|
+
Object.assign(where, buildInstance.requiredWhere);
|
|
1168
|
+
}
|
|
1169
|
+
prismaArgs.where = where;
|
|
1170
|
+
prismaArgs.select = { [buildInstance.pkName]: true };
|
|
1171
|
+
|
|
1172
|
+
let start;
|
|
1173
|
+
if(showWorking){
|
|
1174
|
+
console.log(`[VSRepository] (runtime) Executing has on ${buildInstance.tableName}.`);
|
|
1175
|
+
console.log(`[VSRepository] (runtime) Built arguments to has on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1176
|
+
start = performance.now();
|
|
1177
|
+
}
|
|
1178
|
+
try {
|
|
1179
|
+
const result = await db[buildInstance.tableName].findUnique(prismaArgs);
|
|
1180
|
+
if(showWorking) {
|
|
1181
|
+
const end = performance.now();
|
|
1182
|
+
console.log(`[VSRepository] (runtime) Executed has on ${buildInstance.tableName} (took: ${(end - start).toFixed(2)}ms).`);
|
|
1160
1183
|
}
|
|
1184
|
+
return !!result;
|
|
1185
|
+
} catch (err) {
|
|
1186
|
+
console.log(`[VSRepository] (runtime) Fatal error when trying to has on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1187
|
+
throw err;
|
|
1161
1188
|
}
|
|
1162
1189
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1190
|
+
}
|
|
1191
|
+
if(config.baseMethods?.patch?.active !== false) {
|
|
1192
|
+
buildInstance.patch = async (pk, obj, options = {}) => {
|
|
1193
|
+
let db = options?.db ?? prisma;
|
|
1194
|
+
const prismaArgs = {};
|
|
1195
|
+
|
|
1196
|
+
let selectModelKey = options?.selectModel ?? config.baseMethods?.patch?.defaultSelect ?? buildInstance.defaultSelectModel;
|
|
1197
|
+
if(selectModelKey){
|
|
1198
|
+
prismaArgs.select = buildInstance.selectModels[selectModelKey];
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
let start;
|
|
1202
|
+
if(showWorking){
|
|
1203
|
+
console.log(`[VSRepository] (runtime) Executing patch on ${buildInstance.tableName}.`);
|
|
1204
|
+
start = performance.now();
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
try {
|
|
1208
|
+
let result;
|
|
1209
|
+
prismaArgs.data = {};
|
|
1210
|
+
|
|
1211
|
+
const keys = Object.keys(obj);
|
|
1212
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1213
|
+
const key = keys[i];
|
|
1214
|
+
const field = obj[key];
|
|
1215
|
+
|
|
1216
|
+
if(field === undefined) continue;
|
|
1217
|
+
|
|
1218
|
+
if(relationsKeys.includes(key)){
|
|
1219
|
+
const relation = buildInstance.relations[key];
|
|
1220
|
+
const relationMode = relation.mode;
|
|
1221
|
+
const relationRestriction = relation.restriction;
|
|
1222
|
+
const relationPk = relation.pk;
|
|
1223
|
+
|
|
1224
|
+
if(relationMode === 'oto' || relationMode === 'mto') {
|
|
1225
|
+
if(field === null) {
|
|
1226
|
+
if(relationMode === 'oto' && relationRestriction === 'set') {
|
|
1227
|
+
prismaArgs.data[key] = { delete: true };
|
|
1228
|
+
} else if(relationMode === 'mto' && relation.nullAble) {
|
|
1229
|
+
prismaArgs.data[key] = { disconnect: true };
|
|
1230
|
+
}
|
|
1231
|
+
} else if (field !== undefined) {
|
|
1232
|
+
const relationFieldPk = field[relationPk];
|
|
1233
|
+
if(relationFieldPk){
|
|
1234
|
+
const connectOrCreate = {
|
|
1235
|
+
where: { [relationPk]: relationFieldPk },
|
|
1236
|
+
create: field
|
|
1237
|
+
};
|
|
1238
|
+
|
|
1239
|
+
if(relationRestriction === 'add') {
|
|
1240
|
+
prismaArgs.data[key] = { connectOrCreate };
|
|
1241
|
+
} else {
|
|
1242
|
+
const update = {...field};
|
|
1243
|
+
delete update[relationPk];
|
|
1244
|
+
|
|
1245
|
+
prismaArgs.data[key] = {
|
|
1246
|
+
upsert: {
|
|
1247
|
+
where: { [relationPk]: relationFieldPk },
|
|
1248
|
+
create: field,
|
|
1249
|
+
update: update
|
|
1250
|
+
}
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
} else {
|
|
1254
|
+
prismaArgs.data[key] = { create: field };
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
} else if(Array.isArray(field)) {
|
|
1258
|
+
const dataWithPk = field.filter(data=>data[relationPk]!==undefined);
|
|
1259
|
+
const dataWithoutPk = field.filter(data=>data[relationPk]===undefined);
|
|
1260
|
+
|
|
1261
|
+
const connectOrCreate = dataWithPk.map(data=>({
|
|
1262
|
+
where: { [relationPk]: data[relationPk] },
|
|
1263
|
+
create: data
|
|
1264
|
+
}));
|
|
1265
|
+
|
|
1266
|
+
if(relationRestriction === 'add') {
|
|
1267
|
+
if(relationMode === 'mtm') {
|
|
1268
|
+
prismaArgs.data[key] = {
|
|
1269
|
+
create: dataWithoutPk,
|
|
1270
|
+
connectOrCreate
|
|
1271
|
+
}
|
|
1272
|
+
} else {
|
|
1273
|
+
prismaArgs.data[key] = {
|
|
1274
|
+
create: dataWithoutPk,
|
|
1275
|
+
upsert: dataWithPk.map(data=>{
|
|
1276
|
+
const update = { ...data };
|
|
1277
|
+
delete update[relationPk];
|
|
1278
|
+
return {
|
|
1279
|
+
where: { [relationPk]: data[relationPk] },
|
|
1280
|
+
create: data, update
|
|
1281
|
+
}
|
|
1282
|
+
})
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
} else {
|
|
1286
|
+
if(relationMode === 'mtm') {
|
|
1287
|
+
prismaArgs.data[key] = {
|
|
1288
|
+
set: [],
|
|
1289
|
+
create: dataWithoutPk,
|
|
1290
|
+
connectOrCreate
|
|
1291
|
+
}
|
|
1292
|
+
} else {
|
|
1293
|
+
prismaArgs.data[key] = {
|
|
1294
|
+
deleteMany: { [relationPk]: { notIn: dataWithPk.map(data=>data[relationPk]) } },
|
|
1295
|
+
create: dataWithoutPk,
|
|
1296
|
+
upsert: dataWithPk.map(data=>{
|
|
1297
|
+
const update = { ...data };
|
|
1298
|
+
delete update[relationPk];
|
|
1299
|
+
return {
|
|
1300
|
+
where: { [relationPk]: data[relationPk] },
|
|
1301
|
+
create: data, update
|
|
1302
|
+
}
|
|
1303
|
+
})
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
} else {
|
|
1309
|
+
if (key !== buildInstance.pkName) {
|
|
1310
|
+
prismaArgs.data[key] = field;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1168
1315
|
const where = { [buildInstance.pkName]: pk };
|
|
1169
|
-
if(buildInstance.requiredWhere && !config.baseMethods?.
|
|
1316
|
+
if(buildInstance.requiredWhere && !config.baseMethods?.patch?.ignoreRequiredWhere) {
|
|
1170
1317
|
Object.assign(where, buildInstance.requiredWhere);
|
|
1171
1318
|
}
|
|
1172
1319
|
prismaArgs.where = where;
|
|
1173
|
-
prismaArgs.select = { [buildInstance.pkName]: true };
|
|
1174
1320
|
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
console.log(`[VSRepository] (runtime) Executing has on ${buildInstance.tableName}.`);
|
|
1178
|
-
console.log(`[VSRepository] (runtime) Built arguments to has on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1179
|
-
start = performance.now();
|
|
1321
|
+
if(showWorking) {
|
|
1322
|
+
console.log(`[VSRepository] (runtime) Built arguments to patch on ${buildInstance.tableName}:\n`, JSON.stringify(prismaArgs, null, 2));
|
|
1180
1323
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
} catch (err) {
|
|
1189
|
-
console.log(`[VSRepository] (runtime) Fatal error when trying to has on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1190
|
-
throw err;
|
|
1324
|
+
|
|
1325
|
+
result = await db[buildInstance.tableName].update(prismaArgs);
|
|
1326
|
+
|
|
1327
|
+
if(showWorking) {
|
|
1328
|
+
const end = performance.now();
|
|
1329
|
+
const duration = (end - start).toFixed(2);
|
|
1330
|
+
console.log(`[VSRepository] (runtime) Executed patch on ${buildInstance.tableName} (took: ${duration}ms).`);
|
|
1191
1331
|
}
|
|
1332
|
+
|
|
1333
|
+
return result;
|
|
1334
|
+
} catch (err) {
|
|
1335
|
+
console.log(`[VSRepository] (runtime) Fatal error when trying to patch on ${buildInstance.tableName}:\n`, JSON.stringify({ prismaArgs }, null, 2));
|
|
1336
|
+
throw err;
|
|
1192
1337
|
}
|
|
1193
|
-
}
|
|
1338
|
+
}
|
|
1194
1339
|
}
|
|
1195
1340
|
|
|
1196
1341
|
buildInstance.prisma = prisma;
|