@flusys/nestjs-shared 8.1.5 → 9.0.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.
Files changed (41) hide show
  1. package/README.md +48 -2
  2. package/classes/api-service.class.d.ts +3 -0
  3. package/constants/permissions.d.ts +46 -0
  4. package/exceptions/base-app.exception.d.ts +3 -2
  5. package/fesm/{509.js → 183.js} +43 -37
  6. package/fesm/470.js +228 -105
  7. package/fesm/667.js +28 -10
  8. package/fesm/{67.js → 681.js} +97 -19
  9. package/fesm/{720.js → 948.js} +60 -7
  10. package/fesm/chunks/123.js +9 -10
  11. package/fesm/chunks/37.js +7 -8
  12. package/fesm/classes/index.js +10 -4
  13. package/fesm/constants/index.js +53 -1
  14. package/fesm/decorators/index.js +4 -4
  15. package/fesm/dtos/index.js +2 -2
  16. package/fesm/guards/index.js +48 -426
  17. package/fesm/index.js +436 -341
  18. package/fesm/interceptors/index.js +62 -23
  19. package/fesm/interfaces/index.js +28 -3
  20. package/fesm/middlewares/index.js +5 -3
  21. package/fesm/modules/index.js +6 -414
  22. package/fesm/pipes/index.js +196 -0
  23. package/fesm/utils/index.js +125 -10
  24. package/index.d.ts +1 -0
  25. package/interfaces/company-access-resolver.interface.d.ts +18 -0
  26. package/interfaces/datasource.interface.d.ts +2 -0
  27. package/interfaces/email-adapter.interface.d.ts +27 -0
  28. package/interfaces/index.d.ts +5 -0
  29. package/interfaces/message-ref.interface.d.ts +4 -0
  30. package/interfaces/permission-action-registry.interface.d.ts +12 -0
  31. package/interfaces/permission-resolver.interface.d.ts +9 -0
  32. package/middlewares/logger.middleware.d.ts +4 -0
  33. package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +5 -0
  34. package/package.json +8 -2
  35. package/pipes/dto-body-validation.pipe.d.ts +18 -0
  36. package/pipes/index.d.ts +1 -0
  37. package/utils/cache-tenant.util.d.ts +2 -0
  38. package/utils/index.d.ts +3 -0
  39. package/utils/message-ref.util.d.ts +2 -0
  40. package/utils/permission-match.util.d.ts +1 -0
  41. package/utils/query-helpers.util.d.ts +2 -1
package/README.md CHANGED
@@ -164,6 +164,23 @@ Generated POST-only endpoints: `/insert`, `/insert-many`, `/get-all`, `/get/:id`
164
164
 
165
165
  Security levels: `'public'` (no auth), `'jwt'` (token only), `'permission'` (token + action check).
166
166
 
167
+ Bodies of `insert` / `insert-many` / `update` / `update-many` / `bulk-upsert` are validated against the concrete Create/Update DTO by `DtoBodyValidationPipe` (`@flusys/nestjs-shared/pipes`, same `DEFAULT_VALIDATION_OPTIONS` as the global pipe: whitelist + forbidNonWhitelisted, no implicit conversion), because a generic `@Body() dto: T` reflects as `Object` and the global pipe skips it. Audit fields are never taken from the client: `SetCreatedByOnBody` / `SetUpdateByOnBody` / `SetDeletedByOnBody` drop any client-sent `createdById` / `updatedById` / `deletedById` and stamp the authenticated user's id (nothing without a user), and the pipe keeps only the audit key the endpoint's interceptor stamps. A `slug` the DTO does not declare is the `Slug` interceptor's and is kept.
168
+
169
+ ### Savepoints in a shared transaction
170
+
171
+ `withSavepoint(queryRunner, fn)` (`@flusys/nestjs-shared/utils`) runs `fn` inside a savepoint of an
172
+ already-open transaction: a failure rolls back only what `fn` did and is rethrown, so the caller can
173
+ swallow it and keep using the transaction. Use it for any step that may fail without failing the whole
174
+ unit of work - PostgreSQL aborts the entire transaction after one failed statement otherwise.
175
+
176
+ ```typescript
177
+ try {
178
+ await withSavepoint(queryRunner, () => service.insert(dto, user, { queryRunner }));
179
+ } catch {
180
+ // skipped; the transaction is still usable
181
+ }
182
+ ```
183
+
167
184
  ## 4. Guards and Decorators
