vsrepo 2.2.0 → 2.3.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.
- package/README.md +112 -108
- package/README.pt-BR.md +148 -144
- package/dist/VSRepoAdapter.js +1 -0
- package/dist/VSRepoAdapter.js.map +1 -0
- package/dist/VSRepository.d.ts +3 -8
- package/dist/VSRepository.js +4 -2
- package/dist/VSRepository.js.map +1 -0
- package/dist/decorators/dynamic-method.decorator.js +1 -0
- package/dist/decorators/dynamic-method.decorator.js.map +1 -0
- package/dist/decorators/query-method.decorator.d.ts +7 -4
- package/dist/decorators/query-method.decorator.js +8 -4
- package/dist/decorators/query-method.decorator.js.map +1 -0
- package/dist/errors/VSRepoAdapterError.js +1 -0
- package/dist/errors/VSRepoAdapterError.js.map +1 -0
- package/dist/errors/VSRepoError.js +1 -0
- package/dist/errors/VSRepoError.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/constants/debug-arg-symbol.constant.js +1 -0
- package/dist/internal/constants/debug-arg-symbol.constant.js.map +1 -0
- package/dist/internal/constants/dynamic-methods-key.constant.js +1 -0
- package/dist/internal/constants/dynamic-methods-key.constant.js.map +1 -0
- package/dist/internal/constants/query-methods-key.constant.js +1 -0
- package/dist/internal/constants/query-methods-key.constant.js.map +1 -0
- package/dist/internal/enums/adapter-error-code.enum.d.ts +4 -0
- package/dist/internal/enums/adapter-error-code.enum.js +5 -0
- package/dist/internal/enums/adapter-error-code.enum.js.map +1 -0
- package/dist/internal/enums/transaction-isolation-level.enum.js +1 -0
- package/dist/internal/enums/transaction-isolation-level.enum.js.map +1 -0
- package/dist/internal/enums/vs-log-level.enum.js +1 -0
- package/dist/internal/enums/vs-log-level.enum.js.map +1 -0
- package/dist/internal/enums/vsrepo-error-type.enum.js +1 -0
- package/dist/internal/enums/vsrepo-error-type.enum.js.map +1 -0
- package/dist/internal/resolvers/dynamic-methods.resolver.js +1 -0
- package/dist/internal/resolvers/dynamic-methods.resolver.js.map +1 -0
- package/dist/internal/resolvers/merge-wheres.resolver.js +1 -0
- package/dist/internal/resolvers/merge-wheres.resolver.js.map +1 -0
- package/dist/internal/utils/db-arg.util.js +1 -0
- package/dist/internal/utils/db-arg.util.js.map +1 -0
- package/dist/internal/utils/uncapitalize.util.js +1 -0
- package/dist/internal/utils/uncapitalize.util.js.map +1 -0
- package/dist/internal/utils/vs-logger.util.js +1 -0
- package/dist/internal/utils/vs-logger.util.js.map +1 -0
- package/dist/internal/utils/with-db.util.js +1 -0
- package/dist/internal/utils/with-db.util.js.map +1 -0
- package/dist/internal/validators/decorators.validator.js +1 -0
- package/dist/internal/validators/decorators.validator.js.map +1 -0
- package/dist/internal/validators/schemas/ordering.schema.js +1 -0
- package/dist/internal/validators/schemas/ordering.schema.js.map +1 -0
- package/dist/internal/validators/schemas/pagination.schema.js +1 -0
- package/dist/internal/validators/schemas/pagination.schema.js.map +1 -0
- package/dist/internal/validators/schemas/where.schema.js +1 -0
- package/dist/internal/validators/schemas/where.schema.js.map +1 -0
- package/dist/internal/validators/vsrepo.validator.js +1 -0
- package/dist/internal/validators/vsrepo.validator.js.map +1 -0
- package/dist/types/adapter/adapter-method-options.type.js +1 -0
- package/dist/types/adapter/adapter-method-options.type.js.map +1 -0
- package/dist/types/adapter/adapter-query-options.type.js +1 -0
- package/dist/types/adapter/adapter-query-options.type.js.map +1 -0
- package/dist/types/decorators/dynamic-method-options.type.js +1 -0
- package/dist/types/decorators/dynamic-method-options.type.js.map +1 -0
- package/dist/types/decorators/query-method-options.type.js +1 -0
- package/dist/types/decorators/query-method-options.type.js.map +1 -0
- package/dist/types/dynamic-methods/dynamic-method-customization.type.js +1 -0
- package/dist/types/dynamic-methods/dynamic-method-customization.type.js.map +1 -0
- package/dist/types/dynamic-methods/dynamic-method-info.type.js +1 -0
- package/dist/types/dynamic-methods/dynamic-method-info.type.js.map +1 -0
- package/dist/types/dynamic-methods/dynamic-method-where-ops.type.js +1 -0
- package/dist/types/dynamic-methods/dynamic-method-where-ops.type.js.map +1 -0
- package/dist/types/utils/count-result.type.js +1 -0
- package/dist/types/utils/count-result.type.js.map +1 -0
- package/dist/types/utils/decimal-like.type.js +1 -0
- package/dist/types/utils/decimal-like.type.js.map +1 -0
- package/dist/types/utils/deep-partial.type.js +1 -0
- package/dist/types/utils/deep-partial.type.js.map +1 -0
- package/dist/types/utils/keys-of-type.type.js +1 -0
- package/dist/types/utils/keys-of-type.type.js.map +1 -0
- package/dist/types/utils/methods-options.type.js +1 -0
- package/dist/types/utils/methods-options.type.js.map +1 -0
- package/dist/types/utils/numeric-keys.type.js +1 -0
- package/dist/types/utils/numeric-keys.type.js.map +1 -0
- package/dist/types/utils/numeric-like.type.js +1 -0
- package/dist/types/utils/numeric-like.type.js.map +1 -0
- package/dist/types/utils/ordering.type.js +1 -0
- package/dist/types/utils/ordering.type.js.map +1 -0
- package/dist/types/utils/pagination.type.js +1 -0
- package/dist/types/utils/pagination.type.js.map +1 -0
- package/dist/types/utils/perform-data.type.js +1 -0
- package/dist/types/utils/perform-data.type.js.map +1 -0
- package/dist/types/utils/primitive.type.js +1 -0
- package/dist/types/utils/primitive.type.js.map +1 -0
- package/dist/types/utils/query-args.type.js +1 -0
- package/dist/types/utils/query-args.type.js.map +1 -0
- package/dist/types/utils/query-method-arg.type.d.ts +4 -2
- package/dist/types/utils/query-method-arg.type.js +1 -0
- package/dist/types/utils/query-method-arg.type.js.map +1 -0
- package/dist/types/utils/restrict-method-options.type.js +1 -0
- package/dist/types/utils/restrict-method-options.type.js.map +1 -0
- package/dist/types/utils/see-mode.type.js +1 -0
- package/dist/types/utils/see-mode.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-args.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-args.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-method.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-method.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-options.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-options.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-orm-types.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-orm-types.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-pretty-where.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-pretty-where.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-query-options.type.d.ts +1 -1
- package/dist/types/vsrepo/vsrepo-query-options.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-query-options.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-query.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-query.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-relations.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-relations.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-resolve-args-data.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-resolve-args-data.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-select.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-select.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-transaction-options.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-transaction-options.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-ugly-where.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-ugly-where.type.js.map +1 -0
- package/dist/types/vsrepo/vsrepo-where.type.js +1 -0
- package/dist/types/vsrepo/vsrepo-where.type.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,12 +99,13 @@ VSRepository v2 is **ORM-agnostic by design**. The core package (`vsrepo`) only
|
|
|
99
99
|
|
|
100
100
|
The Prisma 7 adapter has now been published to npm as `@vsrepo/prisma7-adapter` — it's currently the **only** published adapter. Adapters for the other ORMs listed above (Prisma 8, TypeORM, Drizzle) are **planned**; they just haven't been published yet. Until an official `@vsrepo/*-adapter` package exists for your ORM, you're welcome to write your own for your project, and if you'd like, publish it and open a PR to help grow the ecosystem — contributions here are very welcome.
|
|
101
101
|
|
|
102
|
-
| Adapter
|
|
103
|
-
|
|
|
104
|
-
| Prisma 7 (`@vsrepo/prisma7-adapter`)
|
|
105
|
-
|
|
|
106
|
-
|
|
|
107
|
-
|
|
|
102
|
+
| Adapter | Status |
|
|
103
|
+
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
104
|
+
| Prisma 7 (`@vsrepo/prisma7-adapter`) | 🟢 **Released** — published to npm, implements the `VSRepoAdapter` contract (CRUD, relations, transactions, `merge`, logging) with tests; see [`VSRepoPrisma7Adapter`](https://github.com/jaobrabo123/VSRepoPrisma7Adapter) for source and docs. **Note:** the atomic/aggregate methods (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — see [Atomic and aggregate methods](#atomic-and-aggregate-methods)) were added to the `VSRepoAdapter` contract after this adapter's last release; confirm its changelog/version implements them before relying on `increment`/`sum`/etc. against Prisma 7. |
|
|
105
|
+
| Drizzle (`@vsrepo/drizzle-adapter`) | 🔵 **In development** — The adapter for Drizzle ORM is currently under development and accepts community contributions; check the current status of the [`DrizzleAdapter`](https://github.com/jaobrabo123/VSRepoDrizzleAdapter) |
|
|
106
|
+
| TypeORM (`@vsrepo/typeorm-adapter`) | 🟡 **Planned, not published yet.** Only a reference `where`-clause parser (`parseVSRepoWhere`) was written to validate the design; it's the planned starting point for the future `@vsrepo/typeorm-adapter` package. Community contributions toward this are welcome. |
|
|
107
|
+
| Other ORMs (Prisma 8, Drizzle, etc.) | 🟡 **Planned, not published yet.** No official package exists yet — write your own adapter for now (see [Writing your own adapter](#writing-your-own-adapter)), and consider publishing/contributing it back. |
|
|
108
|
+
| Custom adapters | 🟢 Fully supported today — implement the [`VSRepoAdapter`](#writing-your-own-adapter) abstract class yourself for any ORM/database you need, in your own project or package, following the same shape as `@vsrepo/*-adapter` is expected to have. |
|
|
108
109
|
|
|
109
110
|
In short: the repository class, the `@DynamicMethod`/`@QueryMethod` decorators, the name-parsing engine, error handling and logging are all working end-to-end, and Prisma 7 support is now a released, published adapter. Official adapters for the remaining ORMs are on the roadmap and will ship as separate `@vsrepo/*-adapter` packages rather than as part of the core `vsrepo` package — but you don't have to wait for that: writing (and optionally publishing) your own adapter in the meantime is a fully supported way to use v2 today and to contribute back to the project.
|
|
110
111
|
|
|
@@ -172,6 +173,7 @@ export default new UserRepository();
|
|
|
172
173
|
> The core API (`VSRepository`, `VSRepoAdapter`, `DynamicMethod`, `QueryMethod`, `VSRepoError`, enums and types) is imported from the single `vsrepo` entry point. The concrete adapter comes from a **separate** package (`@vsrepo/*-adapter`). On Prisma 7, install the published [`@vsrepo/prisma7-adapter`](https://github.com/jaobrabo123/VSRepoPrisma7Adapter) (its constructor takes a config object — `tableName`, `pkName`, optional `relations`/`logLevel` — as shown above). Official adapters for other ORMs are planned but not published yet; until they are, you can implement the `VSRepoAdapter` contract yourself (see [Writing your own adapter](#writing-your-own-adapter)) — and publishing it to help the project is very welcome.
|
|
173
174
|
|
|
174
175
|
> **The third generic parameter (`OrmTypes`):** `VSRepository<Entity, PKType, OrmTypes>` accepts an optional third type parameter describing your ORM's client/transaction types, via `VSRepoOrmTypes` (`{ dbClient; dbTransaction }`). Supplying it gives you a correctly-typed `getDbClient()`, `transaction()` callback, and `db` option on every method, instead of `any`:
|
|
176
|
+
>
|
|
175
177
|
> ```typescript
|
|
176
178
|
> type PrismaOrmTypes = { dbClient: PrismaClient; dbTransaction: Prisma.TransactionClient };
|
|
177
179
|
>
|
|
@@ -179,6 +181,7 @@ export default new UserRepository();
|
|
|
179
181
|
> // getDbClient() now returns PrismaClient, and transaction(fn) types `tx` as Prisma.TransactionClient
|
|
180
182
|
> }
|
|
181
183
|
> ```
|
|
184
|
+
>
|
|
182
185
|
> If omitted, it defaults to `VSRepoOrmTypes` (`dbClient`/`dbTransaction` both `any`).
|
|
183
186
|
|
|
184
187
|
### Using the repository
|
|
@@ -221,31 +224,31 @@ await userRepository.remove(user.id);
|
|
|
221
224
|
|
|
222
225
|
Available automatically on every `VSRepository` subclass:
|
|
223
226
|
|
|
224
|
-
| Method
|
|
225
|
-
|
|
|
226
|
-
| `get(pk, options?)`
|
|
227
|
-
| `getOrThrow(pk, options?)`
|
|
228
|
-
| `getList(pks, options?)`
|
|
229
|
-
| `getAll(options?)`
|
|
230
|
-
| `save(obj, options?)`
|
|
231
|
-
| `saveList(objs, options?)`
|
|
232
|
-
| `patch(pk, obj, options?)`
|
|
233
|
-
| `merge(pk, obj, options?)`
|
|
234
|
-
| `remove(pk, options?)`
|
|
235
|
-
| `removeList(pks, options?)`
|
|
236
|
-
| `total(options?)`
|
|
237
|
-
| `has(pk, options?)`
|
|
238
|
-
| `increment(pk, field, value, options?)` | Atomically adds `value` to a numeric field. See [Atomic and aggregate methods](#atomic-and-aggregate-methods).
|
|
239
|
-
| `decrement(pk, field, value, options?)` | Atomically subtracts `value` from a numeric field.
|
|
240
|
-
| `multiply(pk, field, value, options?)` | Atomically multiplies a numeric field by `value`.
|
|
241
|
-
| `divide(pk, field, value, options?)` | Atomically divides a numeric field by `value`.
|
|
242
|
-
| `sum(field, where?, options?)` | Sums a numeric field across every matching record; `null` if none match.
|
|
243
|
-
| `average(field, where?, options?)` | Arithmetic mean of a numeric field across every matching record; `null` if none match.
|
|
244
|
-
| `min(field, where?, options?)` | Minimum value of a numeric field across every matching record; `null` if none match.
|
|
245
|
-
| `max(field, where?, options?)` | Maximum value of a numeric field across every matching record; `null` if none match.
|
|
246
|
-
| `transaction(fn, options?)`
|
|
247
|
-
| `getDbClient()`
|
|
248
|
-
| `query<T>(query, options?)`
|
|
227
|
+
| Method | Description |
|
|
228
|
+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
229
|
+
| `get(pk, options?)` | Fetches a record by primary key. |
|
|
230
|
+
| `getOrThrow(pk, options?)` | Fetches a record by primary key, throwing if not found. |
|
|
231
|
+
| `getList(pks, options?)` | Fetches multiple records by a list of primary keys. |
|
|
232
|
+
| `getAll(options?)` | Fetches all records; accepts `pagination` and `order` in `options`. |
|
|
233
|
+
| `save(obj, options?)` | Creates or updates (upsert) a single record. |
|
|
234
|
+
| `saveList(objs, options?)` | Creates or updates (upsert) multiple records in one call. |
|
|
235
|
+
| `patch(pk, obj, options?)` | Partially updates a record by primary key. |
|
|
236
|
+
| `merge(pk, obj, options?)` | Fetches a record and returns it deep-merged, in memory, with the given object — does **not** persist anything. |
|
|
237
|
+
| `remove(pk, options?)` | Deletes a record by primary key. |
|
|
238
|
+
| `removeList(pks, options?)` | Deletes multiple records by primary key, returning `{ count }`. |
|
|
239
|
+
| `total(options?)` | Returns the total number of records. |
|
|
240
|
+
| `has(pk, options?)` | Checks whether a record exists, returning `boolean`. |
|
|
241
|
+
| `increment(pk, field, value, options?)` | Atomically adds `value` to a numeric field. See [Atomic and aggregate methods](#atomic-and-aggregate-methods). |
|
|
242
|
+
| `decrement(pk, field, value, options?)` | Atomically subtracts `value` from a numeric field. |
|
|
243
|
+
| `multiply(pk, field, value, options?)` | Atomically multiplies a numeric field by `value`. |
|
|
244
|
+
| `divide(pk, field, value, options?)` | Atomically divides a numeric field by `value`. |
|
|
245
|
+
| `sum(field, where?, options?)` | Sums a numeric field across every matching record; `null` if none match. |
|
|
246
|
+
| `average(field, where?, options?)` | Arithmetic mean of a numeric field across every matching record; `null` if none match. |
|
|
247
|
+
| `min(field, where?, options?)` | Minimum value of a numeric field across every matching record; `null` if none match. |
|
|
248
|
+
| `max(field, where?, options?)` | Maximum value of a numeric field across every matching record; `null` if none match. |
|
|
249
|
+
| `transaction(fn, options?)` | Runs `fn` inside a native transaction of the underlying ORM. |
|
|
250
|
+
| `getDbClient()` | Returns the underlying ORM client instance used outside of transactions. |
|
|
251
|
+
| `query<T>(query, options?)` | Executes a raw SQL statement directly against the database. See [Ad-hoc raw queries with `query()`](#ad-hoc-raw-queries-with-query). |
|
|
249
252
|
|
|
250
253
|
Most of the above accept a `MethodOptions<Entity, OrmTypes>` object as their last argument (`select`, `relations`, `see`, `db`). A few — `total`, `has`, `removeList`, `sum`, `average`, `min`, `max`, and the soft-delete batch methods (`softRemoveList`/`restoreList`) — don't return/shape an `Entity`, so they accept the narrower `RestrictMethodOptions<Entity, OrmTypes>` instead (`see`, `db` only; no `select`/`relations`). `transaction`, `query`, and `getDbClient` accept their own options or none at all.
|
|
251
254
|
|
|
@@ -286,7 +289,7 @@ await userRepository.getAll({ see: "all" }); // everything, ignoring soft-delete
|
|
|
286
289
|
|
|
287
290
|
Every `VSRepository` subclass gets 8 extra methods for working with numeric fields, split into two groups:
|
|
288
291
|
|
|
289
|
-
**Atomic updates** — evaluated server-side against the row's
|
|
292
|
+
**Atomic updates** — evaluated server-side against the row's _current_ value (`UPDATE ... SET field = field + value`), not a client-side read-modify-write:
|
|
290
293
|
|
|
291
294
|
```typescript
|
|
292
295
|
await userRepository.increment("user-1", "balance", 50); // balance = balance + 50
|
|
@@ -334,7 +337,7 @@ Note that several ORMs (Drizzle, MikroORM, TypeORM) represent `decimal`/`numeric
|
|
|
334
337
|
|
|
335
338
|
### Writing an adapter
|
|
336
339
|
|
|
337
|
-
`VSRepoAdapter` mirrors the same 8 operations (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — see [Writing your own adapter](#writing-your-own-adapter)). Each adapter translates them into whatever its ORM/database considers "native": Prisma has a built-in `{ field: { increment: value } }` update shape and an `aggregate()` call; other ORMs typically need a `QueryBuilder`/raw-`sql` expression (e.g. `SET field = field * :value`, `SELECT SUM(field) ...`) instead. The atomic methods must return the record reflecting the state
|
|
340
|
+
`VSRepoAdapter` mirrors the same 8 operations (`incrementOne`, `decrementOne`, `multiplyOne`, `divideOne`, `sum`, `average`, `min`, `max` — see [Writing your own adapter](#writing-your-own-adapter)). Each adapter translates them into whatever its ORM/database considers "native": Prisma has a built-in `{ field: { increment: value } }` update shape and an `aggregate()` call; other ORMs typically need a `QueryBuilder`/raw-`sql` expression (e.g. `SET field = field * :value`, `SELECT SUM(field) ...`) instead. The atomic methods must return the record reflecting the state _after_ the write — if the ORM's atomic-update API only returns an affected-row count, issue a follow-up read rather than returning a stale in-memory copy.
|
|
338
341
|
|
|
339
342
|
---
|
|
340
343
|
|
|
@@ -418,38 +421,38 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
418
421
|
|
|
419
422
|
### Available prefixes
|
|
420
423
|
|
|
421
|
-
| Prefix | Adapter method | Notes
|
|
422
|
-
| -------------------------- | --------------------- |
|
|
423
|
-
| `findBy` | `findMany` | Field filters follow the prefix.
|
|
424
|
-
| `findOneBy` | `findOne` | Field filters follow the prefix; single result.
|
|
425
|
-
| `findOneOrThrowBy` | `findOneOrThrow` | Throws if no record is found.
|
|
426
|
-
| `findOneOrThrow` | `findOneOrThrow` | No field filters; applies only soft-delete/`see`.
|
|
427
|
-
| `findOneOrThrowWhere` | `findOneOrThrow` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
428
|
-
| `findWhere` | `findMany` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
429
|
-
| `findOneWhere` | `findOne` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
430
|
-
| `findOne` | `findOne` | No field filters; applies only soft-delete/`see`.
|
|
431
|
-
| `countBy` | `count` | Field filters follow the prefix.
|
|
432
|
-
| `countWhere` | `count` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
433
|
-
| `count` | `count` | No field filters.
|
|
434
|
-
| `existsBy` | `exists` | Returns `boolean`.
|
|
435
|
-
| `existsWhere` | `exists` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
436
|
-
| `create` | `create` | Receives `data` as argument.
|
|
437
|
-
| `createMany` | `createMany` | Receives `data[]` as argument; supports `IgnoreConflicts`.
|
|
424
|
+
| Prefix | Adapter method | Notes |
|
|
425
|
+
| -------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
426
|
+
| `findBy` | `findMany` | Field filters follow the prefix. |
|
|
427
|
+
| `findOneBy` | `findOne` | Field filters follow the prefix; single result. |
|
|
428
|
+
| `findOneOrThrowBy` | `findOneOrThrow` | Throws if no record is found. |
|
|
429
|
+
| `findOneOrThrow` | `findOneOrThrow` | No field filters; applies only soft-delete/`see`. |
|
|
430
|
+
| `findOneOrThrowWhere` | `findOneOrThrow` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
431
|
+
| `findWhere` | `findMany` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
432
|
+
| `findOneWhere` | `findOne` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
433
|
+
| `findOne` | `findOne` | No field filters; applies only soft-delete/`see`. |
|
|
434
|
+
| `countBy` | `count` | Field filters follow the prefix. |
|
|
435
|
+
| `countWhere` | `count` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
436
|
+
| `count` | `count` | No field filters. |
|
|
437
|
+
| `existsBy` | `exists` | Returns `boolean`. |
|
|
438
|
+
| `existsWhere` | `exists` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
439
|
+
| `create` | `create` | Receives `data` as argument. |
|
|
440
|
+
| `createMany` | `createMany` | Receives `data[]` as argument; supports `IgnoreConflicts`. |
|
|
438
441
|
| `createManyReturning` | `createManyReturning` | Receives `data[]` as argument; supports `IgnoreConflicts`; returns the created records (`T[]`) instead of `CountResult`. |
|
|
439
|
-
| `updateBy` | `update` | Field filters + `data` as argument.
|
|
440
|
-
| `updateWhere` | `update` | Receives a `VSRepoWhere<T>` as the first argument, then `data`.
|
|
441
|
-
| `updateManyBy` | `updateMany` | Field filters + `data`.
|
|
442
|
-
| `updateManyWhere` | `updateMany` | Receives a `VSRepoWhere<T>` as the first argument, then `data`.
|
|
443
|
-
| `updateManyReturningBy` | `updateManyReturning` | Field filters + `data`; returns updated records.
|
|
444
|
-
| `updateManyReturningWhere` | `updateManyReturning` | Receives a `VSRepoWhere<T>` as the first argument, then `data`; returns updated records.
|
|
445
|
-
| `upsertBy` | `upsert` | Field filters + `create`/`update` payloads.
|
|
446
|
-
| `upsertWhere` | `upsert` | Receives a `VSRepoWhere<T>` as the first argument, then `create`/`update` payloads.
|
|
447
|
-
| `deleteBy` | `delete` | Field filters follow the prefix.
|
|
448
|
-
| `deleteWhere` | `delete` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
449
|
-
| `deleteManyBy` | `deleteMany` | Field filters follow the prefix.
|
|
450
|
-
| `deleteManyWhere` | `deleteMany` | Receives a `VSRepoWhere<T>` as the first argument.
|
|
451
|
-
| `deleteManyReturningBy` | `deleteManyReturning` | Field filters follow the prefix; returns deleted records.
|
|
452
|
-
| `deleteManyReturningWhere` | `deleteManyReturning` | Receives a `VSRepoWhere<T>` as the first argument; returns deleted records.
|
|
442
|
+
| `updateBy` | `update` | Field filters + `data` as argument. |
|
|
443
|
+
| `updateWhere` | `update` | Receives a `VSRepoWhere<T>` as the first argument, then `data`. |
|
|
444
|
+
| `updateManyBy` | `updateMany` | Field filters + `data`. |
|
|
445
|
+
| `updateManyWhere` | `updateMany` | Receives a `VSRepoWhere<T>` as the first argument, then `data`. |
|
|
446
|
+
| `updateManyReturningBy` | `updateManyReturning` | Field filters + `data`; returns updated records. |
|
|
447
|
+
| `updateManyReturningWhere` | `updateManyReturning` | Receives a `VSRepoWhere<T>` as the first argument, then `data`; returns updated records. |
|
|
448
|
+
| `upsertBy` | `upsert` | Field filters + `create`/`update` payloads. |
|
|
449
|
+
| `upsertWhere` | `upsert` | Receives a `VSRepoWhere<T>` as the first argument, then `create`/`update` payloads. |
|
|
450
|
+
| `deleteBy` | `delete` | Field filters follow the prefix. |
|
|
451
|
+
| `deleteWhere` | `delete` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
452
|
+
| `deleteManyBy` | `deleteMany` | Field filters follow the prefix. |
|
|
453
|
+
| `deleteManyWhere` | `deleteMany` | Receives a `VSRepoWhere<T>` as the first argument. |
|
|
454
|
+
| `deleteManyReturningBy` | `deleteManyReturning` | Field filters follow the prefix; returns deleted records. |
|
|
455
|
+
| `deleteManyReturningWhere` | `deleteManyReturning` | Receives a `VSRepoWhere<T>` as the first argument; returns deleted records. |
|
|
453
456
|
|
|
454
457
|
> `aggregate` and `groupBy` are **not implemented yet** in v2 (they existed in v1). This is planned but not currently available.
|
|
455
458
|
|
|
@@ -590,7 +593,7 @@ declare findByStatus: (status: string) => Promise<User[]>;
|
|
|
590
593
|
|
|
591
594
|
## Query methods (raw SQL)
|
|
592
595
|
|
|
593
|
-
`@QueryMethod` bypasses the name-parsing engine entirely and executes a raw SQL statement through the adapter's `query()` method. Use
|
|
596
|
+
`@QueryMethod` bypasses the name-parsing engine entirely and executes a raw SQL statement through the adapter's `query()` method. Use placeholders for the values passed via `args` — never interpolate values directly into the SQL string. **The placeholder syntax depends on the database/driver behind your adapter:** the `$1`, `$2`, ... style used in the examples below is the PostgreSQL convention — MySQL, for instance, uses `?`. Check your adapter's documentation for the exact syntax.
|
|
594
597
|
|
|
595
598
|
```typescript
|
|
596
599
|
class UserRepository extends VSRepository<User, string> {
|
|
@@ -607,9 +610,9 @@ class UserRepository extends VSRepository<User, string> {
|
|
|
607
610
|
}
|
|
608
611
|
```
|
|
609
612
|
|
|
610
|
-
| Option | Type | Default | Description
|
|
611
|
-
| -------------- | --------- | ------- |
|
|
612
|
-
| `modifying` | `boolean` | `false` | When `true`, runs as `INSERT`/`UPDATE`/`DELETE` and the method resolves to the number of affected rows. When `false`, runs as a read query and resolves to the declared return type.
|
|
613
|
+
| Option | Type | Default | Description |
|
|
614
|
+
| -------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
615
|
+
| `modifying` | `boolean` | `false` | When `true`, runs as `INSERT`/`UPDATE`/`DELETE` and the method resolves to the number of affected rows. When `false`, runs as a read query and resolves to the declared return type. |
|
|
613
616
|
| `singleResult` | `boolean` | `false` | When `true`, collapses an array result into its first element (`null` if empty), so you can declare the return type as a single object instead of an array. Has no effect on non-array results (e.g. a `modifying` query's affected-row count). |
|
|
614
617
|
|
|
615
618
|
Query methods accept `{ args, db? }` at the call site — `db` lets them participate in a `transaction()` block just like base and dynamic methods.
|
|
@@ -634,7 +637,7 @@ const admins = await userRepository.findByEmailAndType("joao@email.com", "admin"
|
|
|
634
637
|
To run the query against a specific client or transaction instead of the repository's default one, pass `withDb(tx)` as the trailing argument — it wraps `tx` in a `DbArg`, which the resolver recognizes with `instanceof`, so it's never confused with a regular positional argument even if that argument happens to be an object:
|
|
635
638
|
|
|
636
639
|
```typescript
|
|
637
|
-
await userRepository.transaction(async
|
|
640
|
+
await userRepository.transaction(async tx => {
|
|
638
641
|
await userRepository.findByEmailAndType("joao@email.com", "admin", withDb(tx));
|
|
639
642
|
});
|
|
640
643
|
```
|
|
@@ -661,18 +664,18 @@ const affectedRows = await userRepository.query<number>(
|
|
|
661
664
|
|
|
662
665
|
// Only one row is ever expected here, so `singleResult` collapses the
|
|
663
666
|
// array into a single object (or `null` when no row matches).
|
|
664
|
-
const user = await userRepository.query<User | null>(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
);
|
|
667
|
+
const user = await userRepository.query<User | null>('SELECT * FROM "user" WHERE id = $1 LIMIT 1', {
|
|
668
|
+
args: ["123"],
|
|
669
|
+
singleResult: true,
|
|
670
|
+
});
|
|
668
671
|
```
|
|
669
672
|
|
|
670
|
-
| Option | Type | Default | Description
|
|
671
|
-
| -------------- | --------- |
|
|
672
|
-
| `args` | `any[]` | `undefined`
|
|
673
|
-
| `db` | `any` | Repository's default client
|
|
674
|
-
| `modifying` | `boolean` | `false`
|
|
675
|
-
| `singleResult` | `boolean` | `false`
|
|
673
|
+
| Option | Type | Default | Description |
|
|
674
|
+
| -------------- | --------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
675
|
+
| `args` | `any[]` | `undefined` | Positional parameters injected into the SQL placeholders — the placeholder syntax depends on the database/driver behind your adapter. Never interpolate values directly into the SQL string. |
|
|
676
|
+
| `db` | `any` | Repository's default client | Database client or transaction to run this query in. |
|
|
677
|
+
| `modifying` | `boolean` | `false` | When `true`, treats the statement as `INSERT`/`UPDATE`/`DELETE`. |
|
|
678
|
+
| `singleResult` | `boolean` | `false` | When `true`, collapses an array result into its first element (`null` if empty). Has no effect on non-array results (e.g. a `modifying` query's affected-row count). |
|
|
676
679
|
|
|
677
680
|
Just like base, dynamic and query methods, `query()` accepts `db` in `options` to participate in a `transaction()` block.
|
|
678
681
|
|
|
@@ -708,10 +711,10 @@ await userRepository.transaction(
|
|
|
708
711
|
);
|
|
709
712
|
```
|
|
710
713
|
|
|
711
|
-
| Option | Type
|
|
712
|
-
|
|
|
714
|
+
| Option | Type | Description |
|
|
715
|
+
| ---------------- | --------------------------- | ------------------------------------------------------------------------------------- |
|
|
713
716
|
| `isolationLevel` | `TransactionIsolationLevel` | Isolation level to use for the transaction. Defaults to the underlying ORM's default. |
|
|
714
|
-
| `timeoutMs`
|
|
717
|
+
| `timeoutMs` | `number` | Maximum time (in ms) the transaction is allowed to run before being aborted. |
|
|
715
718
|
|
|
716
719
|
`TransactionIsolationLevel` mirrors the standard SQL isolation levels: `READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`. Support for a given level depends on the adapter/underlying ORM and database.
|
|
717
720
|
|
|
@@ -746,26 +749,26 @@ import type {
|
|
|
746
749
|
} from "vsrepo";
|
|
747
750
|
```
|
|
748
751
|
|
|
749
|
-
| Type | Description
|
|
750
|
-
| --------------------------------------------------- |
|
|
751
|
-
| `MethodOptions<T, K>` | Options accepted as the last argument of most base and dynamic methods: `select`, `relations`, `see`, `db`.
|
|
752
|
-
| `RestrictMethodOptions<T, K>`
|
|
753
|
-
| `Pagination` | `{ limit?, offset? }` accepted by `getAll` and by `Paginated` dynamic methods.
|
|
754
|
-
| `Ordering<T>` / `OrderByField<T>` / `SortDirection` | Ordering shape accepted by `getAll`, `defaultOrdering` and `injectOrdering`, and by `Ordered` dynamic methods. A single object or a chained array; nested objects order to-one relations.
|
|
755
|
-
| `SeeMode` | `"active" \| "removed" \| "all"` — controls visibility of soft-deleted records.
|
|
756
|
-
| `DeepPartial<T>` | Recursively makes every property of `T` optional, including nested objects and array elements.
|
|
757
|
-
| `CountResult` | `{ count: number }` — the shape returned by batch operations.
|
|
758
|
-
| `QueryMethodArg<T>` | `{ args?: T, db? }` — positional SQL parameters (`$1`, `$2`, ...) and transaction client for `@QueryMethod`.
|
|
759
|
-
| `QueryArgs<T, O>` | Types the spread parameter list of a `@QueryMethod` declared with `{ spreadArgs: true }`: `T`'s values in order, followed by an optional trailing `DbArg<O>` built via `withDb()`.
|
|
760
|
-
| `KeysOfType<T, K>` | Extracts the keys of `T` whose value type is assignable to `K`.
|
|
761
|
-
| `NumericKeys<T>` | Extracts the keys of `T` whose (non-nullable) value type is assignable to `NumericLike`. Nullable numeric fields (`number \| null`) are included.
|
|
762
|
-
| `NumericLike` | `number \| bigint \| DecimalLike`.
|
|
763
|
-
| `DecimalLike` | Structural shape of an arbitrary-precision decimal value (`{ toNumber(): number; decimalPlaces(): number }`), matching e.g. Prisma's `Prisma.Decimal` without importing it directly.
|
|
764
|
-
| `Primitive` | Union of scalar types (`string \| number \| boolean \| bigint \| symbol \| undefined \| null \| Date`) treated as leaves — not relations — when walking an entity's shape.
|
|
765
|
-
| `VSRepoWhere<T>` | ORM-agnostic filter type accepted by `*Where` dynamic methods (e.g. `findWhere`, `findOneWhere`, `updateWhere`). Supports field filters, logical operators (`AND`/`OR`/`NOT`), and relation filters.
|
|
752
|
+
| Type | Description | Used by |
|
|
753
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
754
|
+
| `MethodOptions<T, K>` | Options accepted as the last argument of most base and dynamic methods: `select`, `relations`, `see`, `db`. | [Base methods](#base-methods), [Dynamic methods](#dynamic-methods). |
|
|
755
|
+
| `RestrictMethodOptions<T, K>` | Narrowed `MethodOptions<T, K>` exposing only `see`/`db` — used by methods that don't shape/return an `Entity` (`total`, `has`, `sum`, `average`, `min`, `max`, `removeList`, `softRemoveList`, `restoreList`). | [Base methods](#base-methods), [Atomic and aggregate methods](#atomic-and-aggregate-methods). |
|
|
756
|
+
| `Pagination` | `{ limit?, offset? }` accepted by `getAll` and by `Paginated` dynamic methods. | [Base methods](#base-methods), [Ordering, pagination and distinct](#ordering-pagination-and-distinct). |
|
|
757
|
+
| `Ordering<T>` / `OrderByField<T>` / `SortDirection` | Ordering shape accepted by `getAll`, `defaultOrdering` and `injectOrdering`, and by `Ordered` dynamic methods. A single object or a chained array; nested objects order to-one relations. | [Constructor options](#constructor-options), [Decorator options](#decorator-options), [Ordering, pagination and distinct](#ordering-pagination-and-distinct). |
|
|
758
|
+
| `SeeMode` | `"active" \| "removed" \| "all"` — controls visibility of soft-deleted records. | [Soft-delete](#soft-delete). |
|
|
759
|
+
| `DeepPartial<T>` | Recursively makes every property of `T` optional, including nested objects and array elements. | `save`, `saveList`, `patch`, `merge`, and every write method on `VSRepoAdapter`. |
|
|
760
|
+
| `CountResult` | `{ count: number }` — the shape returned by batch operations. | `removeList`, `softRemoveList`, `restoreList`, `createManyIgnoreConflicts`. |
|
|
761
|
+
| `QueryMethodArg<T>` | `{ args?: T, db? }` — positional SQL parameters (the placeholder syntax depends on the database/driver behind your adapter: `$1`, `$2`, ... for PostgreSQL, `?` for MySQL) and transaction client for `@QueryMethod`. | [Query methods (raw SQL)](#query-methods-raw-sql). |
|
|
762
|
+
| `QueryArgs<T, O>` | Types the spread parameter list of a `@QueryMethod` declared with `{ spreadArgs: true }`: `T`'s values in order, followed by an optional trailing `DbArg<O>` built via `withDb()`. | [Spread arguments with `spreadArgs`](#spread-arguments-with-spreadargs). |
|
|
763
|
+
| `KeysOfType<T, K>` | Extracts the keys of `T` whose value type is assignable to `K`. | Constrains `pkName` in [Constructor options](#constructor-options) to fields of the entity matching the configured primary-key type. |
|
|
764
|
+
| `NumericKeys<T>` | Extracts the keys of `T` whose (non-nullable) value type is assignable to `NumericLike`. Nullable numeric fields (`number \| null`) are included. | Constrains `field` in [Atomic and aggregate methods](#atomic-and-aggregate-methods) (`increment`, `sum`, etc). |
|
|
765
|
+
| `NumericLike` | `number \| bigint \| DecimalLike`. | [Atomic and aggregate methods](#atomic-and-aggregate-methods). |
|
|
766
|
+
| `DecimalLike` | Structural shape of an arbitrary-precision decimal value (`{ toNumber(): number; decimalPlaces(): number }`), matching e.g. Prisma's `Prisma.Decimal` without importing it directly. | [Which fields are eligible](#which-fields-are-eligible). |
|
|
767
|
+
| `Primitive` | Union of scalar types (`string \| number \| boolean \| bigint \| symbol \| undefined \| null \| Date`) treated as leaves — not relations — when walking an entity's shape. | Used by `Ordering<T>` to tell scalar fields apart from relation fields. |
|
|
768
|
+
| `VSRepoWhere<T>` | ORM-agnostic filter type accepted by `*Where` dynamic methods (e.g. `findWhere`, `findOneWhere`, `updateWhere`). Supports field filters, logical operators (`AND`/`OR`/`NOT`), and relation filters. | [`findWhere`, `findOneWhere` and other `*Where` prefixes](#available-prefixes). |
|
|
766
769
|
| `VSRepoOrmTypes` | `{ dbClient; dbTransaction }` — describes your ORM's client/transaction types. Passed as the third generic to `VSRepository<Entity, PKType, OrmTypes>` to type `getDbClient()`, `transaction()` and the `db` option instead of `any`. | [Creating a repository](#creating-a-repository). |
|
|
767
|
-
| `VSRepoTransactionOptions` | `{ isolationLevel?, timeoutMs? }` — options accepted as the second argument of `transaction()`.
|
|
768
|
-
| `TransactionIsolationLevel` | Enum of standard SQL isolation levels (`READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`) accepted by `VSRepoTransactionOptions.isolationLevel`.
|
|
770
|
+
| `VSRepoTransactionOptions` | `{ isolationLevel?, timeoutMs? }` — options accepted as the second argument of `transaction()`. | [Transactions](#transactions). |
|
|
771
|
+
| `TransactionIsolationLevel` | Enum of standard SQL isolation levels (`READ_UNCOMMITTED`, `READ_COMMITTED`, `REPEATABLE_READ`, `SERIALIZABLE`) accepted by `VSRepoTransactionOptions.isolationLevel`. | [Transactions](#transactions). |
|
|
769
772
|
|
|
770
773
|
### `DeepPartial<T>`
|
|
771
774
|
|
|
@@ -944,13 +947,13 @@ export class MyOrmAdapter<T> extends VSRepoAdapter<T> {
|
|
|
944
947
|
}
|
|
945
948
|
```
|
|
946
949
|
|
|
947
|
-
| Method
|
|
948
|
-
|
|
|
949
|
-
| `new VSLogger(logLevel, name, slowThresholdMs?)`
|
|
950
|
-
| `logDebug/logInfo/logWarn(text, obj?)`
|
|
951
|
-
| `logError(text, err?)`
|
|
950
|
+
| Method | Description |
|
|
951
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
952
|
+
| `new VSLogger(logLevel, name, slowThresholdMs?)` | Creates a logger; `name` prefixes every line, `slowThresholdMs` defaults to 300. |
|
|
953
|
+
| `logDebug/logInfo/logWarn(text, obj?)` | Logs at the given level if `logLevel` allows it; `obj` is appended as pretty-printed JSON. |
|
|
954
|
+
| `logError(text, err?)` | Logs at `ERROR`; if `err` is an `Error`, only `name`/`message`/`stack`/`cause` are logged. |
|
|
952
955
|
| `startPerformLog(operation)` / `endPerformLog(data)` | Bracket a block to log its duration, escalating to `WARN` if it exceeds `slowThresholdMs`. |
|
|
953
|
-
| `getLogLevel()`
|
|
956
|
+
| `getLogLevel()` | Returns the logger's configured `VSLogLevel`. |
|
|
954
957
|
|
|
955
958
|
This is purely a convenience for adapter authors — nothing in the core requires your adapter to use it.
|
|
956
959
|
|
|
@@ -976,7 +979,7 @@ try {
|
|
|
976
979
|
| ----------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
977
980
|
| `DECORATOR` | Invalid arguments were passed to `@DynamicMethod` or `@QueryMethod`. |
|
|
978
981
|
| `RESOLVER` | The library failed to resolve a dynamic/query method's configuration into a callable method (e.g. an unknown method name). |
|
|
979
|
-
| `DYNAMIC` | A resolved dynamic/query method failed at runtime (e.g. missing arguments).
|
|
982
|
+
| `DYNAMIC` | A resolved dynamic/query method failed at runtime (e.g. missing arguments). |
|
|
980
983
|
| `VALIDATOR` | Invalid method options or arguments were detected during validation. |
|
|
981
984
|
| `BASE` | Invalid usage of a base method (`get`, `save`, `remove`, etc). |
|
|
982
985
|
| `ADAPTER` | A `VSRepoAdapter` failed while talking to the underlying ORM/database — always thrown as `VSRepoAdapterError`. |
|
|
@@ -1034,6 +1037,7 @@ console.log(AdapterErrorCode.UNIQUE_CONSTRAINT_VIOLATION); // "UNIQUE_CONSTRAINT
|
|
|
1034
1037
|
| Code | Meaning |
|
|
1035
1038
|
| ----------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
1036
1039
|
| `UNKNOWN` | Unclassified/unknown error; the fallback when no more specific code matches. |
|
|
1040
|
+
| `TRANSACTION_ROLLED_BACK` | Some adapters might use this code for forced transaction rollbacks (like Drizzle's `tx.rollback()`) |
|
|
1037
1041
|
| `MISSING_DB_CLIENT` | Database client (or connection pool) not provided or could not be resolved. |
|
|
1038
1042
|
| `CONNECTION_FAILED` | Could not reach/connect to the database, or an established connection was lost/terminated. |
|
|
1039
1043
|
| `CONNECTION_POOL_EXHAUSTED` | Connection pool exhausted/depleted — no connection available, all busy or the limit was reached. |
|