@vsrepo/prisma7-adapter 1.3.2 → 2.0.0-dev.1

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 (79) hide show
  1. package/CHANGELOG.md +535 -0
  2. package/LICENSE +20 -20
  3. package/README.md +394 -299
  4. package/README.pt-BR.md +394 -299
  5. package/dist/constants/provider-capabilities.constant.d.ts +17 -0
  6. package/dist/constants/provider-capabilities.constant.js +27 -0
  7. package/dist/index.d.ts +9 -8
  8. package/dist/index.js +1 -7
  9. package/dist/parsers/data.parser.d.ts +3 -33
  10. package/dist/parsers/data.parser.js +70 -69
  11. package/dist/parsers/include.parser.d.ts +1 -1
  12. package/dist/parsers/include.parser.js +3 -7
  13. package/dist/parsers/order-by.parser.d.ts +1 -10
  14. package/dist/parsers/order-by.parser.js +3 -16
  15. package/dist/parsers/select.parser.d.ts +1 -1
  16. package/dist/parsers/select.parser.js +3 -7
  17. package/dist/parsers/where.parser.d.ts +4 -29
  18. package/dist/parsers/where.parser.js +49 -148
  19. package/dist/prisma7.adapter.d.ts +116 -81
  20. package/dist/prisma7.adapter.js +345 -362
  21. package/dist/resolvers/map-prisma-error.resolver.d.ts +0 -11
  22. package/dist/resolvers/map-prisma-error.resolver.js +48 -72
  23. package/dist/resolvers/merge-entities.resolver.d.ts +11 -15
  24. package/dist/resolvers/merge-entities.resolver.js +29 -38
  25. package/dist/resolvers/resolve-provider.resolver.d.ts +2 -22
  26. package/dist/resolvers/resolve-provider.resolver.js +10 -33
  27. package/dist/types/adapter-config.type.d.ts +21 -10
  28. package/dist/types/adapter-config.type.js +1 -3
  29. package/dist/types/adapter-relations.type.d.ts +14 -8
  30. package/dist/types/adapter-relations.type.js +1 -3
  31. package/dist/types/plain-object.type.js +1 -3
  32. package/dist/types/prisma-arg-like.type.js +1 -3
  33. package/dist/types/prisma-client-models.type.d.ts +4 -4
  34. package/dist/types/prisma-client-models.type.js +1 -3
  35. package/dist/types/prisma-provider.type.d.ts +1 -1
  36. package/dist/types/prisma-provider.type.js +1 -3
  37. package/dist/types/prisma-repository-like.type.d.ts +1 -1
  38. package/dist/types/prisma-repository-like.type.js +1 -3
  39. package/dist/types/prisma7-client-like.type.d.ts +1 -8
  40. package/dist/types/prisma7-client-like.type.js +1 -3
  41. package/dist/types/prisma7-global-config.type.d.ts +17 -0
  42. package/dist/types/prisma7-global-config.type.js +1 -0
  43. package/dist/types/prisma7-orm-types.type.d.ts +2 -2
  44. package/dist/types/prisma7-orm-types.type.js +1 -3
  45. package/dist/types/relation.type.d.ts +119 -25
  46. package/dist/types/relation.type.js +1 -3
  47. package/dist/validators/is-decimal.validator.d.ts +2 -5
  48. package/dist/validators/is-decimal.validator.js +3 -6
  49. package/dist/validators/is-plain-object.validator.d.ts +1 -1
  50. package/dist/validators/is-plain-object.validator.js +3 -7
  51. package/dist/validators/validate-prisma-client.validator.d.ts +1 -14
  52. package/dist/validators/validate-prisma-client.validator.js +7 -24
  53. package/package.json +108 -91
  54. package/dist/index.js.map +0 -1
  55. package/dist/parsers/data.parser.js.map +0 -1
  56. package/dist/parsers/include.parser.js.map +0 -1
  57. package/dist/parsers/order-by.parser.js.map +0 -1
  58. package/dist/parsers/select.parser.js.map +0 -1
  59. package/dist/parsers/where.parser.js.map +0 -1
  60. package/dist/prisma7.adapter.js.map +0 -1
  61. package/dist/resolvers/map-prisma-error.resolver.js.map +0 -1
  62. package/dist/resolvers/merge-entities.resolver.js.map +0 -1
  63. package/dist/resolvers/resolve-provider.resolver.js.map +0 -1
  64. package/dist/types/adapter-config.type.js.map +0 -1
  65. package/dist/types/adapter-relations.type.js.map +0 -1
  66. package/dist/types/plain-object.type.js.map +0 -1
  67. package/dist/types/prisma-arg-like.type.js.map +0 -1
  68. package/dist/types/prisma-client-models.type.js.map +0 -1
  69. package/dist/types/prisma-provider.type.js.map +0 -1
  70. package/dist/types/prisma-repository-like.type.js.map +0 -1
  71. package/dist/types/prisma7-client-like.type.js.map +0 -1
  72. package/dist/types/prisma7-orm-types.type.js.map +0 -1
  73. package/dist/types/relation.type.js.map +0 -1
  74. package/dist/validators/is-decimal.validator.js.map +0 -1
  75. package/dist/validators/is-plain-object.validator.js.map +0 -1
  76. package/dist/validators/validate-adapter-config.validator.d.ts +0 -8
  77. package/dist/validators/validate-adapter-config.validator.js +0 -78
  78. package/dist/validators/validate-adapter-config.validator.js.map +0 -1
  79. package/dist/validators/validate-prisma-client.validator.js.map +0 -1
