vsrepo 1.3.3 → 1.3.4
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 +108 -3
- package/README.pt-BR.md +1556 -0
- package/dist/DynamicRepository.d.ts +84 -14
- package/dist/DynamicRepository.js +3 -31
- package/dist/VSRepository.d.ts +92 -9
- package/dist/VSRepository.js +22 -0
- package/dist/internal/decorators/dynamic-method.decorator.js +1 -1
- package/dist/internal/decorators/query-method.decorator.js +16 -0
- package/dist/internal/entities/dynamic-method-metadata.entity.js +3 -1
- package/dist/internal/utils/schemas.util.js +6 -1
- package/dist/internal/validation/query-method-arg.validate.js +22 -0
- package/dist/internal/validation/query-method-options.validate.js +24 -0
- package/dist/internal/validation/types/query-method-arg.type.js +2 -0
- package/dist/internal/validation/types/query-method-options.type.js +2 -0
- package/package.json +1 -1
- package/scripts/configure-prisma-import.mjs +16 -12
|
@@ -91,7 +91,9 @@ type DynamicTransformCreatePayload<U, T, M extends PrismaModelName, TRelations>
|
|
|
91
91
|
export type DynamicSaveInput<TEntity, UName extends PrismaModelName, WRelations = undefined> =
|
|
92
92
|
ModelUpsertInput<UName> extends infer U
|
|
93
93
|
? U extends any
|
|
94
|
-
? Simplify<
|
|
94
|
+
? Simplify<
|
|
95
|
+
DynamicTransformCreatePayload<U, TEntity, UName, ResolveRelations<WRelations>>
|
|
96
|
+
>
|
|
95
97
|
: never
|
|
96
98
|
: never;
|
|
97
99
|
|
|
@@ -108,12 +110,14 @@ export type DynamicPatchInput<
|
|
|
108
110
|
UName extends PrismaModelName,
|
|
109
111
|
WRelations = undefined,
|
|
110
112
|
> = Simplify<
|
|
111
|
-
DistributiveOmit<
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
DistributiveOmit<
|
|
114
|
+
PrismaModelInputs<UName>["updateInput"],
|
|
115
|
+
keyof ResolveRelations<WRelations>
|
|
116
|
+
> & {
|
|
117
|
+
[K in Extract<
|
|
118
|
+
keyof ResolveRelations<WRelations>,
|
|
119
|
+
keyof TEntity
|
|
120
|
+
>]?: DynamicRelationCreatePayload<TEntity[K], UName, K>;
|
|
117
121
|
}
|
|
118
122
|
>;
|
|
119
123
|
|
|
@@ -129,12 +133,14 @@ export type DynamicMergeInput<
|
|
|
129
133
|
UName extends PrismaModelName,
|
|
130
134
|
WRelations = undefined,
|
|
131
135
|
> = Simplify<
|
|
132
|
-
DistributiveOmit<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
DistributiveOmit<
|
|
137
|
+
PrismaModelInputs<UName>["updateInput"],
|
|
138
|
+
keyof ResolveRelations<WRelations>
|
|
139
|
+
> & {
|
|
140
|
+
[K in Extract<
|
|
141
|
+
keyof ResolveRelations<WRelations>,
|
|
142
|
+
keyof TEntity
|
|
143
|
+
>]?: DynamicRelationUpdatePayload<TEntity[K], UName, K>;
|
|
138
144
|
}
|
|
139
145
|
>;
|
|
140
146
|
|
|
@@ -395,7 +401,7 @@ export type DynamicMethodConfig<M extends PrismaModelName = PrismaModelName> = {
|
|
|
395
401
|
* class UserRepository extends DynamicRepository<User, "User", string> {
|
|
396
402
|
* `@DynamicMethod()`
|
|
397
403
|
* declare findOneByEmail: (email: string) => Promise<User | null>;
|
|
398
|
-
*
|
|
404
|
+
*
|
|
399
405
|
* @DynamicMethod<"User">({ injectOrdenation: { createdAt: "desc" } })
|
|
400
406
|
* declare findByAge: (email: number) => Promise<User[]>;
|
|
401
407
|
* }
|
|
@@ -404,3 +410,67 @@ export type DynamicMethodConfig<M extends PrismaModelName = PrismaModelName> = {
|
|
|
404
410
|
export declare function DynamicMethod<M extends PrismaModelName = PrismaModelName>(
|
|
405
411
|
config?: DynamicMethodConfig<M>,
|
|
406
412
|
): PropertyDecorator;
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Single argument accepted by a method declared with `@QueryMethod`.
|
|
416
|
+
*
|
|
417
|
+
* `args` are injected positionally into the raw SQL statement (`$1`, `$2`, ...),
|
|
418
|
+
* exactly like Prisma's `$queryRawUnsafe`/`$executeRawUnsafe` parameters — this is
|
|
419
|
+
* what allows safe parameter injection instead of string-concatenating values into
|
|
420
|
+
* the SQL text.
|
|
421
|
+
*
|
|
422
|
+
* @template T Tuple type of the positional SQL parameters, e.g. `[email: string]`.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```typescript
|
|
426
|
+
* declare findByEmail: (arg: QueryMethodArg<[email: string]>) => Promise<User[]>;
|
|
427
|
+
* ```
|
|
428
|
+
*/
|
|
429
|
+
export type QueryMethodArg<T extends Array<any>> = {
|
|
430
|
+
/** Positional parameters injected into the SQL placeholders (`$1`, `$2`, ...). */
|
|
431
|
+
args: T;
|
|
432
|
+
/** Transaction client to run this query in, instead of the repository's default client. */
|
|
433
|
+
db?: ClientOrTransaction;
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Options accepted by the `@QueryMethod` decorator.
|
|
438
|
+
*/
|
|
439
|
+
export type QueryMethodOptions = {
|
|
440
|
+
/**
|
|
441
|
+
* When `true`, the SQL is executed with `$executeRawUnsafe` (INSERT/UPDATE/DELETE)
|
|
442
|
+
* and the decorated method must resolve to `number` (the count of affected rows).
|
|
443
|
+
* When `false`/omitted, the SQL is executed with `$queryRawUnsafe` and the method
|
|
444
|
+
* resolves to whatever return type you declare on the field.
|
|
445
|
+
*
|
|
446
|
+
* @default false
|
|
447
|
+
*/
|
|
448
|
+
modifying?: boolean;
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Property decorator used to declare a **raw SQL query method** on a `DynamicRepository`
|
|
453
|
+
* subclass, bypassing name-based method parsing entirely.
|
|
454
|
+
*
|
|
455
|
+
* Applied to a `declare` class field, it executes `value` directly through Prisma
|
|
456
|
+
* (`$queryRawUnsafe` or `$executeRawUnsafe`, depending on `options.modifying`), with
|
|
457
|
+
* parameters injected positionally via `QueryMethodArg["args"]`. Since the SQL result
|
|
458
|
+
* isn't statically known, the field's own declared function type is what determines
|
|
459
|
+
* the method's return type — for `modifying: true` it must always resolve to `number`.
|
|
460
|
+
*
|
|
461
|
+
* @param value Raw SQL statement to execute. Use `$1`, `$2`, ... placeholders for the
|
|
462
|
+
* values that will be passed via `args` — never interpolate values directly into `value`.
|
|
463
|
+
* @param options Optional configuration; set `modifying: true` for `INSERT`/`UPDATE`/`DELETE` statements.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```typescript
|
|
467
|
+
* class UserRepository extends DynamicRepository<User, "User", string> {
|
|
468
|
+
* @QueryMethod('SELECT * FROM "user" WHERE email = $1')
|
|
469
|
+
* declare findByEmailRaw: (arg: QueryMethodArg<[email: string]>) => Promise<User[]>;
|
|
470
|
+
*
|
|
471
|
+
* @QueryMethod('UPDATE "user" SET active = true WHERE id = $1', { modifying: true })
|
|
472
|
+
* declare activateUser: (arg: QueryMethodArg<[id: string]>) => Promise<number>;
|
|
473
|
+
* }
|
|
474
|
+
* ```
|
|
475
|
+
*/
|
|
476
|
+
export declare function QueryMethod(value: string, options?: QueryMethodOptions): PropertyDecorator;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DynamicRepository = exports.DynamicMethod = void 0;
|
|
3
|
+
exports.DynamicRepository = exports.QueryMethod = exports.DynamicMethod = void 0;
|
|
4
4
|
const dynamic_methods_metadata_resolve_1 = require("./internal/resolvers/dynamic-methods-metadata.resolve");
|
|
5
5
|
const build_config_validate_1 = require("./internal/validation/build-config.validate");
|
|
6
6
|
const is_object_validate_1 = require("./internal/validation/is-object.validate");
|
|
@@ -8,6 +8,8 @@ const VSRepository_1 = require("./VSRepository");
|
|
|
8
8
|
require("reflect-metadata");
|
|
9
9
|
var dynamic_method_decorator_1 = require("./internal/decorators/dynamic-method.decorator");
|
|
10
10
|
Object.defineProperty(exports, "DynamicMethod", { enumerable: true, get: function () { return dynamic_method_decorator_1.DynamicMethod; } });
|
|
11
|
+
var query_method_decorator_1 = require("./internal/decorators/query-method.decorator");
|
|
12
|
+
Object.defineProperty(exports, "QueryMethod", { enumerable: true, get: function () { return query_method_decorator_1.QueryMethod; } });
|
|
11
13
|
class DynamicRepository extends VSRepository_1.VSRepository {
|
|
12
14
|
constructor(prisma, config) {
|
|
13
15
|
if (!(0, is_object_validate_1.isObject)(config)) {
|
|
@@ -22,33 +24,3 @@ class DynamicRepository extends VSRepository_1.VSRepository {
|
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
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/VSRepository.d.ts
CHANGED
|
@@ -408,18 +408,47 @@ type GroupByMethod<M extends PrismaModelName> = <A extends Prisma.TypeMap['model
|
|
|
408
408
|
options?: { db?: ClientOrTransaction }
|
|
409
409
|
) => Promise<Prisma.Result<PrismaDelegate<M>, A, 'groupBy'>>;
|
|
410
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Function type generated for a dynamic method configured with `query` (non-modifying).
|
|
413
|
+
*
|
|
414
|
+
* The result of a raw SQL `SELECT` isn't statically known, so the method itself
|
|
415
|
+
* resolves to `any` by default, but exposes a generic parameter so the caller can
|
|
416
|
+
* infer/assert the shape of the result: `repo.myRawQuery<User[]>({ args: [...] })`.
|
|
417
|
+
*
|
|
418
|
+
* @template TReturn Return type asserted at the call site. Defaults to `any`.
|
|
419
|
+
*/
|
|
420
|
+
type QueryMethodFn = <TReturn = any>(
|
|
421
|
+
arg: { args: any[]; db?: ClientOrTransaction },
|
|
422
|
+
) => Promise<TReturn>;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Function type generated for a dynamic method configured with `query` and
|
|
426
|
+
* `modifying: true`.
|
|
427
|
+
*
|
|
428
|
+
* Modifying raw queries run through `$executeRawUnsafe` and always resolve to the
|
|
429
|
+
* number of affected rows, so — unlike `QueryMethodFn` — no generic return type is
|
|
430
|
+
* exposed here.
|
|
431
|
+
*/
|
|
432
|
+
type QueryMethodModifyingFn = (
|
|
433
|
+
arg: { args: any[]; db?: ClientOrTransaction },
|
|
434
|
+
) => Promise<number>;
|
|
435
|
+
|
|
411
436
|
type DynamicMethods<T, M extends PrismaModelName, Config, I> = Config extends { methods: infer Methods }
|
|
412
437
|
? {
|
|
413
438
|
[K in keyof Methods as Methods[K] extends { map: true } ? K : never]: K extends string
|
|
414
|
-
?
|
|
415
|
-
?
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
439
|
+
? Methods[K] extends { query: { modifying: true } }
|
|
440
|
+
? QueryMethodModifyingFn
|
|
441
|
+
: Methods[K] extends { query: infer Q }
|
|
442
|
+
? QueryMethodFn
|
|
443
|
+
: (Methods[K] extends { proxyTo: infer P extends string } ? P : K) extends infer ResolvedKey
|
|
444
|
+
? ResolvedKey extends 'aggregate'
|
|
445
|
+
? AggregateMethod<M>
|
|
446
|
+
: ResolvedKey extends 'groupBy'
|
|
447
|
+
? GroupByMethod<M>
|
|
448
|
+
: ResolvedKey extends string
|
|
449
|
+
? MethodFactory<T, M, ResolvedKey, ExtractSelectModels<Config>, ResolveSelectModel<Methods[K], Config, ExtractSelectModels<Config>>, I, Methods[K], ExtractIncludeModels<Config>>
|
|
450
|
+
: never
|
|
421
451
|
: never
|
|
422
|
-
: never
|
|
423
452
|
: never;
|
|
424
453
|
}
|
|
425
454
|
: {};
|
|
@@ -524,6 +553,53 @@ export type MethodConfig<M extends PrismaModelName, SelectModels = any> = {
|
|
|
524
553
|
readonly injectOrdenation?: OrdenationModel<M>;
|
|
525
554
|
/** Injects a fixed pagination automatically into the query. */
|
|
526
555
|
readonly injectPagination?: PaginationModel<M>;
|
|
556
|
+
/**
|
|
557
|
+
* Turns this method into a **raw SQL query method**, bypassing name-based parsing
|
|
558
|
+
* entirely. The method executes the given SQL directly through Prisma, with
|
|
559
|
+
* parameters injected positionally via the `args` array passed at the call site
|
|
560
|
+
* (`$1`, `$2`, ... placeholders), so no other option in `MethodConfig` applies
|
|
561
|
+
* (`selectModels`, `requiredWhere`, `pushWhere`, etc. are all ignored).
|
|
562
|
+
*
|
|
563
|
+
* - `modifying: false` (default) runs through `$queryRawUnsafe` and the method
|
|
564
|
+
* resolves to `TReturn` (`any` by default), inferable/assertable via a generic
|
|
565
|
+
* at the call site.
|
|
566
|
+
* - `modifying: true` runs through `$executeRawUnsafe` and the method **always**
|
|
567
|
+
* resolves to `number` (the count of affected rows).
|
|
568
|
+
*
|
|
569
|
+
* @example
|
|
570
|
+
* ```typescript
|
|
571
|
+
* methods: {
|
|
572
|
+
* findActiveUsersRaw: {
|
|
573
|
+
* map: true,
|
|
574
|
+
* query: { value: 'SELECT * FROM "user" WHERE active = $1' },
|
|
575
|
+
* },
|
|
576
|
+
* deactivateUsersOlderThanRaw: {
|
|
577
|
+
* map: true,
|
|
578
|
+
* query: { value: 'UPDATE "user" SET active = false WHERE "createdAt" < $1', modifying: true },
|
|
579
|
+
* },
|
|
580
|
+
* }
|
|
581
|
+
*
|
|
582
|
+
* // Uso:
|
|
583
|
+
* const users = await repo.findActiveUsersRaw<User[]>({ args: [true] });
|
|
584
|
+
* const affected = await repo.deactivateUsersOlderThanRaw({ args: [cutoffDate] });
|
|
585
|
+
* ```
|
|
586
|
+
*/
|
|
587
|
+
readonly query?: {
|
|
588
|
+
/**
|
|
589
|
+
* Raw SQL statement to execute. Use positional placeholders (`$1`, `$2`, ...)
|
|
590
|
+
* for the values passed in `args`, never string-interpolate the values
|
|
591
|
+
* directly, or you'll re-introduce the SQL injection risk this API exists to avoid.
|
|
592
|
+
*/
|
|
593
|
+
readonly value: string;
|
|
594
|
+
/**
|
|
595
|
+
* When `true`, executes via `$executeRawUnsafe` and the method always resolves
|
|
596
|
+
* to `number` (rows affected). When `false`/omitted, executes via
|
|
597
|
+
* `$queryRawUnsafe` and the method resolves to `TReturn` (`any` by default).
|
|
598
|
+
*
|
|
599
|
+
* @default false
|
|
600
|
+
*/
|
|
601
|
+
readonly modifying?: boolean;
|
|
602
|
+
};
|
|
527
603
|
};
|
|
528
604
|
|
|
529
605
|
type BaseMethodConfig<TSelectKeys extends PropertyKey = string> = {
|
|
@@ -1062,7 +1138,14 @@ export type ValidateRepoConfig<T extends object, M extends PrismaModelName, Conf
|
|
|
1062
1138
|
*/
|
|
1063
1139
|
methods?: {
|
|
1064
1140
|
[K in keyof (Config extends { methods: infer Meth } ? Meth : {})]: K extends string
|
|
1065
|
-
? MethodConfig<M, Config extends { selectModels: infer SM } ? SM : any> &
|
|
1141
|
+
? MethodConfig<M, Config extends { selectModels: infer SM } ? SM : any> &
|
|
1142
|
+
(K extends ValidMethodPatterns
|
|
1143
|
+
? {}
|
|
1144
|
+
: (Config extends { methods: infer Meth }
|
|
1145
|
+
? (K extends keyof Meth ? Meth[K] : never)
|
|
1146
|
+
: never) extends { query: any }
|
|
1147
|
+
? {}
|
|
1148
|
+
: { proxyTo: ValidMethodPatterns })
|
|
1066
1149
|
: never;
|
|
1067
1150
|
};
|
|
1068
1151
|
};
|
package/dist/VSRepository.js
CHANGED
|
@@ -29,6 +29,7 @@ const pretty_wheres_resolve_1 = require("./internal/resolvers/pretty-wheres.reso
|
|
|
29
29
|
const specific_where_resolve_1 = require("./internal/resolvers/specific-where.resolve");
|
|
30
30
|
const dbAndPrismaArgs_resolve_1 = require("./internal/resolvers/dbAndPrismaArgs.resolve");
|
|
31
31
|
const method_options_validate_1 = require("./internal/validation/method-options.validate");
|
|
32
|
+
const query_method_arg_validate_1 = require("./internal/validation/query-method-arg.validate");
|
|
32
33
|
class VSRepository {
|
|
33
34
|
vsrepocache;
|
|
34
35
|
tableName;
|
|
@@ -82,6 +83,27 @@ class VSRepository {
|
|
|
82
83
|
(0, logger_util_1.logger)("Keys to map:", "build", buildInstance.tableName, methodsToMap);
|
|
83
84
|
for (let methodToMap of methodsToMap) {
|
|
84
85
|
const originalKey = methodToMap;
|
|
86
|
+
if (methods[originalKey]?.query) {
|
|
87
|
+
const modifyingQueryMethod = methods[originalKey].query.modifying;
|
|
88
|
+
const valueQueryMethod = methods[originalKey].query.value;
|
|
89
|
+
buildInstance[originalKey] = async (arg) => {
|
|
90
|
+
const queryArgValidated = (0, query_method_arg_validate_1.validateQueryMethodArg)(arg, buildInstance);
|
|
91
|
+
const db = queryArgValidated.db ?? buildInstance.prisma;
|
|
92
|
+
const start = showWorking
|
|
93
|
+
? (0, logger_util_1.performanceLoggerStart)(buildInstance.tableName, `Query method: ${originalKey} (Modifying: ${modifyingQueryMethod})`, queryArgValidated.args)
|
|
94
|
+
: undefined;
|
|
95
|
+
try {
|
|
96
|
+
const result = await db[modifyingQueryMethod ? "$executeRawUnsafe" : "$queryRawUnsafe"](valueQueryMethod, ...queryArgValidated.args);
|
|
97
|
+
if (showWorking)
|
|
98
|
+
(0, logger_util_1.performanceLoggerEnd)(buildInstance.tableName, `Query method: ${originalKey} (Modifying: ${modifyingQueryMethod})`, start);
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
85
107
|
methodToMap = methods[originalKey]?.proxyTo ?? methodToMap;
|
|
86
108
|
const dinamicMethodInfo = (0, dinamic_method_info_resolve_1.resolveDinamicMethodInfo)(buildInstance, methodToMap, originalKey);
|
|
87
109
|
const dinamicMethodCustomization = (0, dinamic_method_customization_resolve_1.resolveDinamicMethodCustomization)(buildInstance, dinamicMethodInfo, originalKey);
|
|
@@ -8,7 +8,7 @@ function DynamicMethod(config) {
|
|
|
8
8
|
const validatedConfig = config ? (0, dynamic_method_config_validate_1.validateDynamicMethodConfig)(config) : undefined;
|
|
9
9
|
return (target, propertyKey) => {
|
|
10
10
|
const methods = Reflect.getMetadata(dinamic_methods_key_constant_1.DINAMIC_METHODS_KEY, target) ?? [];
|
|
11
|
-
methods.push(new dynamic_method_metadata_entity_1.DynamicMethodMetadata(propertyKey,
|
|
11
|
+
methods.push(new dynamic_method_metadata_entity_1.DynamicMethodMetadata(propertyKey, true, validatedConfig?.proxyTo, validatedConfig?.whereType, validatedConfig?.pushWhere, validatedConfig?.fbMode, validatedConfig?.injectOrdenation, validatedConfig?.injectPagination));
|
|
12
12
|
Reflect.defineMetadata(dinamic_methods_key_constant_1.DINAMIC_METHODS_KEY, methods, target);
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryMethod = QueryMethod;
|
|
4
|
+
const dinamic_methods_key_constant_1 = require("../constants/dinamic-methods-key.constant");
|
|
5
|
+
const dynamic_method_metadata_entity_1 = require("../entities/dynamic-method-metadata.entity");
|
|
6
|
+
const query_method_options_validate_1 = require("../validation/query-method-options.validate");
|
|
7
|
+
function QueryMethod(value, options) {
|
|
8
|
+
const validatedConfig = options
|
|
9
|
+
? (0, query_method_options_validate_1.validateQueryMethodOptions)(options)
|
|
10
|
+
: { modifying: false };
|
|
11
|
+
return (target, propertyKey) => {
|
|
12
|
+
const methods = Reflect.getMetadata(dinamic_methods_key_constant_1.DINAMIC_METHODS_KEY, target) ?? [];
|
|
13
|
+
methods.push(new dynamic_method_metadata_entity_1.DynamicMethodMetadata(propertyKey, true, undefined, undefined, undefined, undefined, undefined, undefined, { value, ...validatedConfig }));
|
|
14
|
+
Reflect.defineMetadata(dinamic_methods_key_constant_1.DINAMIC_METHODS_KEY, methods, target);
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -10,7 +10,8 @@ class DynamicMethodMetadata {
|
|
|
10
10
|
fbMode;
|
|
11
11
|
injectOrdenation;
|
|
12
12
|
injectPagination;
|
|
13
|
-
|
|
13
|
+
query;
|
|
14
|
+
constructor(propertyKey, map, proxyTo, whereType, pushWhere, fbMode, injectOrdenation, injectPagination, query) {
|
|
14
15
|
this.propertyKey = propertyKey;
|
|
15
16
|
this.map = map;
|
|
16
17
|
this.proxyTo = proxyTo;
|
|
@@ -19,6 +20,7 @@ class DynamicMethodMetadata {
|
|
|
19
20
|
this.fbMode = fbMode;
|
|
20
21
|
this.injectOrdenation = injectOrdenation;
|
|
21
22
|
this.injectPagination = injectPagination;
|
|
23
|
+
this.query = query;
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
exports.DynamicMethodMetadata = DynamicMethodMetadata;
|
|
@@ -3,11 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.methodSchema = exports.booleanSchema = exports.objectSchema = exports.stringSchema = void 0;
|
|
6
|
+
exports.methodSchema = exports.queryOptionsSchema = exports.booleanSchema = exports.objectSchema = exports.stringSchema = void 0;
|
|
7
7
|
const zod_1 = __importDefault(require("zod"));
|
|
8
8
|
exports.stringSchema = zod_1.default.string().trim().nonempty();
|
|
9
9
|
exports.objectSchema = zod_1.default.looseObject({});
|
|
10
10
|
exports.booleanSchema = zod_1.default.boolean();
|
|
11
|
+
exports.queryOptionsSchema = zod_1.default.strictObject({
|
|
12
|
+
value: exports.stringSchema,
|
|
13
|
+
modifying: exports.booleanSchema.default(false),
|
|
14
|
+
});
|
|
11
15
|
exports.methodSchema = zod_1.default.strictObject({
|
|
12
16
|
map: exports.booleanSchema,
|
|
13
17
|
selectModel: exports.stringSchema.or(zod_1.default.literal(false)).optional(),
|
|
@@ -17,4 +21,5 @@ exports.methodSchema = zod_1.default.strictObject({
|
|
|
17
21
|
fbMode: zod_1.default.enum(["one", "list"]).optional(),
|
|
18
22
|
injectOrdenation: exports.objectSchema.or(zod_1.default.array(exports.objectSchema)).optional(),
|
|
19
23
|
injectPagination: exports.objectSchema.optional(),
|
|
24
|
+
query: exports.queryOptionsSchema.optional(),
|
|
20
25
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateQueryMethodArg = validateQueryMethodArg;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const schemas_util_1 = require("../utils/schemas.util");
|
|
9
|
+
const vs_repo_error_1 = require("../errors/vs-repo.error");
|
|
10
|
+
function validateQueryMethodArg(arg, instance) {
|
|
11
|
+
const queryArgSchema = zod_1.default.strictObject({
|
|
12
|
+
args: zod_1.default.array(zod_1.default.any()),
|
|
13
|
+
db: schemas_util_1.objectSchema.optional(),
|
|
14
|
+
});
|
|
15
|
+
const argParsed = queryArgSchema.safeParse(arg);
|
|
16
|
+
if (!argParsed.success) {
|
|
17
|
+
const firstIssue = argParsed.error.issues[0];
|
|
18
|
+
const path = firstIssue?.path.length ? firstIssue.path.join(".") : "options";
|
|
19
|
+
throw new vs_repo_error_1.VSRepoRuntimeError(`[VSRepository] (${instance.tableName}: runtime) ${path}: ${firstIssue?.message}`, "67542");
|
|
20
|
+
}
|
|
21
|
+
return argParsed.data;
|
|
22
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateQueryMethodOptions = validateQueryMethodOptions;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const vs_repo_error_1 = require("../errors/vs-repo.error");
|
|
9
|
+
const is_object_validate_1 = require("./is-object.validate");
|
|
10
|
+
const schemas_util_1 = require("../utils/schemas.util");
|
|
11
|
+
function validateQueryMethodOptions(options) {
|
|
12
|
+
if (!(0, is_object_validate_1.isObject)(options)) {
|
|
13
|
+
throw new vs_repo_error_1.VSRepoDecoratorError(`[VSRepository] (unknown: decorator) 'options' must be a valid object`);
|
|
14
|
+
}
|
|
15
|
+
const optionsParsed = zod_1.default
|
|
16
|
+
.strictObject({ modifying: schemas_util_1.booleanSchema.default(false) })
|
|
17
|
+
.safeParse(options);
|
|
18
|
+
if (!optionsParsed.success) {
|
|
19
|
+
const firstIssue = optionsParsed.error.issues[0];
|
|
20
|
+
const path = firstIssue?.path.length ? firstIssue.path.join(".") : "options";
|
|
21
|
+
throw new vs_repo_error_1.VSRepoDecoratorError(`[VSRepository] (unknown: decorator) ${path}: ${firstIssue?.message}`);
|
|
22
|
+
}
|
|
23
|
+
return optionsParsed.data;
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -179,16 +179,19 @@ export type * from './VSRepository.types';
|
|
|
179
179
|
fileName: 'DynamicRepository.ts',
|
|
180
180
|
content: `import {
|
|
181
181
|
DynamicRepository as DynamicRepositoryRuntime,
|
|
182
|
-
DynamicMethod as DynamicMethodRuntime
|
|
182
|
+
DynamicMethod as DynamicMethodRuntime,
|
|
183
|
+
QueryMethod as QueryMethodRuntime,
|
|
183
184
|
} from 'vsrepo/DynamicRepository';
|
|
184
185
|
|
|
185
186
|
import type {
|
|
186
187
|
DynamicRepository as DynamicRepositoryType,
|
|
187
|
-
DynamicMethod as DynamicMethodType
|
|
188
|
+
DynamicMethod as DynamicMethodType,
|
|
189
|
+
QueryMethod as QueryMethodType,
|
|
188
190
|
} from './DynamicRepository.types';
|
|
189
191
|
|
|
190
192
|
export const DynamicRepository = DynamicRepositoryRuntime as typeof DynamicRepositoryType;
|
|
191
193
|
export const DynamicMethod = DynamicMethodRuntime as typeof DynamicMethodType;
|
|
194
|
+
export const QueryMethod = QueryMethodRuntime as typeof QueryMethodType;
|
|
192
195
|
|
|
193
196
|
export type * from './DynamicRepository.types';
|
|
194
197
|
`,
|
|
@@ -210,7 +213,8 @@ export {
|
|
|
210
213
|
|
|
211
214
|
export {
|
|
212
215
|
DynamicRepository,
|
|
213
|
-
DynamicMethod
|
|
216
|
+
DynamicMethod,
|
|
217
|
+
QueryMethod,
|
|
214
218
|
} from './DynamicRepository.js';
|
|
215
219
|
|
|
216
220
|
export type * from './VSRepoError.types';
|
|
@@ -229,15 +233,15 @@ for (const file of tsFiles) {
|
|
|
229
233
|
}
|
|
230
234
|
|
|
231
235
|
// Copia o README.md do pacote VSRepository para o diretório de output, se existir
|
|
232
|
-
const readmeSource = path.join(packageRoot, 'README.md');
|
|
233
|
-
const readmeTarget = path.join(outputDir, 'README.md');
|
|
234
|
-
|
|
235
|
-
if (fs.existsSync(readmeSource)) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} else {
|
|
239
|
-
|
|
240
|
-
}
|
|
236
|
+
// const readmeSource = path.join(packageRoot, 'README.md');
|
|
237
|
+
// const readmeTarget = path.join(outputDir, 'README.md');
|
|
238
|
+
|
|
239
|
+
// if (fs.existsSync(readmeSource)) {
|
|
240
|
+
// fs.copyFileSync(readmeSource, readmeTarget);
|
|
241
|
+
// console.log(`Gerado: ${path.relative(workspaceRoot, readmeTarget)}`);
|
|
242
|
+
// } else {
|
|
243
|
+
// console.warn(`README.md do VSRepository nao encontrado em: ${path.relative(workspaceRoot, readmeSource)}. Ignorando a copia.`);
|
|
244
|
+
// }
|
|
241
245
|
|
|
242
246
|
console.log('\nVSRepository gerado com tipagem do Prisma.');
|
|
243
247
|
console.log(`Output: ${path.relative(workspaceRoot, outputDir)}`);
|