@vsrepo/prisma7-adapter 1.0.0 → 1.0.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.
package/README.md CHANGED
@@ -34,6 +34,7 @@
34
34
  - [`relations` in method options (read)](#relations-in-method-options-read)
35
35
  - [`merge`](#merge)
36
36
  - [`createMany`/`createManyReturning`/`updateMany`/`updateManyReturning` don't support nested writes](#createmanycreatemanyreturningupdatemanyupdatemanyreturning-dont-support-nested-writes)
37
+ - [Provider-specific limitations](#provider-specific-limitations)
37
38
  - [Transactions](#transactions)
38
39
  - [Logging](#logging)
39
40
  - [Requirements](#requirements)
@@ -202,6 +203,18 @@ For to-many relations (`otm`/`mtm`), items in the stored record and items in `ob
202
203
 
203
204
  > Note on return order: `createManyReturning` don't guarantee the returned records follow the order of the input payload (`objs`). Their result comes from a second `findMany` (re-querying the inserted/updated rows by primary key), so the order is only guaranteed when you pass `order` in the options.
204
205
 
206
+ ## Provider-specific limitations
207
+
208
+ Some Prisma features this adapter relies on aren't available on every database provider. If you use one of these features on an unsupported provider, Prisma itself will throw a validation error (or, in future versions, the adapter may validate this upfront — see below).
209
+
210
+ | Feature | Supported providers | Not supported |
211
+ | --- | --- | --- |
212
+ | `mode: "insensitive"` (used by `findByXIgnoreCase` dynamic methods) | PostgreSQL, MongoDB | MySQL, SQLite, SQL Server, CockroachDB — MySQL and SQL Server are case-insensitive by default, so no `mode` is needed there; SQLite is only case-insensitive for ASCII characters |
213
+ | `createManyReturning` / `updateManyReturning` (built on Prisma's `createManyAndReturn`/`updateManyAndReturn`) | PostgreSQL, CockroachDB, SQLite | MySQL, SQL Server, MongoDB |
214
+ | `skipDuplicates` on `createManyIgnoreConflicts` / `createManyReturningIgnoreConflicts` | PostgreSQL, MySQL, CockroachDB | MongoDB, SQL Server, SQLite |
215
+
216
+ > These limitations come from Prisma itself, not from this adapter — see [Prisma's case sensitivity docs](https://www.prisma.io/docs/orm/v7/reference/prisma-client-reference#mode) and [CRUD reference](https://www.prisma.io/docs/orm/v7/prisma-client/queries/crud) for details.
217
+
205
218
  ## Transactions
206
219
 
207
220
  **Every** method accepts `options.db` and runs its operation on the client/transaction you pass — the difference is in **how** each one treats it:
package/README.pt-BR.md CHANGED
@@ -34,6 +34,7 @@ Implementação de `VSRepoAdapter` para o [VSRepository v2](https://github.com/j
34
34
  - [`relations` nas options (leitura)](#relations-nas-options-leitura)
35
35
  - [`merge`](#merge)
36
36
  - [`createMany`/`createManyReturning`/`updateMany`/`updateManyReturning` não suportam nested writes](#createmanycreatemanyreturningupdatemanyupdatemanyreturning-não-suportam-nested-writes)
37
+ - [Limitações por provider](#limitações-por-provider)
37
38
  - [Transactions](#transactions)
38
39
  - [Logging](#logging)
39
40
  - [Requisitos](#requisitos)
@@ -202,6 +203,18 @@ Pra relations to-many (`otm`/`mtm`), os itens do registro salvo e os itens de `o
202
203
 
203
204
  > Nota sobre a ordem de retorno: `createManyReturning` não garante que os registros devolvidos seguem a ordem do payload de entrada (`objs`). O resultado vem de um segundo `findMany` (re-buscando as linhas inseridas/atualizadas pela primary key), então a ordem só é garantida quando você passa `order` nas options.
204
205
 
206
+ ## Limitações por provider
207
+
208
+ Alguns recursos do Prisma que esse adapter usa não estão disponíveis em todo banco. Se você usar um desses recursos num provider sem suporte, o próprio Prisma lança um erro de validação (ou, em versões futuras, o adapter pode validar isso antecipadamente — ver abaixo).
209
+
210
+ | Recurso | Providers com suporte | Sem suporte |
211
+ | --- | --- | --- |
212
+ | `mode: "insensitive"` (usado pelos métodos dinâmicos `findByXIgnoreCase`) | PostgreSQL, MongoDB | MySQL, SQLite, SQL Server, CockroachDB — MySQL e SQL Server já são case-insensitive por padrão, então não precisam de `mode`; SQLite só é case-insensitive pra caracteres ASCII |
213
+ | `createManyReturning` / `updateManyReturning` (baseados no `createManyAndReturn`/`updateManyAndReturn` do Prisma) | PostgreSQL, CockroachDB, SQLite | MySQL, SQL Server, MongoDB |
214
+ | `skipDuplicates` no `createManyIgnoreConflicts` / `createManyReturningIgnoreConflicts` | PostgreSQL, MySQL, CockroachDB | MongoDB, SQL Server, SQLite |
215
+
216
+ > Essas limitações vêm do próprio Prisma, não do adapter — veja a [doc de case sensitivity](https://www.prisma.io/docs/orm/v7/reference/prisma-client-reference#mode) e a [referência de CRUD](https://www.prisma.io/docs/orm/v7/prisma-client/queries/crud) do Prisma pra mais detalhes.
217
+
205
218
  ## Transactions
206
219
 
207
220
  **Todos** os métodos aceitam `options.db` e executam a operação no client/transaction passado — a diferença está em **como** cada um o trata:
@@ -40,7 +40,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
40
40
  this.tableName = validated.tableName;
41
41
  this.pkName = validated.pkName;
42
42
  this.relations = validated.relations;
43
- this.logger = new vsrepo_1.VSLogger(validated.logLevel ?? vsrepo_1.VSLogLevel.WARN, this.constructor.name + "Logger");
43
+ this.logger = new vsrepo_1.VSLogger(validated.logLevel ?? vsrepo_1.VSLogLevel.WARN, this.constructor.name + "Logger", validated.logSlowThresholdMs);
44
44
  this.logger.logInfo(`${this.constructor.name} initialized for table '${this.tableName}' (pkName: '${this.pkName}'${this.relations ? `, relations: [${Object.keys(this.relations).join(", ")}]` : ""})`);
45
45
  }
46
46
  getPrismaRepository(db) {
@@ -121,7 +121,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
121
121
  }
122
122
  /** Fetches a single record matching `where`. */
123
123
  async findOne(where, options) {
124
- const start = this.logger.startPerformLog("findOne");
124
+ const start = this.logger.startPerformLog("run findOne");
125
125
  try {
126
126
  const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
127
127
  this.logger.logDebug("Resolved Prisma arg for 'findOne'", arg);
@@ -136,7 +136,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
136
136
  }
137
137
  /** Fetches a single record matching `where`, throwing if none is found. */
138
138
  async findOneOrThrow(where, options) {
139
- const start = this.logger.startPerformLog("findOneOrThrow");
139
+ const start = this.logger.startPerformLog("run findOneOrThrow");
140
140
  try {
141
141
  const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
142
142
  this.logger.logDebug("Resolved Prisma arg for 'findOneOrThrow'", arg);
@@ -151,7 +151,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
151
151
  }
152
152
  /** Fetches all records matching `where`. */
153
153
  async findMany(where, options) {
154
- const start = this.logger.startPerformLog("findMany");
154
+ const start = this.logger.startPerformLog("run findMany");
155
155
  try {
156
156
  const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
157
157
  this.logger.logDebug("Resolved Prisma arg for 'findMany'", arg);
@@ -166,7 +166,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
166
166
  }
167
167
  /** Creates or updates (upsert) a single record. */
168
168
  async save(obj, options) {
169
- const start = this.logger.startPerformLog("save");
169
+ const start = this.logger.startPerformLog("run save");
170
170
  try {
171
171
  const objAny = obj;
172
172
  const pkValue = objAny[this.pkName];
@@ -197,7 +197,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
197
197
  * `runTransactional`).
198
198
  */
199
199
  async saveMany(objs, options) {
200
- const start = this.logger.startPerformLog("saveMany");
200
+ const start = this.logger.startPerformLog("run saveMany");
201
201
  try {
202
202
  this.logger.logDebug(`Saving ${objs.length} record(s) individually inside a transaction`);
203
203
  return await this.runTransactional(options?.db, tx => Promise.all(objs.map(obj => this.save(obj, { ...options, db: tx }))));
@@ -211,7 +211,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
211
211
  }
212
212
  /** Deletes a single record matching `where`. */
213
213
  async delete(where, options) {
214
- const start = this.logger.startPerformLog("delete");
214
+ const start = this.logger.startPerformLog("run delete");
215
215
  try {
216
216
  const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
217
217
  this.logger.logDebug("Resolved Prisma arg for 'delete'", arg);
@@ -226,7 +226,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
226
226
  }
227
227
  /** Deletes every record matching `where`, returning the count of affected rows. */
228
228
  async deleteMany(where, options) {
229
- const start = this.logger.startPerformLog("deleteMany");
229
+ const start = this.logger.startPerformLog("run deleteMany");
230
230
  try {
231
231
  const arg = { where: (0, where_parser_1.parsePrismaWhere)(where) };
232
232
  this.logger.logDebug("Resolved Prisma arg for 'deleteMany'", arg);
@@ -247,7 +247,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
247
247
  * the one starting the transaction.
248
248
  */
249
249
  async deleteManyReturning(where, options) {
250
- const start = this.logger.startPerformLog("deleteManyReturning");
250
+ const start = this.logger.startPerformLog("run deleteManyReturning");
251
251
  try {
252
252
  const prismaWhere = (0, where_parser_1.parsePrismaWhere)(where);
253
253
  const findArg = { ...this.resolveReadArg(options), where: prismaWhere };
@@ -272,7 +272,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
272
272
  }
273
273
  /** Updates a single record matching `where`. */
274
274
  async update(where, obj, options) {
275
- const start = this.logger.startPerformLog("update");
275
+ const start = this.logger.startPerformLog("run update");
276
276
  try {
277
277
  const { update } = (0, data_parser_1.parsePrismaWriteData)(obj, this.pkName, this.relations);
278
278
  const arg = {
@@ -292,7 +292,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
292
292
  }
293
293
  /** Updates every record matching `where`, returning the count of affected rows. */
294
294
  async updateMany(where, obj, options) {
295
- const start = this.logger.startPerformLog("updateMany");
295
+ const start = this.logger.startPerformLog("run updateMany");
296
296
  try {
297
297
  const data = this.stripRelationFields(obj);
298
298
  const arg = { where: (0, where_parser_1.parsePrismaWhere)(where), data };
@@ -308,7 +308,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
308
308
  }
309
309
  /** Updates every record matching `where`, returning the updated records. */
310
310
  async updateManyReturning(where, obj, options) {
311
- const start = this.logger.startPerformLog("updateManyReturning");
311
+ const start = this.logger.startPerformLog("run updateManyReturning");
312
312
  try {
313
313
  const data = this.stripRelationFields(obj);
314
314
  const readArg = this.resolveReadArg(options);
@@ -341,7 +341,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
341
341
  }
342
342
  /** Returns the number of records matching `where`. */
343
343
  async count(where, options) {
344
- const start = this.logger.startPerformLog("count");
344
+ const start = this.logger.startPerformLog("run count");
345
345
  try {
346
346
  const arg = { where: (0, where_parser_1.parsePrismaWhere)(where) };
347
347
  this.logger.logDebug("Resolved Prisma arg for 'count'", arg);
@@ -356,7 +356,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
356
356
  }
357
357
  /** Checks whether at least one record matching `where` exists. */
358
358
  async exists(where, options) {
359
- const start = this.logger.startPerformLog("exists");
359
+ const start = this.logger.startPerformLog("run exists");
360
360
  try {
361
361
  const arg = { where: (0, where_parser_1.parsePrismaWhere)(where), select: { [this.pkName]: true } };
362
362
  this.logger.logDebug("Resolved Prisma arg for 'exists'", arg);
@@ -391,7 +391,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
391
391
  }
392
392
  /** Creates a single record. */
393
393
  async create(obj, options) {
394
- const start = this.logger.startPerformLog("create");
394
+ const start = this.logger.startPerformLog("run create");
395
395
  try {
396
396
  const { create } = (0, data_parser_1.parsePrismaWriteData)(obj, this.pkName, this.relations);
397
397
  const arg = { ...this.resolveReadArg(options), data: create };
@@ -411,7 +411,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
411
411
  * support nested writes.
412
412
  */
413
413
  async createMany(objs, options) {
414
- const start = this.logger.startPerformLog("createMany");
414
+ const start = this.logger.startPerformLog("run createMany");
415
415
  try {
416
416
  const data = objs.map(obj => this.stripRelationFields(obj));
417
417
  const arg = { data, skipDuplicates: options?.ignoreConflicts };
@@ -429,7 +429,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
429
429
  * Creates multiple records in a single operation, returning the created records.
430
430
  */
431
431
  async createManyReturning(objs, options) {
432
- const start = this.logger.startPerformLog("createManyReturning");
432
+ const start = this.logger.startPerformLog("run createManyReturning");
433
433
  try {
434
434
  const data = objs.map(obj => this.stripRelationFields(obj));
435
435
  const readArg = this.resolveReadArg(options);
@@ -463,7 +463,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
463
463
  * what to do with the result (e.g. call `save` next).
464
464
  */
465
465
  async merge(where, obj, options) {
466
- const start = this.logger.startPerformLog("merge");
466
+ const start = this.logger.startPerformLog("run merge");
467
467
  try {
468
468
  const arg = { ...this.resolveReadArg(options), where: (0, where_parser_1.parsePrismaWhere)(where) };
469
469
  this.logger.logDebug("Resolved Prisma arg for 'merge'", arg);
@@ -481,7 +481,7 @@ class VSRepoPrisma7Adapter extends vsrepo_1.VSRepoAdapter {
481
481
  }
482
482
  /** Creates a record if none matches `where`, otherwise updates it. */
483
483
  async upsert(where, create, update, options) {
484
- const start = this.logger.startPerformLog("upsert");
484
+ const start = this.logger.startPerformLog("run upsert");
485
485
  try {
486
486
  const parsedCreate = (0, data_parser_1.parsePrismaWriteData)(create, this.pkName, this.relations).create;
487
487
  const parsedUpdate = (0, data_parser_1.parsePrismaWriteData)(update, this.pkName, this.relations).update;
@@ -46,7 +46,12 @@ function mergeToManyRelation(target, source, relationPk) {
46
46
  }
47
47
  function mergeEntities(result, obj, relations) {
48
48
  if (!relations) {
49
- return (0, deepmerge_1.default)(result, obj, {
49
+ const definedObj = {};
50
+ for (const key of Object.keys(obj)) {
51
+ if (obj[key] !== undefined)
52
+ definedObj[key] = obj[key];
53
+ }
54
+ return (0, deepmerge_1.default)(result, definedObj, {
50
55
  arrayMerge: (target, source) => target.concat(source),
51
56
  });
52
57
  }
@@ -19,4 +19,8 @@ export interface VSRepoPrisma7AdapterConfig<T = any> {
19
19
  relations?: AdapterRelations<T>;
20
20
  /** Minimum log level for the adapter's internal `VSLogger`. @default VSLogLevel.WARN */
21
21
  logLevel?: VSLogLevel;
22
+ /**
23
+ * Duration (in ms) above which a finished operation is logged, flagging potentially slow queries. Defaults to 300ms.
24
+ */
25
+ logSlowThresholdMs?: number;
22
26
  }
package/package.json CHANGED
@@ -1,84 +1,84 @@
1
- {
2
- "name": "@vsrepo/prisma7-adapter",
3
- "version": "1.0.0",
4
- "description": "VSRepository adapter implementation backed by Prisma 7, translating every VSRepository operation into Prisma Client calls.",
5
- "homepage": "https://github.com/jaobrabo123/VSRepoPrisma7Adapter#readme",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/jaobrabo123/VSRepoPrisma7Adapter.git"
9
- },
10
- "main": "./dist/index.js",
11
- "types": "./dist/index.d.ts",
12
- "exports": {
13
- ".": {
14
- "types": "./dist/index.d.ts",
15
- "import": "./dist/index.js",
16
- "require": "./dist/index.js"
17
- }
18
- },
19
- "type": "commonjs",
20
- "files": [
21
- "dist",
22
- "README.md",
23
- "README.pt-BR.md"
24
- ],
25
- "engines": {
26
- "node": ">=18"
27
- },
28
- "scripts": {
29
- "clean": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\"",
30
- "build": "npm run clean && tsc -p tsconfig.build.json",
31
- "prepack": "npm run build",
32
- "typecheck": "tsc --noEmit -p tsconfig.build.json",
33
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
34
- "test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch",
35
- "test:types": "tsc --noEmit -p tests/tsconfig.json"
36
- },
37
- "keywords": [
38
- "prisma",
39
- "prisma7",
40
- "repository",
41
- "orm",
42
- "typescript",
43
- "repository-pattern",
44
- "vsrepo",
45
- "vsrepository",
46
- "adapter"
47
- ],
48
- "author": "João Pedro Azevedo Freire Mecenas",
49
- "license": "MIT",
50
- "peerDependencies": {
51
- "@prisma/client": "^7.10.0",
52
- "vsrepo": "^2.0.0"
53
- },
54
- "dependencies": {
55
- "deepmerge": "^4.3.1",
56
- "valibot": "^1.4.2"
57
- },
58
- "devDependencies": {
59
- "@babel/core": "^7.29.7",
60
- "@babel/plugin-proposal-decorators": "^7.29.7",
61
- "@babel/preset-env": "^7.29.7",
62
- "@babel/preset-typescript": "^7.29.7",
63
- "@jest/globals": "^30.5.0",
64
- "@prisma/adapter-pg": "^7.10.0",
65
- "@types/jest": "^30.0.0",
66
- "@types/node": "^26.4.0",
67
- "@types/pg": "^8.23.1",
68
- "babel-jest": "^30.5.0",
69
- "cross-env": "^10.1.0",
70
- "dotenv": "^17.4.2",
71
- "jest": "^30.5.0",
72
- "pg": "^8.23.0",
73
- "prisma": "^7.10.0",
74
- "tsx": "^4.23.12",
75
- "typescript": "^7.0.2"
76
- },
77
- "allowScripts": {
78
- "prisma@7.10.0": true,
79
- "@parcel/watcher@2.6.0": true,
80
- "unrs-resolver@1.12.2": true,
81
- "@prisma/engines@7.10.0": true,
82
- "esbuild@0.28.2": true
83
- }
84
- }
1
+ {
2
+ "name": "@vsrepo/prisma7-adapter",
3
+ "version": "1.0.1",
4
+ "description": "VSRepository adapter implementation backed by Prisma 7, translating every VSRepository operation into Prisma Client calls.",
5
+ "homepage": "https://github.com/jaobrabo123/VSRepoPrisma7Adapter#readme",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/jaobrabo123/VSRepoPrisma7Adapter.git"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js",
16
+ "require": "./dist/index.js"
17
+ }
18
+ },
19
+ "type": "commonjs",
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "README.pt-BR.md"
24
+ ],
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "scripts": {
29
+ "clean": "node -e \"fs.rmSync('dist',{recursive:true,force:true})\"",
30
+ "build": "npm run clean && tsc -p tsconfig.build.json",
31
+ "prepack": "npm run build",
32
+ "typecheck": "tsc --noEmit -p tsconfig.build.json",
33
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest",
34
+ "test:watch": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --watch",
35
+ "test:types": "tsc --noEmit -p tests/tsconfig.json"
36
+ },
37
+ "keywords": [
38
+ "prisma",
39
+ "prisma7",
40
+ "repository",
41
+ "orm",
42
+ "typescript",
43
+ "repository-pattern",
44
+ "vsrepo",
45
+ "vsrepository",
46
+ "adapter"
47
+ ],
48
+ "author": "João Pedro Azevedo Freire Mecenas",
49
+ "license": "MIT",
50
+ "peerDependencies": {
51
+ "@prisma/client": "^7.10.0",
52
+ "vsrepo": "^2.0.0"
53
+ },
54
+ "dependencies": {
55
+ "deepmerge": "^4.3.1",
56
+ "valibot": "^1.4.2"
57
+ },
58
+ "devDependencies": {
59
+ "@babel/core": "^7.29.7",
60
+ "@babel/plugin-proposal-decorators": "^7.29.7",
61
+ "@babel/preset-env": "^7.29.7",
62
+ "@babel/preset-typescript": "^7.29.7",
63
+ "@jest/globals": "^30.5.0",
64
+ "@prisma/adapter-pg": "^7.10.0",
65
+ "@types/jest": "^30.0.0",
66
+ "@types/node": "^26.4.0",
67
+ "@types/pg": "^8.23.1",
68
+ "babel-jest": "^30.5.0",
69
+ "cross-env": "^10.1.0",
70
+ "dotenv": "^17.4.2",
71
+ "jest": "^30.5.0",
72
+ "pg": "^8.23.0",
73
+ "prisma": "^7.10.0",
74
+ "tsx": "^4.23.12",
75
+ "typescript": "^7.0.2"
76
+ },
77
+ "allowScripts": {
78
+ "prisma@7.10.0": true,
79
+ "@parcel/watcher@2.6.0": true,
80
+ "unrs-resolver@1.12.2": true,
81
+ "@prisma/engines@7.10.0": true,
82
+ "esbuild@0.28.2": true
83
+ }
84
+ }