@@ -1,72 +1,93 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.VSRepoPrisma7Adapter = void 0;
4
- const vsrepo_1 = require("vsrepo");
5
- const where_parser_1 = require("./parsers/where.parser");
6
- const include_parser_1 = require("./parsers/include.parser");
7
- const select_parser_1 = require("./parsers/select.parser");
8
- const order_by_parser_1 = require("./parsers/order-by.parser");
9
- const data_parser_1 = require("./parsers/data.parser");
10
- const merge_entities_resolver_1 = require("./resolvers/merge-entities.resolver");
11
- const map_prisma_error_resolver_1 = require("./resolvers/map-prisma-error.resolver");
12
- const resolve_provider_resolver_1 = require("./resolvers/resolve-provider.resolver");
13
- const validate_adapter_config_validator_1 = require("./validators/validate-adapter-config.validator");
14
- const validate_prisma_client_validator_1 = require("./validators/validate-prisma-client.validator");
1
+ import { AdapterErrorCode, getPostgresPlaceholder, getSqlitePlaceholder, getSqlServerPlaceholder, VSLogger, VSLogLevel, VSRepoAdapter, VSRepoAdapterError, } from "vsrepo";
2
+ import { RETURNING_MANY_PROVIDERS, SKIP_DUPLICATES_PROVIDERS } from "./constants/provider-capabilities.constant.js";
3
+ import { parsePrismaWhere } from "./parsers/where.parser.js";
4
+ import { parsePrismaInclude } from "./parsers/include.parser.js";
5
+ import { parsePrismaSelect } from "./parsers/select.parser.js";
6
+ import { parsePrismaOrderBy } from "./parsers/order-by.parser.js";
7
+ import { parsePrismaWriteData } from "./parsers/data.parser.js";
8
+ // import { mergeEntities } from "./resolvers/merge-entities.resolver.js";
9
+ import { mapPrismaError } from "./resolvers/map-prisma-error.resolver.js";
10
+ import { resolveProvider } from "./resolvers/resolve-provider.resolver.js";
11
+ import { validatePrismaClient } from "./validators/validate-prisma-client.validator.js";
12
+ import { isDecimal } from "./validators/is-decimal.validator.js";
15
13
  /**
16
- * `VSRepoAdapter` implementation for Prisma 7. Translates every method of the
17
- * adapter contract into Prisma Client calls, resolving `VSRepoWhere`/`Ordering`/
18
- * `select`/`include` through the parsers, and — when a
19
- * `relations` config is provided — resolving relation fields on `create`/
20
- * `update`/`upsert`/`merge` the same way the v1 of VSRepository did (see
21
- * `Relation`).
22
- *
23
- * Every method always rejects with a `VSRepoAdapterError` — any error raised
24
- * by Prisma (or by the adapter itself) is translated through `mapPrismaError`
25
- * before leaving the adapter, so callers never have to deal with a raw
26
- * Prisma/driver error shape.
14
+ * `VSRepoAdapter` implementation for Prisma 7.
27
15
  *
28
16
  * @template T Entity type this adapter operates on.
29
17
  *
30
18
  * @publicApi
31
19
  */
