@vsrepo/prisma7-adapter 1.0.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/README.pt-BR.md +233 -0
  4. package/dist/index.d.ts +6 -0
  5. package/dist/index.js +5 -0
  6. package/dist/parsers/data.parser.d.ts +34 -0
  7. package/dist/parsers/data.parser.js +134 -0
  8. package/dist/parsers/include.parser.d.ts +3 -0
  9. package/dist/parsers/include.parser.js +16 -0
  10. package/dist/parsers/order-by.parser.d.ts +15 -0
  11. package/dist/parsers/order-by.parser.js +38 -0
  12. package/dist/parsers/select.parser.d.ts +3 -0
  13. package/dist/parsers/select.parser.js +16 -0
  14. package/dist/parsers/where.parser.d.ts +31 -0
  15. package/dist/parsers/where.parser.js +187 -0
  16. package/dist/prisma7.adapter.d.ts +125 -0
  17. package/dist/prisma7.adapter.js +505 -0
  18. package/dist/resolvers/map-prisma-error.resolver.d.ts +13 -0
  19. package/dist/resolvers/map-prisma-error.resolver.js +100 -0
  20. package/dist/resolvers/merge-entities.resolver.d.ts +19 -0
  21. package/dist/resolvers/merge-entities.resolver.js +73 -0
  22. package/dist/types/adapter-config.type.d.ts +22 -0
  23. package/dist/types/adapter-config.type.js +2 -0
  24. package/dist/types/adapter-relations.type.d.ts +16 -0
  25. package/dist/types/adapter-relations.type.js +2 -0
  26. package/dist/types/plain-object.type.d.ts +1 -0
  27. package/dist/types/plain-object.type.js +2 -0
  28. package/dist/types/prisma-arg-like.type.d.ts +14 -0
  29. package/dist/types/prisma-arg-like.type.js +2 -0
  30. package/dist/types/prisma-repository-like.type.d.ts +20 -0
  31. package/dist/types/prisma-repository-like.type.js +2 -0
  32. package/dist/types/prisma7-client-like.type.d.ts +19 -0
  33. package/dist/types/prisma7-client-like.type.js +2 -0
  34. package/dist/types/prisma7-orm-types.type.d.ts +19 -0
  35. package/dist/types/prisma7-orm-types.type.js +2 -0
  36. package/dist/types/relation.type.d.ts +26 -0
  37. package/dist/types/relation.type.js +2 -0
  38. package/dist/validators/adapter-config.schema.d.ts +13 -0
  39. package/dist/validators/adapter-config.schema.js +45 -0
  40. package/dist/validators/is-decimal.validator.d.ts +5 -0
  41. package/dist/validators/is-decimal.validator.js +10 -0
  42. package/dist/validators/is-plain-object.validator.d.ts +2 -0
  43. package/dist/validators/is-plain-object.validator.js +11 -0
  44. package/dist/validators/relation.schema.d.ts +8 -0
  45. package/dist/validators/relation.schema.js +44 -0
  46. package/dist/validators/validate-adapter-config.validator.d.ts +8 -0
  47. package/dist/validators/validate-adapter-config.validator.js +54 -0
  48. package/package.json +84 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * Parser que converte um `DeepPartial<T>` (formato "cru" vindo do vsrepo) nos