168
185
 
169
186
  ```typescript
@@ -190,6 +207,8 @@ async publicList() { }
190
207
 
191
208
  `ILoggedUserInfo` fields: `id`, `email`, `name?`, `phone?`, `profilePictureId?`, `companyId?`, `branchId?`.
192
209
 
210
+ `matchesPermission(granted, required)` (`@flusys/nestjs-shared/utils`) is the one wildcard matcher (`*`, `prefix.*`) behind `PermissionGuard` and `SharedPermissionCacheService.matchPermission`. For a check inside a handler, `SharedPermissionCacheService.assertPermission(user, code)` throws `InsufficientPermissionsException` (403) unless the user holds the code in their company/branch scope, and `PermissionSystemUnavailableException` when no cache is wired up - never re-implement that check. `PERMISSION_RESOLVER` / `IPermissionResolver` (`@flusys/nestjs-shared/interfaces`) is the provider interface for reading a user's codes in any company/branch scope, including one not loaded into the cache yet; nestjs-iam implements it, feature packages inject it `@Optional()`.
211
+
193
212
  ## 5. Response DTOs
194
213
 
195
214
  All controllers return one of these shapes:
@@ -232,6 +251,8 @@ throw new ValidationException([{ field: 'email', message: 'Invalid format' }]);
232
251
 
233
252
  All exceptions produce: `{ success: false, message, messageKey,messageVariables:{} code, _meta }`.
234
253
 
254
+ **Keyed diagnostics** - when a service returns a list of problems (plan warnings, validation findings) instead of throwing, each item is a translatable reference, not text. `IMessageRef` (`@flusys/nestjs-shared/interfaces`) is `{ messageKey, messageVariables? }`, built with `messageRef(key, variables?)` (`@flusys/nestjs-shared/utils`). A variable may itself be an `IMessageRef` (the frontend translates it first). `IValidationError` (`errors[]` of an exception) may carry `messageKey`/`messageVariables` instead of `message`.
255
+
235
256
  ## 7. Hybrid Cache
236
257
 
237
258
  ```typescript