32
- class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
20
+ export class VSRepoPrisma7Adapter extends VSRepoAdapter {
33
21
  prisma;
34
- tableName;
22
+ modelName;
35
23
  pkName;
36
24
  relations;
37
25
  logger;
38
26
  provider;
27
+ /** Whether the primary key may be dropped from a write payload when Prisma can't take it. */
28
+ allowOmitPk;
29
+ static globalConfig = {};
39
30
  constructor(prisma, config) {
40
31
  super();
41
32
  this.prisma = prisma;
42
- const validated = (0, validate_adapter_config_validator_1.validateAdapterConfig)(config);
43
- (0, validate_prisma_client_validator_1.validatePrismaClient)(prisma, validated.tableName);
44
- this.tableName = validated.tableName;
45
- this.pkName = validated.pkName;
46
- this.relations = validated.relations;
47
- this.provider = (0, resolve_provider_resolver_1.resolveProvider)(prisma, validated.provider);
48
- this.logger = new vsrepo_1.VSLogger(validated.logLevel ?? vsrepo_1.VSLogLevel.WARN, this.constructor.name + "Logger", validated.logSlowThresholdMs ?? 300);
49
- this.logger.logInfo(`${this.constructor.name} initialized for table '${this.tableName}' (pkName: '${this.pkName}'${this.relations ? `, relations: [${Object.keys(this.relations).join(", ")}]` : ""}, provider: ${this.provider ? `'${this.provider}'` : "<not detected>"})`);
33
+ validatePrismaClient(prisma, config.modelName);
34
+ this.modelName = config.modelName;
35
+ this.pkName = config.pkName;
36
+ this.relations = config.relations;
37
+ this.provider = resolveProvider(prisma, config.provider ?? VSRepoPrisma7Adapter.globalConfig.provider);
38
+ this.logger = new VSLogger(config.logLevel ?? VSRepoPrisma7Adapter.globalConfig.logLevel ?? VSLogLevel.WARN, this.constructor.name + "Logger");
39
+ this.allowOmitPk = config.allowOmitPk ?? VSRepoPrisma7Adapter.globalConfig.allowOmitPk;
40
+ this.logger.logInfo(`${this.constructor.name} initialized for table '${this.modelName}' (pkName: '${this.pkName}'${this.relations ? `, relations: [${Object.keys(this.relations).join(", ")}]` : ""}, provider: ${this.provider ? `'${this.provider}'` : "<not detected>"}${this.allowOmitPk ? ", allowOmitPk: true" : ""})`);
41
+ }
42
+ /**
43
+ * Sets defaults (`provider`, `logLevel`, `allowOmitPk`) for every adapter
44
+ * created **after** this call. It replaces the previous global config, and
45
+ * the config passed to each adapter's constructor takes precedence.
46
+ */
47
+ static setGlobalConfig(globalConfig) {
48
+ this.globalConfig = globalConfig;
50
49
  }
51
50
  getPrismaRepository(db) {
52
- return db ? db[this.tableName] : this.prisma[this.tableName];
51
+ return db ? db[this.modelName] : this.prisma[this.modelName];
53
52
  }
54
53
  /** Resolves the "read" part of a Prisma arg: select/include/orderBy/pagination. */
55
54
  resolveReadArg(options) {
56
- options ??= {};
57
- const prismaSelect = options.select && (0, select_parser_1.parsePrismaSelect)(options.select);
58
- const prismaInclude = prismaSelect
59
- ? undefined
60
- : options.relations && (0, include_parser_1.parsePrismaInclude)(options.relations);
55
+ if (!options)
56
+ return {};
57
+ const prismaSelect = options.select && parsePrismaSelect(options.select);
58
+ const prismaInclude = prismaSelect ? undefined : options.relations && parsePrismaInclude(options.relations);
61
59
  return {
62
60
  select: prismaSelect,
63
61
  include: prismaInclude,
64
- orderBy: (0, order_by_parser_1.parsePrismaOrderBy)(options.order),
62
+ orderBy: parsePrismaOrderBy(options.order),
65
63
  skip: options.pagination?.offset,
66
64
  take: options.pagination?.limit,
67
- distinct: options.distinct,
68
65
  };
69
66
  }
67
+ /** Parses a `where` for this adapter's provider (rejecting what the provider cannot run). */
68
+ parseWhere(where) {
69
+ return parsePrismaWhere(where, this.provider);
70
+ }
71
+ /**
72
+ * `createManyReturning` and `updateManyReturning` rely on Prisma's `createManyAndReturn` /
73
+ * `updateManyAndReturn`, which only exist on PostgreSQL, CockroachDB and SQLite.
74
+ */
75
+ assertReturningManySupported(methodName) {
76
+ if (RETURNING_MANY_PROVIDERS.has(this.provider))
77
+ return;
78
+ throw new VSRepoAdapterError(`'${methodName}' is not supported by the '${this.provider}' provider, since Prisma only provides ` +
79
+ `createManyAndReturn/updateManyAndReturn on PostgreSQL, CockroachDB and SQLite.`, AdapterErrorCode.NOT_SUPPORTED, null);
80
+ }
81
+ /**
82
+ * `ignoreConflicts` is translated to Prisma's `skipDuplicates`, which isn't available on
83
+ * SQL Server and SQLite. Rejects with `NOT_SUPPORTED` instead of leaving it to Prisma.
84
+ */
85
+ assertIgnoreConflictsSupported(methodName, ignoreConflicts) {
86
+ if (!ignoreConflicts || SKIP_DUPLICATES_PROVIDERS.has(this.provider))
87
+ return;
88
+ throw new VSRepoAdapterError(`The 'ignoreConflicts' option of '${methodName}' is not supported by the '${this.provider}' provider, since Prisma only ` +
89
+ `supports skipDuplicates on PostgreSQL, MySQL and CockroachDB. Remove 'ignoreConflicts' to run it without skipping conflicts.`, AdapterErrorCode.NOT_SUPPORTED, null);
90
+ }
70
91
  /**
71
92
  * Strips relation fields from a payload — used by `createMany`/`updateMany`/
72
93
  * `updateManyReturning`, since those Prisma operations don't support nested
@@ -82,7 +103,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
82
103
  if (value === undefined)
83
104
  continue;
84
105
  if (key in this.relations) {
85
- throw new vsrepo_1.VSRepoAdapterError(`Field '${key}' is a configured relation, but Prisma's *Many operations don't support nested relation writes.`, vsrepo_1.AdapterErrorCode.NOT_SUPPORTED, null);
106
+ throw new VSRepoAdapterError(`Field '${key}' is a configured relation, but Prisma's *Many operations don't support nested relation writes.`, AdapterErrorCode.NOT_SUPPORTED, null);
86
107
  }
87
108
  data[key] = value;
88
109
  }
@@ -117,28 +138,47 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
117
138
  * evaluated server-side against the row's current value, never as a
118
139
  * client-side read-modify-write. `value` is passed through as-is:
119
140
  * Prisma accepts a `number`, `bigint`, or any `Decimal`/`DecimalJsLike`
120
- * value (which covers a {@link DecimalLike} like `Prisma.Decimal`)
141
+ * value (which covers a `DecimalLike` like `Prisma.Decimal`)
121
142
  * depending on the target column's type.
122
143
  *
123
144
  * Prisma's `update()` already returns the row reflecting the state
124
145
  * *after* the write, so no follow-up read is needed here.
125
146
  */
126
147
  async atomicUpdate(operation, field, value, where, options) {
127
- const start = this.logger.startPerformLog(`run ${operation}One`);
148
+ const methodName = `${operation}One`;
149
+ const start = this.logger.startPerformLog(`run ${methodName}`);
128
150
  try {
129
151
  const arg = {
130
- ...this.resolveReadArg(options),
131
- where: (0, where_parser_1.parsePrismaWhere)(where),
152
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
153
+ where: this.parseWhere(where),
132
154
  data: { [field]: { [operation]: value } },
133
155
  };
134
- this.logger.logDebug(`Resolved Prisma arg for '${operation}One'`, arg);
135
- return await this.getPrismaRepository(options?.db).update(arg);
156
+ this.logger.logDebug(`Resolved Prisma arg for ${methodName}`, arg);
157
+ const result = await this.getPrismaRepository(options?.db).update(arg);
158
+ this.logger.endPerformLog(start);
159
+ return result;
136
160
  }
137
161
  catch (error) {
138
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, `${operation}One`);
162
+ this.logger.endPerformLog(start);
163
+ throw mapPrismaError(error, methodName);
139
164
  }
140
- finally {
165
+ }
166
+ async atomicUpdateMany(operation, field, value, where, options) {
167
+ const methodName = `${operation}Many`;
168
+ const start = this.logger.startPerformLog(`run ${methodName}`);
169
+ try {
170
+ const arg = {
171
+ where: this.parseWhere(where),
172
+ data: { [field]: { [operation]: value } },
173
+ };
174
+ this.logger.logDebug(`Resolved Prisma arg for ${methodName}`, arg);
175
+ const result = await this.getPrismaRepository(options?.db).updateMany(arg);
141
176
  this.logger.endPerformLog(start);
177
+ return result;
178
+ }
179
+ catch (error) {
180
+ this.logger.endPerformLog(start);
181
+ throw mapPrismaError(error, methodName);
142
182
  }
143
183
  }
144
184
  /**
@@ -152,7 +192,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
152
192
  return null;
153
193
  if (typeof value === "bigint")
154
194
  return Number(value);
155
- if (typeof value?.toNumber === "function") {
195
+ if (isDecimal(value)) {
156
196
  return value.toNumber();
157
197
  }
158
198
  return Number(value);
@@ -170,18 +210,17 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
170
210
  const aggKey = `_${operation}`;
171
211
  try {
172
212
  const arg = {
173
- where: (0, where_parser_1.parsePrismaWhere)(where),
213
+ where: this.parseWhere(where),
174
214
  [aggKey]: { [field]: true },
175
215
  };
176
- this.logger.logDebug(`Resolved Prisma arg for '${operation}'`, arg);
177
- const result = await this.getPrismaRepository(options?.db).aggregate(arg);
178
- return this.toNullableNumber(result?.[aggKey]?.[field]);
216
+ this.logger.logDebug(`Resolved Prisma arg for ${operation}`, arg);
217
+ const aggResult = await this.getPrismaRepository(options?.db).aggregate(arg);
218
+ this.logger.endPerformLog(start);
219
+ return this.toNullableNumber(aggResult?.[aggKey]?.[field]);
179
220
  }
180
221
  catch (error) {
181
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, operation);
182
- }
183
- finally {
184
222
  this.logger.endPerformLog(start);
223
+ throw mapPrismaError(error, operation);
185
224
  }
186
225
  }
187
226
  /** Returns the underlying ORM client instance used outside of transactions. */
@@ -197,277 +236,211 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
197
236
  });