4
+ * payloads `create`/`update` esperados pelo Prisma para escritas com relations,
5
+ * replicando o comportamento da v1 (`resolveCreateUpdatePayloadsWithRelations`).
6
+ *
7
+ * Sem `relations` configurado no adapter, cada campo é repassado como está —
8
+ * exceto `pkName`, que é omitido do `update` (não faz sentido reatribuir a PK
9
+ * num update parcial).
10
+ *
11
+ * Com `relations`, cada campo de relação é resolvido de acordo com seu `mode`/
12
+ * `restriction` (ver `Relation`):
13
+ * - to-one (`oto`/`mto`) sem PK no valor enviado -> `create` (e `upsert` no
14
+ * update, a não ser que `restriction: "add"`, que usa só `create`)
15
+ * - to-one com PK no valor enviado -> `connectOrCreate` (e
16
+ * `upsert` no update, a não ser que `restriction: "add"`)
17
+ * - to-one enviado como `null` -> `delete` (`oto` +
18
+ * `restriction: "set"`) ou `disconnect` (`mto` + `nullable`)
19
+ * - to-many (`otm`/`mtm`) — itens são separados entre "com PK" e "sem PK":
20
+ * os sem PK viram `create`, os com PK viram `connectOrCreate` no create e
21
+ * `upsert` no update; com `restriction: "set"`, itens de `otm` que não
22
+ * vieram no array são removidos (`deleteMany`) e itens de `mtm` têm o
23
+ * vínculo resetado (`set: []`) antes de reconectar
24
+ *
25
+ * Essa mesma saída `{ create, update }` é reaproveitada em todos os métodos de
26
+ * escrita do adapter: `create()` usa só `.create`, `update()`/`updateMany()`
27
+ * usam só `.update`, e `save()`/`upsert()` usam os dois.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.parsePrismaWriteData = parsePrismaWriteData;
31
+ function omitKey(item, key) {
32
+ const clone = { ...item };
33
+ delete clone[key];
34
+ return clone;
35
+ }
36
+ function splitByPk(items, pk) {
37
+ const withPk = [];
38
+ const withoutPk = [];
39
+ for (const item of items) {
40
+ (item[pk] !== undefined ? withPk : withoutPk).push(item);
41
+ }
42
+ return { withPk, withoutPk };
43
+ }
44
+ function parseToOneRelation(field, relation) {
45
+ if (field === null) {
46
+ if (relation.mode === "oto" && relation.restriction === "set") {
47
+ return { update: { delete: true } };
48
+ }
49
+ if (relation.mode === "mto" && relation.nullable) {
50
+ return { update: { disconnect: true } };
51
+ }
52
+ return {};
53
+ }
54
+ const pkValue = field[relation.pk];
55
+ if (pkValue == null) {
56
+ return {
57
+ create: { create: field },
58
+ update: relation.restriction === "add"
59
+ ? { create: field }
60
+ : { upsert: { create: field, update: field } },
61
+ };
62
+ }
63
+ const connectOrCreate = { where: { [relation.pk]: pkValue }, create: field };
64
+ return {
65
+ create: { connectOrCreate },
66
+ update: relation.restriction === "add"
67
+ ? { connectOrCreate }
68
+ : {
69
+ upsert: {
70
+ where: { [relation.pk]: pkValue },
71
+ create: field,
72
+ update: omitKey(field, relation.pk),
73
+ },
74
+ },
75
+ };
76
+ }
77
+ function parseToManyRelation(field, relation) {
78
+ const { withPk, withoutPk } = splitByPk(field, relation.pk);
79
+ const connectOrCreate = withPk.map(item => ({
80
+ where: { [relation.pk]: item[relation.pk] },
81
+ create: item,
82
+ }));
83
+ const upsert = withPk.map(item => ({
84
+ where: { [relation.pk]: item[relation.pk] },
85
+ create: item,
86
+ update: omitKey(item, relation.pk),
87
+ }));
88
+ const create = { create: withoutPk, connectOrCreate };
89
+ if (relation.restriction === "add") {
90
+ return {
91
+ create,
92
+ update: relation.mode === "mtm"
93
+ ? { create: withoutPk, connectOrCreate }
94
+ : { create: withoutPk, upsert },
95
+ };
96
+ }
97
+ return {
98
+ create,
99
+ update: relation.mode === "mtm"
100
+ ? { set: [], create: withoutPk, connectOrCreate }
101
+ : {
102
+ deleteMany: { [relation.pk]: { notIn: withPk.map(item => item[relation.pk]) } },
103
+ create: withoutPk,
104
+ upsert,
105
+ },
106
+ };
107
+ }
108
+ function parsePrismaWriteData(obj, pkName, relations) {
109
+ const create = {};
110
+ const update = {};
111
+ for (const [key, field] of Object.entries(obj)) {
112
+ if (field === undefined)
113
+ continue;
114
+ const relation = relations?.[key];
115
+ if (!relation) {
116
+ create[key] = field;
117
+ if (key !== pkName)
118
+ update[key] = field;
119
+ continue;
120
+ }
121
+ if (relation.mode === "oto" || relation.mode === "mto") {
122
+ const parsed = parseToOneRelation(field, relation);
123
+ if (parsed.create !== undefined)
124
+ create[key] = parsed.create;
125
+ if (parsed.update !== undefined)
126
+ update[key] = parsed.update;
127
+ continue;
128
+ }
129
+ const parsed = parseToManyRelation(field, relation);
130
+ create[key] = parsed.create;
131
+ update[key] = parsed.update;
132
+ }
133
+ return { create, update };
134
+ }
@@ -0,0 +1,3 @@
1
+ import { VSRepoRelations } from "vsrepo";
2
+ import { PlainObject } from "../types/plain-object.type";
3
+ export declare function parsePrismaInclude<T>(relations: VSRepoRelations<T>): PlainObject;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePrismaInclude = parsePrismaInclude;
4
+ const is_plain_object_validator_1 = require("../validators/is-plain-object.validator");
5
+ function parsePrismaInclude(relations) {
6
+ const include = {};
7
+ for (const [key, value] of Object.entries(relations)) {
8
+ if ((0, is_plain_object_validator_1.isPlainObject)(value)) {
9
+ include[key] = { include: parsePrismaInclude(value) };
10
+ }
11
+ else {
12
+ include[key] = value;
13
+ }
14
+ }
15
+ return include;
16
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Parser que converte um `Ordering<T>` (formato "amigável" do vsrepo) num
3
+ * `orderBy` válido de qualquer modelo do Prisma.
4
+ *
5
+ * Suporta:
6
+ * - Direção em qualquer caixa: { name: "ASC" } / { name: "asc" } -> { name: "asc" }
7
+ * - Ordenação encadeada: [{ name: "asc" }, { createdAt: "desc" }]
8
+ * - Ordenação aninhada em relations to-one: { address: { city: "asc" } }
9
+ */
10
+ import { Ordering } from "vsrepo";
11
+ /**
12
+ * Use o segundo generic para tipar o retorno com o `OrderByInput`
13
+ * do Prisma correspondente ao modelo.
14
+ */
15
+ export declare function parsePrismaOrderBy<T, O = any>(order: Ordering<T> | undefined | null): O | undefined;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ /**
3
+ * Parser que converte um `Ordering<T>` (formato "amigável" do vsrepo) num
4
+ * `orderBy` válido de qualquer modelo do Prisma.
5
+ *
6
+ * Suporta:
7
+ * - Direção em qualquer caixa: { name: "ASC" } / { name: "asc" } -> { name: "asc" }
8
+ * - Ordenação encadeada: [{ name: "asc" }, { createdAt: "desc" }]
9
+ * - Ordenação aninhada em relations to-one: { address: { city: "asc" } }
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.parsePrismaOrderBy = parsePrismaOrderBy;
13
+ const is_plain_object_validator_1 = require("../validators/is-plain-object.validator");
14
+ function isSortDirection(value) {
15
+ return value === "asc" || value === "desc" || value === "ASC" || value === "DESC";
16
+ }
17
+ function parseOrderByField(order) {
18
+ const result = {};
19
+ for (const [key, value] of Object.entries(order)) {
20
+ if (value === undefined)
21
+ continue;
22
+ result[key] = isSortDirection(value)
23
+ ? value.toLowerCase()
24
+ : (0, is_plain_object_validator_1.isPlainObject)(value)
25
+ ? parseOrderByField(value)
26
+ : value;
27
+ }
28
+ return result;
29
+ }
30
+ /**
31
+ * Use o segundo generic para tipar o retorno com o `OrderByInput`
32
+ * do Prisma correspondente ao modelo.
33
+ */
34
+ function parsePrismaOrderBy(order) {
35
+ if (order === undefined || order === null)
36
+ return undefined;
37
+ return (Array.isArray(order) ? order.map(o => parseOrderByField(o)) : parseOrderByField(order));
38
+ }
@@ -0,0 +1,3 @@
1
+ import { VSRepoSelect } from "vsrepo";
2
+ import { PlainObject } from "../types/plain-object.type";
3
+ export declare function parsePrismaSelect<T>(relations: VSRepoSelect<T>): PlainObject;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePrismaSelect = parsePrismaSelect;
4
+ const is_plain_object_validator_1 = require("../validators/is-plain-object.validator");
5
+ function parsePrismaSelect(relations) {
6
+ const select = {};
7
+ for (const [key, value] of Object.entries(relations)) {
8
+ if ((0, is_plain_object_validator_1.isPlainObject)(value)) {
9
+ select[key] = { select: parsePrismaSelect(value) };
10
+ }
11
+ else {
12
+ select[key] = value;
13
+ }
14
+ }
15
+ return select;
16
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Parser que converte um `VSRepoWhere<T>` (formato "amigável" da aplicação)
3
+ * em um `where` válido de qualquer modelo do Prisma.
4
+ *
5
+ * Suporta:
6
+ * - Valor direto: { name: "Ana" }
7
+ * - Operadores de campo: { age: { gte: 18, lte: 65 } }
8
+ * - `between`: { age: { between: [18, 65] } } -> { gte: 18, lte: 65 }
9
+ * - `not` (valor ou operador): { name: { not: "Ana" } }
10
+ * { name: { not: { contains: "an" } } }
11
+ * - Strings case-insensitive: { name: { contains: "ana", ignoreCase: true } }
12
+ * -> { contains: "ana", mode: "insensitive" }
13
+ * - Relação lista (array): { posts: { _some: { title: "x" } } } -> { posts: { some: {...} } }
14
+ * - Relação objeto (to-one): { author: { _with: { id: 1 } } } -> { author: { is: {...} } }
15
+ * { author: { _without: { id: 1 } } } -> { author: { isNot: {...} } }
16
+ * - Lógicos no nível raiz: { AND: [...] , OR: [...], NOT: {...} }
17
+ *
18
+ * Reflete a tipagem atual: `AND`/`OR`/`NOT` só existem em `VSRepoWhere<T>`
19
+ * (nível raiz). Dentro de relações (`_some`/`_every`/`_none`/`_with`/
20
+ * `_without`), o tipo usado é `VSRepoWherePlain<U>`, que NÃO tem esses
21
+ * operadores lógicos — por isso a recursão para relações usa
22
+ * `parsePlainWhere`, e não `parseWhere`.
23
+ */
24
+ import { VSRepoWhere } from "vsrepo";
25
+ /**
26
+ * API pública. Use o segundo generic para tipar o retorno com o `WhereInput`
27
+ * do Prisma correspondente ao modelo, ex:
28
+ *
29
+ * parseVSRepoWhere<User, Prisma.UserWhereInput>(where)
30
+ */
31
+ export declare function parsePrismaWhere<T, W = any>(where: VSRepoWhere<T> | undefined | null): W | undefined;
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ /**
3
+ * Parser que converte um `VSRepoWhere<T>` (formato "amigável" da aplicação)
4
+ * em um `where` válido de qualquer modelo do Prisma.
5
+ *
6
+ * Suporta:
7
+ * - Valor direto: { name: "Ana" }
8
+ * - Operadores de campo: { age: { gte: 18, lte: 65 } }
9
+ * - `between`: { age: { between: [18, 65] } } -> { gte: 18, lte: 65 }
10
+ * - `not` (valor ou operador): { name: { not: "Ana" } }
11
+ * { name: { not: { contains: "an" } } }
12
+ * - Strings case-insensitive: { name: { contains: "ana", ignoreCase: true } }
13
+ * -> { contains: "ana", mode: "insensitive" }
14
+ * - Relação lista (array): { posts: { _some: { title: "x" } } } -> { posts: { some: {...} } }
15
+ * - Relação objeto (to-one): { author: { _with: { id: 1 } } } -> { author: { is: {...} } }
16
+ * { author: { _without: { id: 1 } } } -> { author: { isNot: {...} } }
17
+ * - Lógicos no nível raiz: { AND: [...] , OR: [...], NOT: {...} }
18
+ *
19
+ * Reflete a tipagem atual: `AND`/`OR`/`NOT` só existem em `VSRepoWhere<T>`
20
+ * (nível raiz). Dentro de relações (`_some`/`_every`/`_none`/`_with`/
21
+ * `_without`), o tipo usado é `VSRepoWherePlain<U>`, que NÃO tem esses
22
+ * operadores lógicos — por isso a recursão para relações usa
23
+ * `parsePlainWhere`, e não `parseWhere`.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.parsePrismaWhere = parsePrismaWhere;
27
+ const is_decimal_validator_1 = require("../validators/is-decimal.validator");
28
+ const is_plain_object_validator_1 = require("../validators/is-plain-object.validator");
29
+ /** Chaves reconhecidas como operadores de campo do VSRepoFieldOperators */
30
+ const FIELD_OPERATOR_KEYS = new Set([
31
+ "equals",
32
+ "not",
33
+ "in",
34
+ "notIn",
35
+ "gt",
36
+ "gte",
37
+ "lt",
38
+ "lte",
39
+ "between",
40
+ "contains",
41
+ "startsWith",
42
+ "endsWith",
43
+ "ignoreCase",
44
+ ]);
45
+ /** Chaves de operadores de string que aceitam `mode: 'insensitive'` no Prisma */
46
+ const CASE_SENSITIVE_STRING_KEYS = ["equals", "contains", "startsWith", "endsWith"];
47
+ const LOGICAL_KEYS = new Set(["AND", "OR", "NOT"]);
48
+ /** Verifica se um objeto "parece" um VSRepoFieldOperators (e não um filtro de relação/nested where) */
49
+ function isFieldOperatorObject(value) {
50
+ return Object.keys(value).some(key => FIELD_OPERATOR_KEYS.has(key));
51
+ }
52
+ function isArrayRelationFilter(value) {
53
+ return "_some" in value || "_every" in value || "_none" in value;
54
+ }
55
+ function isObjectRelationFilter(value) {
56
+ return "_with" in value || "_without" in value;
57
+ }
58
+ /**
59
+ * Converte um VSRepoFieldOperators<V> em um filtro de campo do Prisma.
60
+ */
61
+ function parseFieldOperators(value) {
62
+ const result = {};
63
+ const ignoreCase = value.ignoreCase === true;
64
+ for (const [key, val] of Object.entries(value)) {
65
+ if (val === undefined)
66
+ continue;
67
+ switch (key) {
68
+ case "ignoreCase":
69
+ // tratado à parte, no final (vira `mode`)
70
+ break;
71
+ case "between": {
72
+ const [min, max] = val;
73
+ if (min !== undefined)
74
+ result.gte = min;
75
+ if (max !== undefined)
76
+ result.lte = max;
77
+ break;
78
+ }
79
+ case "not": {
80
+ result.not =
81
+ (0, is_plain_object_validator_1.isPlainObject)(val) && isFieldOperatorObject(val)
82
+ ? parseFieldOperators(val)
83
+ : val;
84
+ break;
85
+ }
86
+ default:
87
+ result[key] = val;
88
+ }
89
+ }
90
+ if (ignoreCase) {
91
+ const hasCaseSensitiveKey = CASE_SENSITIVE_STRING_KEYS.some(k => k in result);
92
+ if (hasCaseSensitiveKey) {
93
+ result.mode = "insensitive";
94
+ }
95
+ }
96
+ return result;
97
+ }
98
+ /** Converte { _some, _every, _none } em { some, every, none } (VSRepoWherePlain — sem AND/OR/NOT) */
99
+ function parseArrayRelationFilter(value) {
100
+ const result = {};
101
+ if (value._some !== undefined) {
102
+ result.some = parsePlainWhere(value._some);
103
+ }
104
+ if (value._every !== undefined) {
105
+ result.every = parsePlainWhere(value._every);
106
+ }
107
+ if (value._none !== undefined) {
108
+ result.none = parsePlainWhere(value._none);
109
+ }
110
+ return result;
111
+ }
112
+ /** Converte { _with, _without } em { is, isNot } (VSRepoWherePlain — sem AND/OR/NOT) */
113
+ function parseObjectRelationFilter(value) {
114
+ if (value._with !== undefined) {
115
+ return { is: parsePlainWhere(value._with) };
116
+ }
117
+ if (value._without !== undefined) {
118
+ return { isNot: parsePlainWhere(value._without) };
119
+ }
120
+ return {};
121
+ }
122
+ /** Decide como interpretar o valor de um campo do where */
123
+ function parseFieldValue(value) {
124
+ // valores primitivos (string, number, boolean, Date, null, bigint, Decimal) passam direto
125
+ if (value === null || typeof value !== "object" || value instanceof Date || (0, is_decimal_validator_1.isDecimal)(value)) {
126
+ return value;
127
+ }
128
+ // arrays (usados em `in`/`notIn` no nível mais alto, ex: { status: ["A","B"] })
129
+ if (Array.isArray(value)) {
130
+ return value;
131
+ }
132
+ const obj = value;
133
+ if (isArrayRelationFilter(obj)) {
134
+ return parseArrayRelationFilter(obj);
135
+ }
136
+ if (isObjectRelationFilter(obj)) {
137
+ return parseObjectRelationFilter(obj);
138
+ }
139
+ if (isFieldOperatorObject(obj)) {
140
+ return parseFieldOperators(obj);
141
+ }
142
+ // fallback: nested where (não deveria ocorrer para campos primitivos bem tipados)
143
+ return parsePlainWhere(obj);
144
+ }
145
+ /**
146
+ * Converte um `VSRepoWherePlain<T>` (sem AND/OR/NOT) — usado para o corpo de
147
+ * relações (`_some`/`_every`/`_none`/`_with`/`_without`).
148
+ */
149
+ function parsePlainWhere(where) {
150
+ if (where === undefined || where === null)
151
+ return undefined;
152
+ const result = {};
153
+ for (const [key, value] of Object.entries(where)) {
154
+ if (value === undefined)
155
+ continue;
156
+ result[key] = parseFieldValue(value);
157
+ }
158
+ return result;
159
+ }
160
+ /**
161
+ * Converte um `VSRepoWhere<T>` completo (nível raiz, com AND/OR/NOT) em um
162
+ * where do Prisma.
163
+ */
164
+ function parseWhere(where) {
165
+ if (where === undefined || where === null)
166
+ return undefined;
167
+ const result = {};
168
+ for (const [key, value] of Object.entries(where)) {
169
+ if (value === undefined)
170
+ continue;
171
+ if (LOGICAL_KEYS.has(key)) {
172
+ result[key] = Array.isArray(value) ? value.map(v => parseWhere(v)) : parseWhere(value);
173
+ continue;
174
+ }
175
+ result[key] = parseFieldValue(value);
176
+ }
177
+ return result;
178
+ }
179
+ /**
180
+ * API pública. Use o segundo generic para tipar o retorno com o `WhereInput`
181
+ * do Prisma correspondente ao modelo, ex:
182
+ *
183
+ * parseVSRepoWhere<User, Prisma.UserWhereInput>(where)
184
+ */
185
+ function parsePrismaWhere(where) {
186
+ return parseWhere(where);
187
+ }
@@ -0,0 +1,125 @@
1
+ import { AdapterMethodOptions, AdapterQueryOptions, CountResult, DeepPartial, VSRepoAdapter, VSRepoWhere } from "vsrepo";
2
+ import { VSRepoPrisma7AdapterConfig } from "./types/adapter-config.type";
3
+ /**
4
+ * `VSRepoAdapter` implementation for Prisma 7. Translates every method of the
5
+ * adapter contract into Prisma Client calls, resolving `VSRepoWhere`/`Ordering`/
6
+ * `select`/`include` through the parsers, and — when a
7
+ * `relations` config is provided — resolving relation fields on `create`/
8
+ * `update`/`upsert`/`merge` the same way the v1 of VSRepository did (see
9
+ * `Relation`).
10
+ *
11
+ * Every method always rejects with a `VSRepoAdapterError` — any error raised
12
+ * by Prisma (or by the adapter itself) is translated through `mapPrismaError`
13
+ * before leaving the adapter, so callers never have to deal with a raw
14
+ * Prisma/driver error shape.
15
+ *
16
+ * @template T Entity type this adapter operates on.
17
+ *
18
+ * @publicApi
19
+ */
20
+ export declare class VSRepoPrisma7Adapter<T> extends VSRepoAdapter<T> {
21
+ private readonly prisma;
22
+ private readonly tableName;
23
+ private readonly pkName;
24
+ private readonly relations?;
25
+ private readonly logger;
26
+ constructor(prisma: any, config: VSRepoPrisma7AdapterConfig<T>);
27
+ private getPrismaRepository;
28
+ /** Resolves the "read" part of a Prisma arg: select/include/orderBy/pagination. */
29
+ private resolveReadArg;
30
+ /**
31
+ * Strips relation fields from a payload — used by `createMany`/`updateMany`/
32
+ * `updateManyReturning`, since those Prisma operations don't support nested
33
+ * writes (scalar fields only). Throws a `VSRepoAdapterError` (code
34
+ * `NOT_SUPPORTED`) instead of silently ignoring the field, when a configured
35
+ * relation field is present in the payload.
36
+ */
37
+ private stripRelationFields;
38
+ /**
39
+ * Tells apart a root Prisma Client from an active transaction client: only
40
+ * the root client exposes `$on` (used for event listeners), Prisma's
41
+ * interactive transaction client doesn't (see `Prisma7ClientLike`).
42
+ */
43
+ private isRootClient;
44
+ /**
45
+ * Runs `fn` against a transaction, reusing `db` when it's already a
46
+ * transaction client (see `isRootClient`) instead of nesting a new one —
47
+ * this is what lets `saveMany`/`deleteManyReturning` participate in a
48
+ * transaction already started via `VSRepository.transaction()`.
49
+ * When `db` isn't provided, or is a root client, a new transaction is
50
+ * started on it (or on `this.prisma` when `db` isn't provided at all).
51
+ */
52
+ private runTransactional;
53
+ /** Returns the underlying ORM client instance used outside of transactions. */
54
+ getDbClient(): any;
55
+ /** Runs `fn` inside a native transaction of the underlying ORM/database. */
56
+ runInTransaction<R>(fn: (tx: any) => Promise<R>, options?: {
57
+ isolationLevel?: any;
58
+ }): Promise<R>;
59
+ /** Fetches a single record matching `where`. */
60
+ findOne(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<T | null>;
61
+ /** Fetches a single record matching `where`, throwing if none is found. */
62
+ findOneOrThrow(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<T>;
63
+ /** Fetches all records matching `where`. */
64
+ findMany(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T> & {
65
+ distinct?: (keyof T)[];
66
+ }): Promise<T[]>;
67
+ /** Creates or updates (upsert) a single record. */
68
+ save(obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<T>;
69
+ /**
70
+ * Creates or updates (upsert) multiple records. Prisma has no native bulk
71
+ * upsert, so each record is saved individually inside a transaction —
72
+ * reusing `options.db` when it's already a transaction client (see
73
+ * `runTransactional`).
74
+ */
75
+ saveMany(objs: DeepPartial<T>[], options?: AdapterMethodOptions<T>): Promise<T[]>;
76
+ /** Deletes a single record matching `where`. */
77
+ delete(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<T>;
78
+ /** Deletes every record matching `where`, returning the count of affected rows. */
79
+ deleteMany(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<CountResult>;
80
+ /**
81
+ * Deletes every record matching `where`, returning the deleted records.
82
+ * Prisma has no `deleteManyAndReturn`, so this fetches then deletes inside
83
+ * a transaction — reusing `options.db` when it's already a transaction
84
+ * client (see `runTransactional`), so it stays atomic even when it's not
85
+ * the one starting the transaction.
86
+ */
87
+ deleteManyReturning(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<T[]>;
88
+ /** Updates a single record matching `where`. */
89
+ update(where: VSRepoWhere<T>, obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<T>;
90
+ /** Updates every record matching `where`, returning the count of affected rows. */
91
+ updateMany(where: VSRepoWhere<T>, obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<CountResult>;
92
+ /** Updates every record matching `where`, returning the updated records. */
93
+ updateManyReturning(where: VSRepoWhere<T>, obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<T[]>;
94
+ /** Returns the number of records matching `where`. */
95
+ count(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<number>;
96
+ /** Checks whether at least one record matching `where` exists. */
97
+ exists(where: VSRepoWhere<T>, options?: AdapterMethodOptions<T>): Promise<boolean>;
98
+ /** Executes a raw query/statement against the underlying database, used by `@QueryMethod`. */
99
+ query<R = any>(query: string, options?: AdapterQueryOptions): Promise<R>;
100
+ /** Creates a single record. */
101
+ create(obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<T>;
102
+ /**
103
+ * Creates multiple records in a single operation. Relation fields are
104
+ * stripped (see `stripRelationFields`), since Prisma's `createMany` doesn't
105
+ * support nested writes.
106
+ */
107
+ createMany(objs: DeepPartial<T>[], options?: AdapterMethodOptions<T> & {
108
+ ignoreConflicts?: boolean;
109
+ }): Promise<CountResult>;
110
+ /**
111
+ * Creates multiple records in a single operation, returning the created records.
112
+ */
113
+ createManyReturning(objs: DeepPartial<T>[], options?: AdapterMethodOptions<T> & {
114
+ ignoreConflicts?: boolean;
115
+ }): Promise<T[]>;
116
+ /**
117
+ * Fetches the record matching `where` and returns it deep-merged with
118
+ * `obj`, WITHOUT persisting anything — same behavior the v1 of
119
+ * VSRepository had (see `mergeEntities`). It's on the caller to decide
120
+ * what to do with the result (e.g. call `save` next).
121
+ */
122
+ merge<K>(where: VSRepoWhere<T>, obj: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<K & T>;
123
+ /** Creates a record if none matches `where`, otherwise updates it. */
124
+ upsert(where: VSRepoWhere<T>, create: DeepPartial<T>, update: DeepPartial<T>, options?: AdapterMethodOptions<T>): Promise<T>;
125
+ }