@@ -260,6 +281,8 @@ export class MyService {
260
281
 
261
282
  `CacheModule.forRoot(true)` connects to Redis automatically when `REDIS_URL` is set; otherwise uses in-memory only.
262
283
 
284
+ **Multi-tenant keys:** one cache serves every tenant, so `ApiService` prefixes its keys with the current tenant (`cacheTenant()`), taken from a tenant-aware DataSource provider (`isMultiTenant()` / `getCurrentTenantId()`, which `MultiTenantDataSourceService` implements). A single database is never prefixed. Code that clears or reads these keys through `UtilsService` itself must pass the same tenant: `cacheTenantId(dataSourceProvider)` from `@flusys/nestjs-shared/utils`, or `this.cacheTenant()` inside an `ApiService`.
285
+
263
286
  ## 8. Hybrid Event Bus
264
287
 
265
288
  The event counterpart of the hybrid cache: one wrapper, transport chosen by configuration.
@@ -603,7 +626,6 @@ import { NOTIFICATION_EVENT_ACTIONS } from '@flusys/nestjs-notification/config';
603
626
  NotificationModule.forRoot({
604
627
  config: {
605
628
  ...dbConfig,
606
- enableRealtime: true,
607
629
  events: {
608
630
  enabled: true,
609
631
  actions: [
@@ -713,7 +735,31 @@ export class AuditConsumer {
713
735
  actions, so one type fits every handler. `*` matches exactly one segment; `**` (or `#`)
714
736
  matches the rest. Handlers are discovered at bootstrap on any singleton provider or
715
737
  controller registered with Nest - a REQUEST-scoped provider has no instance at that point,
716
- so put consumers on singletons. Injecting `EVENT_BUS_INSTANCE` gives direct
738
+ so put consumers on singletons.
739
+
740
+ **Database work in a handler.** Every handler runs inside the request context of the event's
741
+ actor - tenant, company, user and request id restored from `event.actor`. When
742
+ `MultiTenantDataSourceService` has no HTTP request, it takes the tenant from that context, so a
743
+ handler reaches the right tenant database by resolving any request-scoped service through
744
+ `ModuleRef` - no tenant plumbing:
745
+
746
+ ```typescript
747
+ @Injectable()
748
+ export class InvoiceConsumer {
749
+ constructor(@Inject(ModuleRef) private readonly moduleRef: ModuleRef) {}
750
+
751
+ @OnDomainEvent('form-builder.form_result.submitted')
752
+ async handle(event: DomainEvent) {
753
+ const results = await this.moduleRef.resolve(FormResultService, ContextIdFactory.create(), { strict: false });
754
+ // ...any read or write here hits event.actor.tenantId's database
755
+ }
756
+ }
757
+ ```
758
+
759
+ Events a handler publishes carry the same actor, so a chain of handlers stays on one tenant.
760
+ The same fallback serves any service resolved through `ModuleRef` during an HTTP request.
761
+
762
+ Injecting `EVENT_BUS_INSTANCE` gives direct
717
763
  `publish` / `subscribe` access - mark it `@Optional()`, so the service still resolves in an
718
764
  app that never registers `EventBusModule`.
719
765
 
@@ -25,6 +25,7 @@ export declare abstract class ApiService<CreateDtoT extends object, UpdateDtoT e
25
25
  private readonly _dataSourceProvider;
26
26
  constructor(entityName: string, cacheManager: HybridCache, utilsService: UtilsService, _loggerName: string, isCacheable: boolean | undefined, moduleName: string, dataSourceProvider: IDataSourceProvider, entity: EntityTarget<EntityT>);
27
27
  protected getDataSourceProvider(): IDataSourceProvider;
28
+ protected cacheTenant(): string | undefined;
28
29
  protected ensureDataSourceRepository(): Promise<void>;
29
30
  protected resolveRepositories(entities: EntityTarget<any>[]): Promise<Repository<any>[]>;
30
31
  insert(dto: CreateDtoT, user: ILoggedUserInfo | null): Promise<InterfaceT>;
@@ -46,6 +47,8 @@ export declare abstract class ApiService<CreateDtoT extends object, UpdateDtoT e
46
47
  private handleError;
47
48
  private ensureArray;
48
49
  private executeInTransaction;
50
+ protected assertColumnProperty(key: string): void;
51
+ protected applyEqualsFilter(query: SelectQueryBuilder<EntityT>, key: string, value: unknown): void;
49
52
  protected beforeInsertOperation(_dto: CreateDtoT | Array<CreateDtoT>, _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
50
53
  protected afterInsertOperation(_entity: EntityT[], _dto: CreateDtoT | Array<CreateDtoT>, _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
51
54
  protected beforeUpdateOperation(_dto: UpdateDtoT | Array<UpdateDtoT>, _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
@@ -97,6 +97,30 @@ export declare const FORM_RESULT_PERMISSIONS: {
97
97
  readonly UPDATE: "form-result.update";
98
98
  readonly DELETE: "form-result.delete";
99
99
  };
100
+ export declare const ENTITY_DEFINITION_PERMISSIONS: {
101
+ readonly CREATE: "entity_builder.entity_definition.create";
102
+ readonly READ: "entity_builder.entity_definition.read";
103
+ readonly UPDATE: "entity_builder.entity_definition.update";
104
+ readonly DELETE: "entity_builder.entity_definition.delete";
105
+ };
106
+ export declare const FIELD_DEFINITION_PERMISSIONS: {
107
+ readonly READ: "entity_builder.field_definition.read";
108
+ readonly UPDATE: "entity_builder.field_definition.update";
109
+ };
110
+ export declare const FLOW_DEFINITION_PERMISSIONS: {
111
+ readonly CREATE: "entity_builder.flow_definition.create";
112
+ readonly READ: "entity_builder.flow_definition.read";
113
+ readonly UPDATE: "entity_builder.flow_definition.update";
114
+ readonly DELETE: "entity_builder.flow_definition.delete";
115
+ readonly TEST: "entity_builder.flow_definition.test";
116
+ readonly SYSTEM: "entity_builder.flow_definition.system";
117
+ readonly CODE: "entity_builder.flow_definition.code";
118
+ };
119
+ export declare const ENTITY_BUILDER_ALL_DYNAMIC: {
120
+ readonly ALL: "entity_builder.entity.*";
121
+ };
122
+ export declare const dynamicEntityPermissionParent: (entityCode: string) => string;
123
+ export declare const dynamicEntityPermission: (entityCode: string, action: "create" | "read" | "update" | "delete") => string;
100
124
  export declare const EVENT_PERMISSIONS: {
101
125
  readonly CREATE: "event.create";
102
126
  readonly READ: "event.read";
@@ -259,6 +283,28 @@ export declare const PERMISSIONS: {
259
283
  readonly UPDATE: "form-result.update";
260
284
  readonly DELETE: "form-result.delete";
261
285
  };
286
+ readonly ENTITY_DEFINITION: {
287
+ readonly CREATE: "entity_builder.entity_definition.create";
288
+ readonly READ: "entity_builder.entity_definition.read";
289
+ readonly UPDATE: "entity_builder.entity_definition.update";
290
+ readonly DELETE: "entity_builder.entity_definition.delete";
291
+ };
292
+ readonly FIELD_DEFINITION: {
293
+ readonly READ: "entity_builder.field_definition.read";
294
+ readonly UPDATE: "entity_builder.field_definition.update";
295
+ };
296
+ readonly FLOW_DEFINITION: {
297
+ readonly CREATE: "entity_builder.flow_definition.create";
298
+ readonly READ: "entity_builder.flow_definition.read";
299
+ readonly UPDATE: "entity_builder.flow_definition.update";
300
+ readonly DELETE: "entity_builder.flow_definition.delete";
301
+ readonly TEST: "entity_builder.flow_definition.test";
302
+ readonly SYSTEM: "entity_builder.flow_definition.system";
303
+ readonly CODE: "entity_builder.flow_definition.code";
304
+ };
305
+ readonly ENTITY_BUILDER_ALL_DYNAMIC: {
306
+ readonly ALL: "entity_builder.entity.*";
307
+ };
262
308
  readonly EVENT: {
263
309
  readonly CREATE: "event.create";
264
310
  readonly READ: "event.read";
@@ -1,7 +1,8 @@
1
1
  import { HttpException, HttpStatus } from '@nestjs/common';
2
- export interface IValidationError {
2
+ import { type IMessageRef } from '../interfaces/message-ref.interface.js';
3
+ export interface IValidationError extends Partial<IMessageRef> {
3
4
  field: string;
4
- message: string;
5
+ message?: string;
5
6
  }
6
7
  export interface IBaseAppExceptionOptions {
7
8
  message: string;
@@ -1,10 +1,10 @@
1
- import { IsArray, IsBoolean, IsIn, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, IsUUID, Matches, MaxLength, ValidateNested } from "class-validator";
2
1
  import * as __rspack_external__nestjs_swagger_7cd450b5 from "@nestjs/swagger";
3
2
  import * as __rspack_external_class_transformer_c5a479fb from "class-transformer";
4
- export const __rspack_esm_id = 509;
5
- export const __rspack_esm_ids = [509];
3
+ import * as __rspack_external_class_validator_7b99ef4d from "class-validator";
4
+ export const __rspack_esm_id = 183;
5
+ export const __rspack_esm_ids = [183];
6
6
  export const __webpack_modules__ = {
7
- 980(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
7
+ 746(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
8
8
 
9
9
  // EXPORTS
10
10
  __webpack_require__.d(__webpack_exports__, {
@@ -25,8 +25,8 @@ __webpack_require__.d(__webpack_exports__, {
25
25
 
26
26
  // EXTERNAL MODULE: external "@nestjs/swagger"
27
27
  var swagger_ = __webpack_require__(176);
28
- ;// CONCATENATED MODULE: external "class-validator"
29
-
28
+ // EXTERNAL MODULE: external "class-validator"
29
+ var external_class_validator_ = __webpack_require__(421);
30
30
  ;// CONCATENATED MODULE: ./projects/nestjs-shared/src/dtos/delete.dto.ts
31
31
  function _ts_decorate(decorators, target, key, desc) {
32
32
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -74,7 +74,7 @@ _ts_decorate([
74
74
  }
75
75
  ]
76
76
  }),
77
- IsNotEmpty(),
77
+ (0,external_class_validator_.IsNotEmpty)(),
78
78
  _ts_metadata("design:type", Object)
79
79
  ], DeleteDto.prototype, "id", void 0);
80
80
  _ts_decorate([
@@ -87,8 +87,8 @@ _ts_decorate([
87
87
  ],
88
88
  example: 'delete'
89
89
  }),
90
- IsNotEmpty(),
91
- IsIn([
90
+ (0,external_class_validator_.IsNotEmpty)(),
91
+ (0,external_class_validator_.IsIn)([
92
92
  'delete',
93
93
  'restore',
94
94
  'permanent'
@@ -100,8 +100,8 @@ _ts_decorate([
100
100
  description: 'User ID who initiated the deletion (auto-set by interceptor)',
101
101
  example: 'f2e9c8d0-7a2a-11eb-9439-0242ac130002'
102
102
  }),
103
- IsOptional(),
104
- IsUUID(),
103
+ (0,external_class_validator_.IsOptional)(),
104
+ (0,external_class_validator_.IsUUID)(),
105
105
  _ts_metadata("design:type", String)
106
106
  ], DeleteDto.prototype, "deletedById", void 0);
107
107
 
@@ -138,12 +138,12 @@ pagination_dto_ts_decorate([
138
138
  description: 'Number of items per page (default: 10)',
139
139
  example: 10
140
140
  }),
141
- IsOptional(),
141
+ (0,external_class_validator_.IsOptional)(),
142
142
  (0,external_class_transformer_.Transform)(({ value })=>{
143
143
  const n = Number(value);
144
144
  return Number.isFinite(n) && n > 0 ? Math.trunc(n) : 10;
145
145
  }),
146
- IsNumber(),
146
+ (0,external_class_validator_.IsNumber)(),
147
147
  pagination_dto_ts_metadata("design:type", Number)
148
148
  ], PaginationDto.prototype, "pageSize", void 0);
149
149
  pagination_dto_ts_decorate([
@@ -151,12 +151,12 @@ pagination_dto_ts_decorate([
151
151
  description: 'Zero-based page index (default: 0)',
152
152
  example: 0
153
153
  }),
154
- IsOptional(),
154
+ (0,external_class_validator_.IsOptional)(),
155
155
  (0,external_class_transformer_.Transform)(({ value })=>{
156
156
  const n = Number(value);
157
157
  return Number.isFinite(n) && n >= 0 ? Math.trunc(n) : 0;
158
158
  }),
159
- IsNumber(),
159
+ (0,external_class_validator_.IsNumber)(),
160
160
  pagination_dto_ts_metadata("design:type", Number)
161
161
  ], PaginationDto.prototype, "currentPage", void 0);
162
162
 
@@ -199,8 +199,8 @@ filter_and_pagination_dto_ts_decorate([
199
199
  category: 'electronics'
200
200
  }
201
201
  }),
202
- IsOptional(),
203
- IsObject(),
202
+ (0,external_class_validator_.IsOptional)(),
203
+ (0,external_class_validator_.IsObject)(),
204
204
  filter_and_pagination_dto_ts_metadata("design:type", typeof Record === "undefined" ? Object : Record)
205
205
  ], FilterAndPaginationDto.prototype, "filter", void 0);
206
206
  filter_and_pagination_dto_ts_decorate([
@@ -212,8 +212,8 @@ filter_and_pagination_dto_ts_decorate([
212
212
  pageSize: 10
213
213
  }
214
214
  }),
215
- IsOptional(),
216
- ValidateNested(),
215
+ (0,external_class_validator_.IsOptional)(),
216
+ (0,external_class_validator_.ValidateNested)(),
217
217
  (0,external_class_transformer_.Type)(()=>PaginationDto),
218
218
  filter_and_pagination_dto_ts_metadata("design:type", typeof PaginationDto === "undefined" ? Object : PaginationDto)
219
219
  ], FilterAndPaginationDto.prototype, "pagination", void 0);
@@ -226,8 +226,8 @@ filter_and_pagination_dto_ts_decorate([
226
226
  name: 'ASC'
227
227
  }
228
228
  }),
229
- IsOptional(),
230
- IsObject(),
229
+ (0,external_class_validator_.IsOptional)(),
230
+ (0,external_class_validator_.IsObject)(),
231
231
  filter_and_pagination_dto_ts_metadata("design:type", typeof Record === "undefined" ? Object : Record)
232
232
  ], FilterAndPaginationDto.prototype, "sort", void 0);
233
233
  filter_and_pagination_dto_ts_decorate([
@@ -243,16 +243,16 @@ filter_and_pagination_dto_ts_decorate([
243
243
  'createdAt'
244
244
  ]
245
245
  }),
246
- IsOptional(),
247
- IsArray(),
248
- IsString({
246
+ (0,external_class_validator_.IsOptional)(),
247
+ (0,external_class_validator_.IsArray)(),
248
+ (0,external_class_validator_.IsString)({
249
249
  each: true
250
250
  }),
251
- Matches(/^[a-zA-Z_][a-zA-Z0-9_]*$/, {
251
+ (0,external_class_validator_.Matches)(/^[a-zA-Z_][a-zA-Z0-9_]*$/, {
252
252
  each: true,
253
253
  message: 'Select fields must be valid identifiers (alphanumeric and underscores only)'
254
254
  }),
255
- MaxLength(64, {
255
+ (0,external_class_validator_.MaxLength)(64, {
256
256
  each: true,
257
257
  message: 'Field names must be 64 characters or less'
258
258
  }),
@@ -264,8 +264,8 @@ filter_and_pagination_dto_ts_decorate([
264
264
  example: false,
265
265
  default: false
266
266
  }),
267
- IsOptional(),
268
- IsBoolean(),
267
+ (0,external_class_validator_.IsOptional)(),
268
+ (0,external_class_validator_.IsBoolean)(),
269
269
  filter_and_pagination_dto_ts_metadata("design:type", Boolean)
270
270
  ], FilterAndPaginationDto.prototype, "withDeleted", void 0);
271
271
  /**
@@ -286,16 +286,16 @@ filter_and_pagination_dto_ts_decorate([
286
286
  'createdAt'
287
287
  ]
288
288
  }),
289
- IsOptional(),
290
- IsArray(),
291
- IsString({
289
+ (0,external_class_validator_.IsOptional)(),
290
+ (0,external_class_validator_.IsArray)(),
291
+ (0,external_class_validator_.IsString)({
292
292
  each: true
293
293
  }),
294
- Matches(/^[a-zA-Z_][a-zA-Z0-9_]*$/, {
294
+ (0,external_class_validator_.Matches)(/^[a-zA-Z_][a-zA-Z0-9_]*$/, {
295
295
  each: true,
296
296
  message: 'Select fields must be valid identifiers (alphanumeric and underscores only)'
297
297
  }),
298
- MaxLength(64, {
298
+ (0,external_class_validator_.MaxLength)(64, {
299
299
  each: true,
300
300
  message: 'Field names must be 64 characters or less'
301
301
  }),
@@ -338,9 +338,9 @@ get_by_ids_dto_ts_decorate([
338
338
  'uuid-2'
339
339
  ]
340
340
  }),
341
- IsNotEmpty(),
342
- IsArray(),
343
- IsUUID('all', {
341
+ (0,external_class_validator_.IsNotEmpty)(),
342
+ (0,external_class_validator_.IsArray)(),
343
+ (0,external_class_validator_.IsUUID)('all', {
344
344
  each: true
345
345
  }),
346
346
  get_by_ids_dto_ts_metadata("design:type", Array)
@@ -349,7 +349,7 @@ get_by_ids_dto_ts_decorate([
349
349
  (0,swagger_.ApiPropertyOptional)({
350
350
  description: 'Select specific fields to return (comma-separated or array)'
351
351
  }),
352
- IsOptional(),
352
+ (0,external_class_validator_.IsOptional)(),
353
353
  get_by_ids_dto_ts_metadata("design:type", Object)
354
354
  ], GetByIdsDto.prototype, "select", void 0);
355
355
 
@@ -788,6 +788,12 @@ module.exports = __rspack_external__nestjs_swagger_7cd450b5;
788
788
  module.exports = __rspack_external_class_transformer_c5a479fb;
789
789
 
790
790
 
791
+ },
792
+ 421(module) {
793
+
794
+ module.exports = __rspack_external_class_validator_7b99ef4d;
795
+
796
+
791
797
  },
792
798
 
793
799
  };