198
237
  }
199
238
  catch (error) {
200
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "runInTransaction");
239
+ throw mapPrismaError(error, "runInTransaction");
201
240
  }
202
241
  }
203
- /** Fetches a single record matching `where`. */
204
- async findOne(where, options) {
205
- const start = this.logger.startPerformLog("run findOne");
242
+ async execMethod(fn, methodName, arg) {
243
+ const start = this.logger.startPerformLog(`run ${methodName}`);
206
244
  try {
207
- const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
208
- this.logger.logDebug("Resolved Prisma arg for 'findOne'", arg);
209
- return await this.getPrismaRepository(options?.db).findFirst(arg);
245
+ this.logger.logDebug(`Resolved Prisma arg for ${methodName}`, arg);
246
+ const result = await fn();
247
+ this.logger.endPerformLog(start);
248
+ return result;
210
249
  }
211
250
  catch (error) {
212
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "findOne");
213
- }
214
- finally {
215
251
  this.logger.endPerformLog(start);
252
+ throw mapPrismaError(error, methodName);
216
253
  }
217
254
  }
255
+ /** Runs `parsePrismaWriteData` with this adapter's `pkName`, `relations` and `allowOmitPk`. */
256
+ parseData(obj, omitPkInUpdate) {
257
+ return parsePrismaWriteData(obj, this.pkName, this.relations, omitPkInUpdate, this.allowOmitPk);
258
+ }
259
+ /** Fetches a single record matching `where`. */
260
+ async findOne(where, options) {
261
+ const arg = { ...this.resolveReadArg(options), where: this.parseWhere(where) };
262
+ return this.execMethod(() => this.getPrismaRepository(options?.db).findFirst(arg), "findOne", arg);
263
+ }
218
264
  /** Fetches a single record matching `where`, throwing if none is found. */
219
265
  async findOneOrThrow(where, options) {
220
- const start = this.logger.startPerformLog("run findOneOrThrow");
221
- try {
222
- const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
223
- this.logger.logDebug("Resolved Prisma arg for 'findOneOrThrow'", arg);
224
- return await this.getPrismaRepository(options?.db).findFirstOrThrow(arg);
225
- }
226
- catch (error) {
227
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "findOneOrThrow");
228
- }
229
- finally {
230
- this.logger.endPerformLog(start);
231
- }
266
+ const arg = { ...this.resolveReadArg(options), where: this.parseWhere(where) };
267
+ return this.execMethod(() => this.getPrismaRepository(options?.db).findFirstOrThrow(arg), "findOneOrThrow", arg);
232
268
  }
233
269
  /** Fetches all records matching `where`. */
234
270
  async findMany(where, options) {
235
- const start = this.logger.startPerformLog("run findMany");
236
- try {
237
- const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
238
- this.logger.logDebug("Resolved Prisma arg for 'findMany'", arg);
239
- return await this.getPrismaRepository(options?.db).findMany(arg);
240
- }
241
- catch (error) {
242
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "findMany");
243
- }
244
- finally {
245
- this.logger.endPerformLog(start);
246
- }
271
+ const arg = { ...this.resolveReadArg(options), where: this.parseWhere(where) };
272
+ return this.execMethod(() => this.getPrismaRepository(options?.db).findMany(arg), "findMany", arg);
247
273
  }
248
274
  /** Creates or updates (upsert) a single record. */
249
275
  async save(obj, options) {
250
- const start = this.logger.startPerformLog("run save");
251
- try {
252
- const objAny = obj;
253
- const pkValue = objAny[this.pkName];
254
- const readArg = this.resolveReadArg(options);
255
- const repo = this.getPrismaRepository(options?.db);
256
- if (pkValue === undefined) {
257
- const { create } = (0, data_parser_1.parsePrismaWriteData)(objAny, this.pkName, this.relations);
258
- const arg = { ...readArg, data: create };
259
- this.logger.logDebug("Resolved Prisma arg for 'save' (create)", arg);
260
- return await repo.create(arg);
261
- }
262
- const { create, update } = (0, data_parser_1.parsePrismaWriteData)(objAny, this.pkName, this.relations);
263
- const arg = { ...readArg, where: { [this.pkName]: pkValue }, create, update };
264
- this.logger.logDebug("Resolved Prisma arg for 'save' (upsert)", arg);
265
- return await repo.upsert(arg);
266
- }
267
- catch (error) {
268
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "save");
269
- }
270
- finally {
271
- this.logger.endPerformLog(start);
272
- }
276
+ const objAny = obj;
277
+ const pkValue = objAny[this.pkName];
278
+ const readArg = this.resolveReadArg({ select: options?.select, relations: options?.relations });
279
+ const repo = this.getPrismaRepository(options?.db);
280
+ const { create, update } = this.parseData(objAny, true);
281
+ if (pkValue === undefined) {
282
+ const arg = { ...readArg, data: create };
283
+ return this.execMethod(() => repo.create(arg), "save (create)", arg);
284
+ }
285
+ const arg = { ...readArg, where: { [this.pkName]: pkValue }, create, update };
286
+ return this.execMethod(() => repo.upsert(arg), "save (upsert)", arg);
273
287
  }
274
288
  /**
275
289
  * Creates or updates (upsert) multiple records. Prisma has no native bulk
276
290
  * upsert, so each record is saved individually inside a transaction —
277
- * reusing `options.db` when it's already a transaction client (see
278
- * `runTransactional`).
291
+ * reusing `options.db` when it's already a transaction client.
279
292
  */
