vsrepo 1.3.1 → 1.3.3
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 +614 -567
- package/dist/DynamicRepository.d.ts +406 -0
- package/dist/DynamicRepository.js +54 -0
- package/dist/VSRepoError.d.ts +63 -54
- package/dist/VSRepository.d.ts +1079 -1047
- package/dist/VSRepository.js +30 -16
- package/dist/internal/constants/dinamic-methods-key.constant.js +4 -0
- package/dist/internal/decorators/dynamic-method.decorator.js +14 -0
- package/dist/internal/decorators/types/dynamic-method-config.type.js +2 -0
- package/dist/internal/entities/dynamic-method-metadata.entity.js +24 -0
- package/dist/internal/errors/vs-repo.error.js +5 -1
- package/dist/internal/resolvers/dbAndPrismaArgs.resolve.js +7 -1
- package/dist/internal/resolvers/dinamic-method-customization.resolve.js +14 -2
- package/dist/internal/resolvers/dinamic-method-info.resolve.js +14 -0
- package/dist/internal/resolvers/dynamic-methods-metadata.resolve.js +15 -0
- package/dist/internal/utils/logger.util.js +1 -1
- package/dist/internal/utils/schemas.util.js +11 -1
- package/dist/internal/validation/constructor-config.validate.js +1 -10
- package/dist/internal/validation/dynamic-method-config.validate.js +19 -0
- package/dist/internal/validation/method-options.validate.js +1 -0
- package/package.json +78 -72
- package/scripts/configure-prisma-import.mjs +45 -0
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BuildConfig,
|
|
3
|
+
ClientOrTransaction,
|
|
4
|
+
DbClient,
|
|
5
|
+
DbTransaction,
|
|
6
|
+
DistributiveOmit,
|
|
7
|
+
ExtractNestedCreateInput,
|
|
8
|
+
ExtractNestedUpdateInput,
|
|
9
|
+
IncludeModel,
|
|
10
|
+
ModelUpsertInput,
|
|
11
|
+
OrdenationModel,
|
|
12
|
+
PaginationModel,
|
|
13
|
+
PaginationOptions,
|
|
14
|
+
PrismaModelInputs,
|
|
15
|
+
PrismaModelName,
|
|
16
|
+
RepositoryRelations,
|
|
17
|
+
SeeMode,
|
|
18
|
+
WhereModel,
|
|
19
|
+
} from "./VSRepository.d";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Flattens a type intersection into a single object,
|
|
23
|
+
* avoiding the TypeScript "union type too complex to represent" error.
|
|
24
|
+
*/
|
|
25
|
+
type Simplify<T> = { [K in keyof T]: T[K] } & {};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolves `WRelations` to a concrete relation map, falling back to `{}` when no
|
|
29
|
+
* relations were flagged (mirrors `VSRepository`'s own internal fallback).
|
|
30
|
+
*/
|
|
31
|
+
type ResolveRelations<WRelations> = WRelations extends object ? WRelations : {};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Payload accepted for a relation field mapped as `true` in `WRelations`, used to build
|
|
35
|
+
* the `create`-shaped payload for `save`/`saveList`/`patch`/`patchList`.
|
|
36
|
+
*
|
|
37
|
+
* To-many relations (array fields) resolve to a list of Prisma's own nested `create`
|
|
38
|
+
* payload. To-one relations (object fields) resolve to that same nested `create` payload,
|
|
39
|
+
* but **always also accept `null`** by default — since `WRelations` only flags *which*
|
|
40
|
+
* fields are relations (not their `mode`/`restriction`/`nullable` config), every to-one
|
|
41
|
+
* relation here is treated as unlinkable.
|
|
42
|
+
*/
|
|
43
|
+
type DynamicRelationCreatePayload<TField, M extends PrismaModelName, K extends PropertyKey> =
|
|
44
|
+
NonNullable<TField> extends any[]
|
|
45
|
+
? ExtractNestedCreateInput<M, K>[]
|
|
46
|
+
: NonNullable<TField> extends object
|
|
47
|
+
? ExtractNestedCreateInput<M, K> | null
|
|
48
|
+
: never;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Same as `DynamicRelationCreatePayload`, but built from Prisma's nested `update` payload
|
|
52
|
+
* instead of `create` — used by `merge`. To-one relations still accept `null` by default.
|
|
53
|
+
*/
|
|
54
|
+
type DynamicRelationUpdatePayload<TField, M extends PrismaModelName, K extends PropertyKey> =
|
|
55
|
+
NonNullable<TField> extends any[]
|
|
56
|
+
? ExtractNestedUpdateInput<M, K>[]
|
|
57
|
+
: NonNullable<TField> extends object
|
|
58
|
+
? ExtractNestedUpdateInput<M, K> | null
|
|
59
|
+
: never;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Distributes over the branches of Prisma's own upsert/create union for `UName`, replacing
|
|
63
|
+
* every field flagged in `TRelations` with `DynamicRelationCreatePayload`.
|
|
64
|
+
*/
|
|
65
|
+
type DynamicTransformCreatePayload<U, T, M extends PrismaModelName, TRelations> = Omit<
|
|
66
|
+
U,
|
|
67
|
+
keyof TRelations
|
|
68
|
+
> & {
|
|
69
|
+
// Fields that are REQUIRED in this specific branch of the Prisma union
|
|
70
|
+
[K in Extract<keyof TRelations, keyof U> as {} extends Pick<U, K>
|
|
71
|
+
? never
|
|
72
|
+
: K]: K extends keyof T ? DynamicRelationCreatePayload<T[K], M, K> : never;
|
|
73
|
+
} & {
|
|
74
|
+
// Fields that are OPTIONAL in this branch or do not originally belong to it
|
|
75
|
+
[K in keyof TRelations as K extends keyof U
|
|
76
|
+
? {} extends Pick<U, K>
|
|
77
|
+
? K
|
|
78
|
+
: never
|
|
79
|
+
: K]?: K extends keyof T ? DynamicRelationCreatePayload<T[K], M, K> : never;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Payload accepted by the `save`/`saveList` methods.
|
|
84
|
+
*
|
|
85
|
+
* Built directly from Prisma's own upsert/create input for `UName`, exactly like
|
|
86
|
+
* `VSRepository`'s `save`: fields flagged as relations via `WRelations` are resolved
|
|
87
|
+
* into their nested `create` payload shape instead of `TEntity`'s own shape (to-one
|
|
88
|
+
* relations also accept `null` by default); every other field keeps Prisma's own
|
|
89
|
+
* validated create input shape.
|
|
90
|
+
*/
|
|
91
|
+
export type DynamicSaveInput<TEntity, UName extends PrismaModelName, WRelations = undefined> =
|
|
92
|
+
ModelUpsertInput<UName> extends infer U
|
|
93
|
+
? U extends any
|
|
94
|
+
? Simplify<DynamicTransformCreatePayload<U, TEntity, UName, ResolveRelations<WRelations>>>
|
|
95
|
+
: never
|
|
96
|
+
: never;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Payload accepted by the `patch`/`patchList` methods.
|
|
100
|
+
*
|
|
101
|
+
* Built from Prisma's own `update` input for `UName` (so every field is already
|
|
102
|
+
* optional); fields flagged as relations via `WRelations` are resolved into their
|
|
103
|
+
* nested `create` payload shape, the same way as in `DynamicSaveInput` (to-one
|
|
104
|
+
* relations also accept `null` by default).
|
|
105
|
+
*/
|
|
106
|
+
export type DynamicPatchInput<
|
|
107
|
+
TEntity,
|
|
108
|
+
UName extends PrismaModelName,
|
|
109
|
+
WRelations = undefined,
|
|
110
|
+
> = Simplify<
|
|
111
|
+
DistributiveOmit<PrismaModelInputs<UName>["updateInput"], keyof ResolveRelations<WRelations>> & {
|
|
112
|
+
[K in Extract<keyof ResolveRelations<WRelations>, keyof TEntity>]?: DynamicRelationCreatePayload<
|
|
113
|
+
TEntity[K],
|
|
114
|
+
UName,
|
|
115
|
+
K
|
|
116
|
+
>;
|
|
117
|
+
}
|
|
118
|
+
>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Payload accepted by the `merge` method.
|
|
122
|
+
*
|
|
123
|
+
* Built from Prisma's own `update` input for `UName` (so every field is already
|
|
124
|
+
* optional); fields flagged as relations via `WRelations` are resolved into their
|
|
125
|
+
* nested `update` payload shape (to-one relations also accept `null` by default).
|
|
126
|
+
*/
|
|
127
|
+
export type DynamicMergeInput<
|
|
128
|
+
TEntity,
|
|
129
|
+
UName extends PrismaModelName,
|
|
130
|
+
WRelations = undefined,
|
|
131
|
+
> = Simplify<
|
|
132
|
+
DistributiveOmit<PrismaModelInputs<UName>["updateInput"], keyof ResolveRelations<WRelations>> & {
|
|
133
|
+
[K in Extract<keyof ResolveRelations<WRelations>, keyof TEntity>]?: DynamicRelationUpdatePayload<
|
|
134
|
+
TEntity[K],
|
|
135
|
+
UName,
|
|
136
|
+
K
|
|
137
|
+
>;
|
|
138
|
+
}
|
|
139
|
+
>;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Base options accepted by most `DynamicRepository` methods.
|
|
143
|
+
*/
|
|
144
|
+
export type DynamicMethodOptions<TName extends PrismaModelName = PrismaModelName> = {
|
|
145
|
+
/** Database client or transaction to use for this operation. */
|
|
146
|
+
db?: ClientOrTransaction;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Controls visibility of soft-deleted records.
|
|
150
|
+
* Only takes effect if `softRemovekName` is configured.
|
|
151
|
+
*/
|
|
152
|
+
see?: SeeMode;
|
|
153
|
+
|
|
154
|
+
/** Raw Prisma `include`. */
|
|
155
|
+
include?: IncludeModel<TName>;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Configuration for an individual base method exposed by `DynamicRepository`.
|
|
160
|
+
*
|
|
161
|
+
* Unlike `VSRepository`'s `BuildConfig`, this configuration does not accept
|
|
162
|
+
* `active` (base methods are always available) nor `defaultSelect`
|
|
163
|
+
* (`DynamicRepository` has no select models).
|
|
164
|
+
*/
|
|
165
|
+
type StrippedBaseMethods<TSelectKeys extends PropertyKey = string> = {
|
|
166
|
+
[K in keyof NonNullable<BuildConfig<TSelectKeys>["baseMethods"]>]: Omit<
|
|
167
|
+
NonNullable<NonNullable<BuildConfig<TSelectKeys>["baseMethods"]>[K]>,
|
|
168
|
+
"active" | "defaultSelect"
|
|
169
|
+
>;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Configuration applied during the construction of a `DynamicRepository`.
|
|
174
|
+
*
|
|
175
|
+
* Equivalent to `VSRepository`'s `BuildConfig`, but without `freeze`
|
|
176
|
+
* (no longer configurable) and without `active`/`defaultSelect` on each
|
|
177
|
+
* base method (base methods are always active and there are no select models).
|
|
178
|
+
*/
|
|
179
|
+
export type DynamicRepositoryBuildConfig = Omit<BuildConfig, "freeze" | "baseMethods"> & {
|
|
180
|
+
/** Customizes the behavior of the automatic base methods. */
|
|
181
|
+
baseMethods?: StrippedBaseMethods;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Configuration used to construct a `DynamicRepository`.
|
|
186
|
+
*
|
|
187
|
+
* @template T Type of the entity managed by the repository.
|
|
188
|
+
* @template U Prisma model name.
|
|
189
|
+
*/
|
|
190
|
+
export interface DynamicRepositoryConstructorConfig<T, U extends PrismaModelName> {
|
|
191
|
+
/**
|
|
192
|
+
* Name of the table mapped by Prisma (usually uncapitalized).
|
|
193
|
+
*/
|
|
194
|
+
tableName: Uncapitalize<U>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Name of the field that represents the entity's primary key (Primary Key).
|
|
198
|
+
*/
|
|
199
|
+
pkName: keyof T;
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Name of the `DateTime` field used for soft-delete.
|
|
203
|
+
*
|
|
204
|
+
* When configured, enables the `softRemove`, `softRemoveList`, `restore`, and `restoreList` methods.
|
|
205
|
+
* The field **must** be of type `DateTime` in the Prisma schema — VSRepository validates this during `build`.
|
|
206
|
+
*/
|
|
207
|
+
softRemovekName?: keyof T;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Defines global filters that will be automatically applied to all repository queries.
|
|
211
|
+
* Useful for tenant isolation (multi-tenancy) or base restrictions (e.g., `isActive: true`).
|
|
212
|
+
*/
|
|
213
|
+
requiredWhere?: WhereModel<U>;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Default ordering automatically injected into all queries that accept `orderBy`,
|
|
217
|
+
* unless the method already has `injectOrdenation` configured or uses the `Ordered` suffix.
|
|
218
|
+
*
|
|
219
|
+
* Useful for ensuring a consistent sort order across the repository without repeating
|
|
220
|
+
* the `order` argument on every call.
|
|
221
|
+
*/
|
|
222
|
+
defaultOrdenation?: OrdenationModel<U>;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Configures automatic relation management.
|
|
226
|
+
* When configured, allows the `save`, `saveList`, `patch`, and `patchList` methods
|
|
227
|
+
* to automatically handle linking, creation, or cascading deletion of related records.
|
|
228
|
+
*/
|
|
229
|
+
relations?: RepositoryRelations<T>;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Customizes the behavior of the automatic base methods when the repository is built.
|
|
233
|
+
*/
|
|
234
|
+
build?: DynamicRepositoryBuildConfig;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Base repository built from a fixed configuration, exposing a complete set of
|
|
239
|
+
* ready-to-use CRUD and soft-delete methods around a Prisma model.
|
|
240
|
+
*
|
|
241
|
+
* @template TEntity Type of the entity managed by the repository.
|
|
242
|
+
* @template UName Prisma model name.
|
|
243
|
+
* @template VPKType Type of the entity's primary key value.
|
|
244
|
+
* @template WRelations Keys of `TEntity` configured as relations (flags only, `true`
|
|
245
|
+
* per relation field). The actual relation behavior (`mode`, `restriction`, `nullable`)
|
|
246
|
+
* still comes from `relations` in the constructor config; `WRelations` here only tells
|
|
247
|
+
* `DynamicSaveInput`/`DynamicPatchInput`/`DynamicMergeInput` which fields to resolve
|
|
248
|
+
* into their nested Prisma create/update payload shape instead of `TEntity`'s own shape.
|
|
249
|
+
*/
|
|
250
|
+
export declare abstract class DynamicRepository<
|
|
251
|
+
TEntity extends object,
|
|
252
|
+
UName extends PrismaModelName,
|
|
253
|
+
VPKType,
|
|
254
|
+
WRelations extends Partial<Record<keyof TEntity, true>> | undefined = undefined,
|
|
255
|
+
> {
|
|
256
|
+
/**
|
|
257
|
+
* Creates a configured instance of `DynamicRepository`.
|
|
258
|
+
*/
|
|
259
|
+
constructor(prisma: DbClient, config: DynamicRepositoryConstructorConfig<TEntity, UName>);
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The Prisma Client instance passed to constructor.
|
|
263
|
+
*/
|
|
264
|
+
readonly prisma: DbClient;
|
|
265
|
+
|
|
266
|
+
/** Fetches a record by its primary key (PK). */
|
|
267
|
+
get(pk: VPKType, options?: DynamicMethodOptions<UName>): Promise<TEntity | null>;
|
|
268
|
+
|
|
269
|
+
/** Fetches a record by PK and throws `VSRepoRuntimeError` if not found. */
|
|
270
|
+
getOrThrow(pk: VPKType, options?: DynamicMethodOptions<UName>): Promise<TEntity>;
|
|
271
|
+
|
|
272
|
+
/** Fetches multiple records by a list of primary keys (PKs). */
|
|
273
|
+
getList(pks: VPKType[], options?: DynamicMethodOptions<UName>): Promise<TEntity[]>;
|
|
274
|
+
|
|
275
|
+
/** Deletes a record identified by its primary key (PK). */
|
|
276
|
+
remove(pk: VPKType, options?: DynamicMethodOptions<UName>): Promise<TEntity>;
|
|
277
|
+
|
|
278
|
+
/** Inserts or updates (upsert) a record. */
|
|
279
|
+
save(
|
|
280
|
+
obj: DynamicSaveInput<TEntity, UName, WRelations>,
|
|
281
|
+
options?: DynamicMethodOptions<UName>,
|
|
282
|
+
): Promise<TEntity>;
|
|
283
|
+
|
|
284
|
+
/** Saves an array of objects in a single automatic transaction. */
|
|
285
|
+
saveList(
|
|
286
|
+
objs: DynamicSaveInput<TEntity, UName, WRelations>[],
|
|
287
|
+
options?: Omit<DynamicMethodOptions<UName>, "include"> & {
|
|
288
|
+
/** Transaction client to use for this operation. */
|
|
289
|
+
db?: DbTransaction;
|
|
290
|
+
},
|
|
291
|
+
): Promise<TEntity[]>;
|
|
292
|
+
|
|
293
|
+
/** Partially updates (patch) an existing record by its primary key (PK). */
|
|
294
|
+
patch(
|
|
295
|
+
pk: VPKType,
|
|
296
|
+
obj: DynamicPatchInput<TEntity, UName, WRelations>,
|
|
297
|
+
options?: DynamicMethodOptions<UName>,
|
|
298
|
+
): Promise<TEntity>;
|
|
299
|
+
|
|
300
|
+
/** Partially updates multiple records via `[pk, obj]` tuples in an automatic transaction. */
|
|
301
|
+
patchList(
|
|
302
|
+
tuples: [pk: VPKType, obj: DynamicPatchInput<TEntity, UName, WRelations>][],
|
|
303
|
+
options?: Omit<DynamicMethodOptions<UName>, "include"> & {
|
|
304
|
+
/** Transaction client to use for this operation. */
|
|
305
|
+
db?: DbTransaction;
|
|
306
|
+
},
|
|
307
|
+
): Promise<TEntity[]>;
|
|
308
|
+
|
|
309
|
+
/** Fetches a record by PK and deep-merges it with the provided object **in memory**. */
|
|
310
|
+
merge(
|
|
311
|
+
pk: VPKType,
|
|
312
|
+
obj: DynamicMergeInput<TEntity, UName, WRelations>,
|
|
313
|
+
options?: DynamicMethodOptions<UName>,
|
|
314
|
+
): Promise<TEntity | null>;
|
|
315
|
+
|
|
316
|
+
/** Deletes multiple records by their primary keys. */
|
|
317
|
+
removeList(
|
|
318
|
+
pks: VPKType[],
|
|
319
|
+
options?: Omit<DynamicMethodOptions<UName>, "include">,
|
|
320
|
+
): Promise<{ count: number }>;
|
|
321
|
+
|
|
322
|
+
/** Fetches all records (respects `requiredWhere` when set). */
|
|
323
|
+
getAll(
|
|
324
|
+
options?: DynamicMethodOptions<UName> & {
|
|
325
|
+
/** Pagination options for the query. */
|
|
326
|
+
pagination?: PaginationOptions;
|
|
327
|
+
/**
|
|
328
|
+
* Ordering to apply to the query.
|
|
329
|
+
* When omitted and `defaultOrdenation` is configured on the repository,
|
|
330
|
+
* the default ordering is applied automatically.
|
|
331
|
+
*/
|
|
332
|
+
order?: OrdenationModel<UName>;
|
|
333
|
+
},
|
|
334
|
+
): Promise<TEntity[]>;
|
|
335
|
+
|
|
336
|
+
/** Returns the total number of records. */
|
|
337
|
+
total(options?: Omit<DynamicMethodOptions<UName>, "include">): Promise<number>;
|
|
338
|
+
|
|
339
|
+
/** Checks whether a record exists by its primary key (PK). */
|
|
340
|
+
has(pk: VPKType, options?: Omit<DynamicMethodOptions<UName>, "include">): Promise<boolean>;
|
|
341
|
+
|
|
342
|
+
/** Marks a record as deleted (soft-delete). */
|
|
343
|
+
softRemove(pk: VPKType, options?: Omit<DynamicMethodOptions<UName>, "see">): Promise<TEntity>;
|
|
344
|
+
|
|
345
|
+
/** Marks multiple records as deleted (soft-delete) in batch. */
|
|
346
|
+
softRemoveList(
|
|
347
|
+
pks: VPKType[],
|
|
348
|
+
options?: Omit<DynamicMethodOptions<UName>, "see" | "include">,
|
|
349
|
+
): Promise<{ count: number }>;
|
|
350
|
+
|
|
351
|
+
/** Restores a record previously marked as deleted (soft-delete). */
|
|
352
|
+
restore(pk: VPKType, options?: Omit<DynamicMethodOptions<UName>, "see">): Promise<TEntity>;
|
|
353
|
+
|
|
354
|
+
/** Restores multiple records previously marked as deleted (soft-delete) in batch. */
|
|
355
|
+
restoreList(
|
|
356
|
+
pks: VPKType[],
|
|
357
|
+
options?: Omit<DynamicMethodOptions<UName>, "see" | "include">,
|
|
358
|
+
): Promise<{ count: number }>;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export type DynamicMethodConfig<M extends PrismaModelName = PrismaModelName> = {
|
|
362
|
+
/** Redirects the logic to another valid method pattern. */
|
|
363
|
+
proxyTo?: string;
|
|
364
|
+
|
|
365
|
+
/** Controls whether the method combines (`extending`) or overwrites (`overwrite`) the `requiredWhere`. */
|
|
366
|
+
whereType?: "overwrite" | "extending";
|
|
367
|
+
|
|
368
|
+
/** Adds an extra `where` on top of `requiredWhere`. */
|
|
369
|
+
pushWhere?: WhereModel<M>;
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Defines whether the method returns a single item (`one`) or a list (`list`).
|
|
373
|
+
* @deprecated Use `findOneBy` if you want to return a single result.
|
|
374
|
+
*/
|
|
375
|
+
fbMode?: "one" | "list";
|
|
376
|
+
|
|
377
|
+
/** Injects a fixed ordering automatically into the query. */
|
|
378
|
+
injectOrdenation?: OrdenationModel<M>;
|
|
379
|
+
|
|
380
|
+
/** Injects a fixed pagination automatically into the query. */
|
|
381
|
+
injectPagination?: PaginationModel<M>;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Property decorator used to declare a dynamic method on a `DynamicRepository` subclass.
|
|
386
|
+
*
|
|
387
|
+
* Applied to a `declare` class field whose name follows one of the supported method
|
|
388
|
+
* patterns (e.g. `findByEmail`, `findManyByStatusPaginated`); the method's behavior and
|
|
389
|
+
* return type are inferred from the field name, optionally adjusted via `config`.
|
|
390
|
+
*
|
|
391
|
+
* @template M Prisma model name the decorated method operates on.
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* ```typescript
|
|
395
|
+
* class UserRepository extends DynamicRepository<User, "User", string> {
|
|
396
|
+
* `@DynamicMethod()`
|
|
397
|
+
* declare findOneByEmail: (email: string) => Promise<User | null>;
|
|
398
|
+
*
|
|
399
|
+
* @DynamicMethod<"User">({ injectOrdenation: { createdAt: "desc" } })
|
|
400
|
+
* declare findByAge: (email: number) => Promise<User[]>;
|
|
401
|
+
* }
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
export declare function DynamicMethod<M extends PrismaModelName = PrismaModelName>(
|
|
405
|
+
config?: DynamicMethodConfig<M>,
|
|
406
|
+
): PropertyDecorator;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DynamicRepository = exports.DynamicMethod = void 0;
|
|
4
|
+
const dynamic_methods_metadata_resolve_1 = require("./internal/resolvers/dynamic-methods-metadata.resolve");
|
|
5
|
+
const build_config_validate_1 = require("./internal/validation/build-config.validate");
|
|
6
|
+
const is_object_validate_1 = require("./internal/validation/is-object.validate");
|
|
7
|
+
const VSRepository_1 = require("./VSRepository");
|
|
8
|
+
require("reflect-metadata");
|
|
9
|
+
var dynamic_method_decorator_1 = require("./internal/decorators/dynamic-method.decorator");
|
|
10
|
+
Object.defineProperty(exports, "DynamicMethod", { enumerable: true, get: function () { return dynamic_method_decorator_1.DynamicMethod; } });
|
|
11
|
+
class DynamicRepository extends VSRepository_1.VSRepository {
|
|
12
|
+
constructor(prisma, config) {
|
|
13
|
+
if (!(0, is_object_validate_1.isObject)(config)) {
|
|
14
|
+
throw new VSRepository_1.VSRepoConfigError(`[VSRepository] (unknown: config) 'config' must be a valid object`);
|
|
15
|
+
}
|
|
16
|
+
const { build: buildConfig = {}, ...constructorConfig } = config;
|
|
17
|
+
super(constructorConfig);
|
|
18
|
+
const dynamicMethodsMetadata = (0, dynamic_methods_metadata_resolve_1.resolveDynamicMethodsMetadata)(this.constructor.prototype);
|
|
19
|
+
this.methods = dynamicMethodsMetadata;
|
|
20
|
+
const buildConfigValidated = (0, build_config_validate_1.validateBuildConfig)(buildConfig, this);
|
|
21
|
+
this.build(prisma, { ...buildConfigValidated, freeze: false }, this);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
exports.DynamicRepository = DynamicRepository;
|
|
25
|
+
// export class UserRepository extends DynamicRepository {
|
|
26
|
+
// constructor() {
|
|
27
|
+
// super(
|
|
28
|
+
// { $transaction: {} },
|
|
29
|
+
// {
|
|
30
|
+
// tableName: "user",
|
|
31
|
+
// pkName: "id",
|
|
32
|
+
// requiredWhere: { active: true },
|
|
33
|
+
// softRemovekName: "createdAt",
|
|
34
|
+
// build: { showWorking: true },
|
|
35
|
+
// },
|
|
36
|
+
// );
|
|
37
|
+
// }
|
|
38
|
+
// @DynamicMethod()
|
|
39
|
+
// declare findByAge: (age: number) => Promise<object[]>;
|
|
40
|
+
// @DynamicMethod()
|
|
41
|
+
// declare findOneByEmail: (email: number) => Promise<object[]>;
|
|
42
|
+
// @DynamicMethod()
|
|
43
|
+
// declare findByNameStartsWithInsensitive: (email: number) => Promise<object[]>;
|
|
44
|
+
// @DynamicMethod()
|
|
45
|
+
// declare findByDescriptionIsNull: (email: number) => Promise<object[]>;
|
|
46
|
+
// @DynamicMethod({ whereType: "overwrite" })
|
|
47
|
+
// declare findByNameContainsInsensitiveOrderedAndPaginated: (email: number) => Promise<object[]>;
|
|
48
|
+
// @DynamicMethod({
|
|
49
|
+
// injectOrdenation: [{ address: { state: "asc" } }, { address: { city: "asc" } }],
|
|
50
|
+
// })
|
|
51
|
+
// declare findByAddressWithCountry: (email: number) => Promise<object[]>;
|
|
52
|
+
// }
|
|
53
|
+
// const userRepository = new UserRepository();
|
|
54
|
+
// console.log(userRepository);
|
package/dist/VSRepoError.d.ts
CHANGED
|
@@ -1,54 +1,63 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Literal types representing the internal error codes of the library.
|
|
3
|
-
*/
|
|
4
|
-
export type VSRepoErrorType =
|
|
5
|
-
| 'VSREPO_CONFIG'
|
|
6
|
-
| 'VSREPO_BUILD'
|
|
7
|
-
| 'VSREPO_EXTEND'
|
|
8
|
-
| 'VSREPO_RUNTIME'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
* when invalid arguments are passed to
|
|
50
|
-
*/
|
|
51
|
-
export declare class
|
|
52
|
-
readonly type: '
|
|
53
|
-
constructor(message: string
|
|
54
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Literal types representing the internal error codes of the library.
|
|
3
|
+
*/
|
|
4
|
+
export type VSRepoErrorType =
|
|
5
|
+
| 'VSREPO_CONFIG'
|
|
6
|
+
| 'VSREPO_BUILD'
|
|
7
|
+
| 'VSREPO_EXTEND'
|
|
8
|
+
| 'VSREPO_RUNTIME'
|
|
9
|
+
| 'VSREPO_DECORATOR';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Base class for all errors thrown by the VSRepository.
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class VSRepoError extends Error {
|
|
15
|
+
/** Internal code used to identify the error category. */
|
|
16
|
+
abstract readonly type: VSRepoErrorType;
|
|
17
|
+
|
|
18
|
+
constructor(message: string, type: VSRepoErrorType);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when an invalid configuration or a configuration inconsistency
|
|
23
|
+
* is detected before or during repository initialization.
|
|
24
|
+
*/
|
|
25
|
+
export declare class VSRepoConfigError extends VSRepoError {
|
|
26
|
+
readonly type: 'VSREPO_CONFIG';
|
|
27
|
+
constructor(message: string);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Thrown when the Prisma instance injection fails or when the
|
|
32
|
+
* build configuration is incorrect in the `.build()`.
|
|
33
|
+
*/
|
|
34
|
+
export declare class VSRepoBuildError extends VSRepoError {
|
|
35
|
+
readonly type: 'VSREPO_BUILD';
|
|
36
|
+
constructor(message: string);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Thrown when an error occurs while injecting new methods into the repository
|
|
41
|
+
* via `.extend()`.
|
|
42
|
+
*/
|
|
43
|
+
export declare class VSRepoExtendError extends VSRepoError {
|
|
44
|
+
readonly type: 'VSREPO_EXTEND';
|
|
45
|
+
constructor(message: string);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Thrown when invalid arguments are passed to a decorator.
|
|
50
|
+
*/
|
|
51
|
+
export declare class VSRepoDecoratorError extends VSRepoError {
|
|
52
|
+
readonly type: 'VSREPO_DECORATOR';
|
|
53
|
+
constructor(message: string);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Thrown when dynamic operations fail at runtime, such as
|
|
58
|
+
* when invalid arguments are passed to methods.
|
|
59
|
+
*/
|
|
60
|
+
export declare class VSRepoRuntimeError extends VSRepoError {
|
|
61
|
+
readonly type: 'VSREPO_RUNTIME';
|
|
62
|
+
constructor(message: string, code: string);
|
|
63
|
+
}
|