280
293
  async saveMany(objs, options) {
281
294
  const start = this.logger.startPerformLog("run saveMany");
282
295
  try {
283
296
  this.logger.logDebug(`Saving ${objs.length} record(s) individually inside a transaction`);
284
- return await this.runTransactional(options?.db, async (tx) => {
297
+ const result = await this.runTransactional(options?.db, async (tx) => {
298
+ const optionsResolved = { ...options, db: tx };
285
299
  const saved = [];
286
300
  for (let i = 0; i < objs.length; i++) {
287
301
  const obj = objs[i];
288
- saved.push(await this.save(obj, { ...options, db: tx }));
302
+ saved.push(await this.save(obj, optionsResolved));
289
303
  }
290
304
  return saved;
291
305
  });
306
+ this.logger.endPerformLog(start);
307
+ return result;
292
308
  }
293
309
  catch (error) {
294
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "saveMany");
295
- }
296
- finally {
297
310
  this.logger.endPerformLog(start);
311
+ throw mapPrismaError(error, "saveMany");
298
312
  }
299
313
  }
300
314
  /** Deletes a single record matching `where`. */
301
315
  async delete(where, options) {
302
- const start = this.logger.startPerformLog("run delete");
303
- try {
304
- const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
305
- this.logger.logDebug("Resolved Prisma arg for 'delete'", arg);
306
- return await this.getPrismaRepository(options?.db).delete(arg);
307
- }
308
- catch (error) {
309
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "delete");
310
- }
311
- finally {
312
- this.logger.endPerformLog(start);
313
- }
316
+ const arg = {
317
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
318
+ where: this.parseWhere(where),
319
+ };
320
+ return this.execMethod(() => this.getPrismaRepository(options?.db).delete(arg), "delete", arg);
314
321
  }
315
322
  /** Deletes every record matching `where`, returning the count of affected rows. */
316
323
  async deleteMany(where, options) {
317
- const start = this.logger.startPerformLog("run deleteMany");
318
- try {
319
- const arg = { where: (0, where_parser_1.parsePrismaWhere)(where) };
320
- this.logger.logDebug("Resolved Prisma arg for 'deleteMany'", arg);
321
- return await this.getPrismaRepository(options?.db).deleteMany(arg);
322
- }
323
- catch (error) {
324
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "deleteMany");
325
- }
326
- finally {
327
- this.logger.endPerformLog(start);
328
- }
324
+ const arg = { where: this.parseWhere(where) };
325
+ return this.execMethod(() => this.getPrismaRepository(options?.db).deleteMany(arg), "deleteMany", arg);
329
326
  }
330
327
  /**
331
- * Deletes every record matching `where`, returning the deleted records.
328
+ * Deletes every record matching `where` and returns the deleted records.
332
329
  *
333
- * Prisma has no `deleteManyAndReturn`, so this does a `findMany` on
334
- * `where` first and then re-applies the same `where` to a `deleteMany`,
335
- * both inside a transaction (`runTransactional`).
330
+ * In the absence of a native `deleteManyAndReturn`, this fetches matching records
331
+ * via `findMany` first, extracts their primary keys, and then deletes them by ID
332
+ * using `{ [pkName]: { in: pks } }` inside a transaction.
336
333
  *
337
- * Because the delete is driven by the same `where` (not by the fetched
338
- * records), a concurrent change between the two operations can make them
339
- * diverge — e.g. a row inserted after the `findMany` matching the `where`
340
- * would still be deleted, while a row changed to stop matching wouldn't.
341
- * If you need to guarantee no concurrency issues, run this method inside a
342
- * `repository.transaction()` with a higher isolation level, e.g.
343
- * `TransactionIsolationLevel.SERIALIZABLE`.
334
+ * Key behaviors:
335
+ * - **Primary Key Handling:** If `options.select` omits the primary key, it is
336
+ * temporarily added to the query so the subsequent batch delete can target
337
+ * those exact IDs, and stripped from the returned objects afterward.
338
+ * - **Concurrency & Isolation:** Deleting strictly by the fetched IDs ensures only
339
+ * the exact returned rows are removed (avoiding deleting newly inserted rows that
340
+ * match `where`). However, if a row is modified or deleted concurrently between
341
+ * the read and the delete step, race conditions can still occur unless wrapped
342
+ * in a transaction with an appropriate isolation level (e.g., `SERIALIZABLE`).
344
343
  */
345
344
  async deleteManyReturning(where, options) {
346
345
  const start = this.logger.startPerformLog("run deleteManyReturning");
347
346
  try {
348
- const prismaWhere = (0, where_parser_1.parsePrismaWhere)(where);
349
- const findArg = { ...this.resolveReadArg(options), where: prismaWhere };
350
- const deleteArg = { where: prismaWhere };
351
- this.logger.logDebug("Resolved Prisma args for 'deleteManyReturning'", {
352
- findArg,
353
- deleteArg,
354
- });
355
- return await this.runTransactional(options?.db, async (tx) => {
347
+ const prismaWhere = this.parseWhere(where);
348
+ const findArg = {
349
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
350
+ where: prismaWhere,
351
+ };
352
+ const userRequestedPk = findArg.include || !findArg.select || !!findArg.select[this.pkName];
353
+ if (!userRequestedPk) {
354
+ findArg.select[this.pkName] = true;
355
+ }
356
+ this.logger.logDebug("Resolved Prisma args for deleteManyReturning", findArg);
357
+ const result = await this.runTransactional(options?.db, async (tx) => {
356
358
  const repo = this.getPrismaRepository(tx);
357
359
  const records = await repo.findMany(findArg);
358
- await repo.deleteMany(deleteArg);
360
+ if (records.length === 0)
361
+ return [];
362
+ const pks = records.map((rec) => rec[this.pkName]);
363
+ await repo.deleteMany({ where: { [this.pkName]: { in: pks } } });
359
364
  return records;
360
365
  });
366
+ if (!userRequestedPk) {
367
+ for (const obj of result) {
368
+ delete obj[this.pkName];
369
+ }
370
+ }
371
+ this.logger.endPerformLog(start);
372
+ return result;
361
373
  }
362
374
  catch (error) {
363
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "deleteManyReturning");
364
- }
365
- finally {
366
375
  this.logger.endPerformLog(start);
376
+ throw mapPrismaError(error, "deleteManyReturning");
367
377
  }
368
378
  }
369
379
  /** Updates a single record matching `where`. */
370
380
  async update(where, obj, options) {
371
- const start = this.logger.startPerformLog("run update");
372
- try {
373
- const { update } = (0, data_parser_1.parsePrismaWriteData)(obj, this.pkName, this.relations);
374
- const arg = {
375
- ...this.resolveReadArg(options),
376
- where: (0, where_parser_1.parsePrismaWhere)(where),
377
- data: update,
378
- };
379
- this.logger.logDebug("Resolved Prisma arg for 'update'", arg);
380
- return await this.getPrismaRepository(options?.db).update(arg);
381
- }
382
- catch (error) {
383
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "update");
384
- }
385
- finally {
386
- this.logger.endPerformLog(start);
387
- }
381
+ const { update } = this.parseData(obj);
382
+ const arg = {
383
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
384
+ where: this.parseWhere(where),
385
+ data: update,
386
+ };
387
+ return this.execMethod(() => this.getPrismaRepository(options?.db).update(arg), "update", arg);
388
388
  }
389
389
  /** Updates every record matching `where`, returning the count of affected rows. */
390
390
  async updateMany(where, obj, options) {
391
- const start = this.logger.startPerformLog("run updateMany");
392
- try {
393
- const data = this.stripRelationFields(obj);
394
- const arg = { where: (0, where_parser_1.parsePrismaWhere)(where), data };
395
- this.logger.logDebug("Resolved Prisma arg for 'updateMany'", arg);
396
- return await this.getPrismaRepository(options?.db).updateMany(arg);
397
- }
398
- catch (error) {
399
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "updateMany");
400
- }
401
- finally {
402
- this.logger.endPerformLog(start);
403
- }
391
+ const data = this.stripRelationFields(obj);
392
+ const arg = { where: this.parseWhere(where), data };
393
+ return this.execMethod(() => this.getPrismaRepository(options?.db).updateMany(arg), "updateMany", arg);
404
394
  }
405
- /** Updates every record matching `where`, returning the updated records. */
395
+ /**
396
+ * Updates every record matching `where`, returning the updated records.
397
+ *
398
+ * Rejects with `NOT_SUPPORTED` on providers without `updateManyAndReturn` (MySQL and SQL Server).
399
+ */
406
400
  async updateManyReturning(where, obj, options) {
407
401
  const start = this.logger.startPerformLog("run updateManyReturning");
408
402
  try {
409
- const data = this.stripRelationFields(obj);
410
- const readArg = this.resolveReadArg(options);
411
- const arg = {
412
- ...readArg,
413
- where: (0, where_parser_1.parsePrismaWhere)(where),
414
- data,
415
- };
416
- this.logger.logDebug("Resolved Prisma arg for 'updateManyReturning'", arg);
417
- return await this.runTransactional(options?.db, async (tx) => {
418
- const repo = this.getPrismaRepository(tx);
419
- const updated = await repo.updateManyAndReturn({
420
- ...arg,
421
- include: undefined,
422
- select: { [this.pkName]: true },
423
- });
424
- const idsUpdated = updated.map((_) => _[this.pkName]);
425
- return repo.findMany({
426
- ...readArg,
427
- where: { [this.pkName]: { in: idsUpdated } },
403
+ this.assertReturningManySupported("updateManyReturning");
404
+ const readArg = this.resolveReadArg({ select: options?.select, relations: options?.relations });
405
+ const arg = { where: this.parseWhere(where), data: this.stripRelationFields(obj) };
406
+ this.logger.logDebug("Resolved Prisma args for updateManyReturning", { ...readArg, ...arg });
407
+ let result;
408
+ if (!readArg.select && !readArg.include) {
409
+ result = await this.getPrismaRepository(options?.db).updateManyAndReturn(arg);
410
+ }
411
+ else {
412
+ result = await this.runTransactional(options?.db, async (tx) => {
413
+ const repo = this.getPrismaRepository(tx);
414
+ const updated = await repo.updateManyAndReturn({ ...arg, select: { [this.pkName]: true } });
415
+ const idsUpdated = updated.map((_) => _[this.pkName]);
416
+ return await repo.findMany({
417
+ ...readArg,
418
+ where: { [this.pkName]: { in: idsUpdated } },
419
+ });
428
420
  });
429
- });
421
+ }
422
+ this.logger.endPerformLog(start);
423
+ return result;
430
424
  }
431
425
  catch (error) {
432
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "updateManyReturning");
433
- }
434
- finally {
435
426
  this.logger.endPerformLog(start);
427
+ throw mapPrismaError(error, "updateManyReturning");
436
428
  }
437
429
  }
438
430
  /** Returns the number of records matching `where`. */
439
431
  async count(where, options) {
440
- const start = this.logger.startPerformLog("run count");
441
- try {
442
- const readArg = this.resolveReadArg(options);
443
- const arg = { ...readArg, where: (0, where_parser_1.parsePrismaWhere)(where) };
444
- this.logger.logDebug("Resolved Prisma arg for 'count'", arg);
445
- return await this.getPrismaRepository(options?.db).count(arg);
446
- }
447
- catch (error) {
448
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "count");
449
- }
450
- finally {
451
- this.logger.endPerformLog(start);
452
- }
432
+ const arg = { where: this.parseWhere(where) };
433
+ return this.execMethod(() => this.getPrismaRepository(options?.db).count(arg), "count", arg);
453
434
  }
454
435
  /** Checks whether at least one record matching `where` exists. */
455
436
  async exists(where, options) {
456
- const start = this.logger.startPerformLog("run exists");
457
- try {
458
- const arg = { where: (0, where_parser_1.parsePrismaWhere)(where), select: { [this.pkName]: true } };
459
- this.logger.logDebug("Resolved Prisma arg for 'exists'", arg);
437
+ const arg = { where: this.parseWhere(where), select: { [this.pkName]: true } };
438
+ return this.execMethod(async () => {
460
439
  const result = await this.getPrismaRepository(options?.db).findFirst(arg);
461
440
  return result !== null;
462
- }
463
- catch (error) {
464
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "exists");
465
- }
466
- finally {
467
- this.logger.endPerformLog(start);
468
- }
441
+ }, "exists", arg);
469
442
  }
470
- /** Executes a raw query/statement against the underlying database, used by `@QueryMethod`. */
443
+ /** Executes a raw query/statement against the underlying database. */
471
444
  async query(query, options) {
472
445
  const modifying = options?.modifying ?? false;
473
446
  const db = options?.db ?? this.prisma;
@@ -475,128 +448,114 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
475
448
  const start = this.logger.startPerformLog(`run raw query (modifying: ${modifying})`);
476
449
  try {
477
450
  this.logger.logDebug("Running raw query", { query, args, modifying });
478
- return modifying
451
+ const result = modifying
479
452
  ? await db.$executeRawUnsafe(query, ...args)
480
453
  : await db.$queryRawUnsafe(query, ...args);
454
+ this.logger.endPerformLog(start);
455
+ return result;
481
456
  }
482
457
  catch (error) {
483
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "query");
484
- }
485
- finally {
486
458
  this.logger.endPerformLog(start);
459
+ throw mapPrismaError(error, "query");
487
460
  }
488
461
  }
489
462
  /** Creates a single record. */
490
463
  async create(obj, options) {
491
- const start = this.logger.startPerformLog("run create");
492
- try {
493
- const { create } = (0, data_parser_1.parsePrismaWriteData)(obj, this.pkName, this.relations);
494
- const arg = { ...this.resolveReadArg(options), data: create };
495
- this.logger.logDebug("Resolved Prisma arg for 'create'", arg);
496
- return await this.getPrismaRepository(options?.db).create(arg);
497
- }
498
- catch (error) {
499
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "create");
500
- }
501
- finally {
502
- this.logger.endPerformLog(start);
503
- }
464
+ const { create } = this.parseData(obj);
465
+ const arg = {
466
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
467
+ data: create,
468
+ };
469
+ return this.execMethod(() => this.getPrismaRepository(options?.db).create(arg), "create", arg);
504
470
  }
505
471
  /**
506
- * Creates multiple records in a single operation. Relation fields are
507
- * stripped (see `stripRelationFields`), since Prisma's `createMany` doesn't
508
- * support nested writes.
472
+ * Creates multiple records in a single operation.
473
+ *
474
+ * Rejects with `NOT_SUPPORTED` when `ignoreConflicts` is used on a provider without
475
+ * `skipDuplicates` (SQL Server and SQLite).
509
476
  */
510
477
  async createMany(objs, options) {
511
- const start = this.logger.startPerformLog("run createMany");
512
- try {
513
- const data = objs.map(obj => this.stripRelationFields(obj));
514
- const arg = { data, skipDuplicates: options?.ignoreConflicts };
515
- this.logger.logDebug("Resolved Prisma arg for 'createMany'", arg);
516
- return await this.getPrismaRepository(options?.db).createMany(arg);
517
- }
518
- catch (error) {
519
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "createMany");
520
- }
521
- finally {
522
- this.logger.endPerformLog(start);
523
- }
478
+ this.assertIgnoreConflictsSupported("createMany", options?.ignoreConflicts);
479
+ const data = objs.map(obj => this.stripRelationFields(obj));
480
+ const arg = { data, skipDuplicates: options?.ignoreConflicts };
481
+ return this.execMethod(() => this.getPrismaRepository(options?.db).createMany(arg), "createMany", arg);
524
482
  }
525
483
  /**
526
484
  * Creates multiple records in a single operation, returning the created records.
485
+ *
486
+ * Rejects with `NOT_SUPPORTED` on providers without `createManyAndReturn` (MySQL and SQL Server),
487
+ * and when `ignoreConflicts` is used on a provider without `skipDuplicates` (SQL Server and SQLite).
527
488
  */
528
489
  async createManyReturning(objs, options) {
529
490
  const start = this.logger.startPerformLog("run createManyReturning");
530
491
  try {
531
- const data = objs.map(obj => this.stripRelationFields(obj));
532
- const readArg = this.resolveReadArg(options);
533
- const arg = { data, skipDuplicates: options?.ignoreConflicts };
534
- this.logger.logDebug("Resolved Prisma arg for 'createManyReturning'", arg);
535
- return await this.runTransactional(options?.db, async (tx) => {
536
- const repo = this.getPrismaRepository(tx);
537
- const created = await repo.createManyAndReturn({
538
- ...arg,
539
- include: undefined,
540
- select: { [this.pkName]: true },
541
- });
542
- const idsCreated = created.map((_) => _[this.pkName]);
543
- return repo.findMany({
544
- ...readArg,
545
- where: { [this.pkName]: { in: idsCreated } },
492
+ this.assertReturningManySupported("createManyReturning");
493
+ this.assertIgnoreConflictsSupported("createManyReturning", options?.ignoreConflicts);
494
+ const readArg = this.resolveReadArg({ select: options?.select, relations: options?.relations });
495
+ const arg = {
496
+ data: objs.map(obj => this.stripRelationFields(obj)),
497
+ skipDuplicates: options?.ignoreConflicts,
498
+ };
499
+ this.logger.logDebug("Resolved Prisma args for createManyReturning", { ...readArg, ...arg });
500
+ let result;
501
+ if (!readArg.select && !readArg.include) {
502
+ result = await this.getPrismaRepository(options?.db).createManyAndReturn(arg);
503
+ }
504
+ else {
505
+ result = await this.runTransactional(options?.db, async (tx) => {
506
+ const repo = this.getPrismaRepository(tx);
507
+ const created = await repo.createManyAndReturn({ ...arg, select: { [this.pkName]: true } });
508
+ const idsCreated = created.map((_) => _[this.pkName]);
509
+ return await repo.findMany({
510
+ ...readArg,
511
+ where: { [this.pkName]: { in: idsCreated } },
512
+ });
546
513
  });
547
- });
548
- }
549
- catch (error) {
550
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "createManyReturning");
551
- }
552
- finally {
514
+ }
553
515
  this.logger.endPerformLog(start);
554
- }
555
- }
556
- /**
557
- * Fetches the record matching `where` and returns it deep-merged with
558
- * `obj`, WITHOUT persisting anything — same behavior the v1 of
559
- * VSRepository had (see `mergeEntities`). It's on the caller to decide
560
- * what to do with the result (e.g. call `save` next).
561
- */
562
- async merge(where, obj, options) {
563
- const start = this.logger.startPerformLog("run merge");
564
- try {
565
- const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
566
- this.logger.logDebug("Resolved Prisma arg for 'merge'", arg);
567
- const result = await this.getPrismaRepository(options?.db).findFirst(arg);
568
- if (!result)
569
- return null;
570
- return (0, merge_entities_resolver_1.mergeEntities)(result, obj, this.relations);
516
+ return result;
571
517
  }
572
518
  catch (error) {
573
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "merge");
574
- }
575
- finally {
576
519
  this.logger.endPerformLog(start);
577
- }
578
- }
520
+ throw mapPrismaError(error, "createManyReturning");
521
+ }
522
+ }
523
+ // /**
524
+ // * Fetches the record matching `where` and returns it merged with `obj`,
525
+ // * WITHOUT persisting anything. Only the configured `relations` are merged;
526
+ // * every other value is replaced. It's on the caller to decide what to do
527
+ // * with the result (e.g. call `save` next).
528
+ // */
529
+ // async merge<K extends DeepPartial<T>>(
530
+ // where: VSRepoWhere<T>,
531
+ // obj: K,
532
+ // options?: SimpleAdapterMethodOptions<T>,
533
+ // ): Promise<(K & T) | null> {
534
+ // const arg = {
535
+ // ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
536
+ // where: this.parseWhere(where),
537
+ // };
538
+ // return this.execMethod(
539
+ // async () => {
540
+ // const result = await this.getPrismaRepository(options?.db).findFirst(arg);
541
+ // if (!result) return null;
542
+ // return mergeEntities(result, obj as PlainObject, this.relations) as K & T;
543
+ // },
544
+ // "merge",
545
+ // arg,
546
+ // );
547
+ // }
579
548
  /** Creates a record if none matches `where`, otherwise updates it. */
580
549
  async upsert(where, create, update, options) {
581
- const start = this.logger.startPerformLog("run upsert");
582
- try {
583
- const parsedCreate = (0, data_parser_1.parsePrismaWriteData)(create, this.pkName, this.relations).create;
584
- const parsedUpdate = (0, data_parser_1.parsePrismaWriteData)(update, this.pkName, this.relations).update;
585
- const arg = {
586
- ...this.resolveReadArg(options),
587
- where: (0, where_parser_1.parsePrismaWhere)(where),
588
- create: parsedCreate,
589
- update: parsedUpdate,
590
- };
591
- this.logger.logDebug("Resolved Prisma arg for 'upsert'", arg);
592
- return await this.getPrismaRepository(options?.db).upsert(arg);
593
- }
594
- catch (error) {
595
- throw (0, map_prisma_error_resolver_1.mapPrismaError)(error, "upsert");
596
- }
597
- finally {
598
- this.logger.endPerformLog(start);
599
- }
550
+ const parsedCreate = this.parseData(create).create;
551
+ const parsedUpdate = this.parseData(update).update;
552
+ const arg = {
553
+ ...this.resolveReadArg({ select: options?.select, relations: options?.relations }),
554
+ where: this.parseWhere(where),
555
+ create: parsedCreate,
556
+ update: parsedUpdate,
557
+ };
558
+ return this.execMethod(() => this.getPrismaRepository(options?.db).upsert(arg), "upsert", arg);
600
559
  }
601
560
  /**
602
561
  * Atomically adds `value` to `field` on the record matching `where`,
@@ -605,24 +564,55 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
605
564
  async incrementOne(field, value, where, options) {
606
565
  return this.atomicUpdate("increment", field, value, where, options);
607
566
  }
608
- /** Same as {@link VSRepoPrisma7Adapter.incrementOne}, subtracting `value` instead of adding it. */
567
+ /**
568
+ * Atomically subtracts `value` to `field` on the record matching `where`,
569
+ * via Prisma's native `{ field: { decrement: value } }` write.
570
+ */
609
571
  async decrementOne(field, value, where, options) {
610
572
  return this.atomicUpdate("decrement", field, value, where, options);
611
573
  }
612
- /** Same as {@link VSRepoPrisma7Adapter.incrementOne}, multiplying the field's current value by `value`. */
574
+ /**
575
+ * Atomically multiplies `value` to `field` on the record matching `where`,
576
+ * via Prisma's native `{ field: { multiply: value } }` write.
577
+ */
613
578
  async multiplyOne(field, value, where, options) {
614
579
  return this.atomicUpdate("multiply", field, value, where, options);
615
580
  }
616
581
  /**
617
- * Same as {@link VSRepoPrisma7Adapter.incrementOne}, dividing the
618
- * field's current value by `value`. Division-by-zero is not handled by
619
- * the adapter — it's whatever Postgres does natively (raises a
620
- * `division_by_zero` error for integer columns; `Infinity`/`NaN` are not
621
- * representable in a numeric/decimal column, so those also error).
582
+ * Atomically divides `value` to `field` on the record matching `where`,
583
+ * via Prisma's native `{ field: { divide: value } }` write.
622
584
  */
623
585
  async divideOne(field, value, where, options) {
624
586
  return this.atomicUpdate("divide", field, value, where, options);
625
587
  }
588
+ /**
589
+ * Atomically adds `value` to `field` on every record matching `where`,
590
+ * via Prisma's native `{ field: { increment: value } }` write.
591
+ */
592
+ async incrementMany(field, value, where, options) {
593
+ return this.atomicUpdateMany("increment", field, value, where, options);
594
+ }
595
+ /**
596
+ * Atomically subtracts `value` from `field` on every record matching `where`,
597
+ * via Prisma's native `{ field: { decrement: value } }` write.
598
+ */
599
+ async decrementMany(field, value, where, options) {
600
+ return this.atomicUpdateMany("decrement", field, value, where, options);
601
+ }
602
+ /**
603
+ * Atomically multiplies `field` by `value` on every record matching `where`,
604
+ * via Prisma's native `{ field: { multiply: value } }` write.
605
+ */
606
+ async multiplyMany(field, value, where, options) {
607
+ return this.atomicUpdateMany("multiply", field, value, where, options);
608
+ }
609
+ /**
610
+ * Atomically divides `field` by `value` on every record matching `where`,
611
+ * via Prisma's native `{ field: { divide: value } }` write.
612
+ */
613
+ async divideMany(field, value, where, options) {
614
+ return this.atomicUpdateMany("divide", field, value, where, options);
615
+ }
626
616
  /**
627
617
  * Returns the sum of `field` across every record matching `where` (all
628
618
  * records if `where` is empty), or `null` if no record matches.
@@ -659,19 +649,12 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
659
649
  switch (this.provider) {
660
650
  case "postgresql":
661
651
  case "cockroachdb":
662
- return `$${index + 1}`;
652
+ return getPostgresPlaceholder(index);
663
653
  case "mysql":
664
654
  case "sqlite":
665
- return "?";
655
+ return getSqlitePlaceholder(index);
666
656
  case "sqlserver":
667
- return `@P${index + 1}`;
668
- default:
669
- throw new vsrepo_1.VSRepoAdapterError("Cannot resolve the raw-query placeholder syntax: the Prisma provider couldn't be detected from the client, " +
670
- "and no 'provider' was set in the adapter config. Set 'provider' in the VSRepoPrisma7Adapter config (one of: " +
671
- "postgresql, cockroachdb, mysql, sqlite, sqlserver) to enable raw-query placeholder compilation " +
672
- "(e.g. VSSql fragments and 'vsPlaceholders').", vsrepo_1.AdapterErrorCode.NOT_SUPPORTED, null);
657
+ return getSqlServerPlaceholder(index);
673
658
  }
674
659
  }
675
660
  }
676
- exports.VSRepoPrisma7Adapter = VSRepoPrisma7Adapter;
677
- //# sourceMappingURL=prisma7.adapter.js.map