@flusys/nestjs-shared 9.1.1 → 9.2.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 +119 -18
- package/classes/api-controller.class.d.ts +1 -0
- package/classes/api-service.class.d.ts +7 -2
- package/classes/hybrid-cache.class.d.ts +17 -4
- package/constants/index.d.ts +1 -0
- package/constants/permissions.d.ts +9 -0
- package/fesm/183.js +7 -7
- package/fesm/47.js +1520 -0
- package/fesm/470.js +333 -382
- package/fesm/667.js +17 -17
- package/fesm/681.js +326 -129
- package/fesm/{948.js → 997.js} +45 -23
- package/fesm/chunks/123.js +17 -9
- package/fesm/chunks/37.js +5 -5
- package/fesm/classes/index.js +4 -3
- package/fesm/constants/index.js +18 -7
- package/fesm/decorators/index.js +120 -39
- package/fesm/dtos/index.js +1 -1
- package/fesm/entities/index.js +8 -8
- package/fesm/enums/index.js +2 -2
- package/fesm/exceptions/index.js +12 -12
- package/fesm/guards/index.js +201 -68
- package/fesm/index.js +95 -42
- package/fesm/interceptors/index.js +290 -590
- package/fesm/interfaces/index.js +97 -8
- package/fesm/middlewares/index.js +4 -4
- package/fesm/modules/index.js +2 -2
- package/fesm/pipes/index.js +8 -8
- package/fesm/utils/index.js +150 -478
- package/interceptors/idempotency.interceptor.d.ts +14 -2
- package/interceptors/slug.interceptor.d.ts +1 -0
- package/interfaces/expression.interface.d.ts +45 -0
- package/interfaces/index.d.ts +1 -0
- package/interfaces/permission-action-registry.interface.d.ts +1 -0
- package/interfaces/permission.interface.d.ts +1 -0
- package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +3 -1
- package/modules/utils/utils.service.d.ts +6 -6
- package/package.json +3 -2
- package/utils/date-time.util.d.ts +0 -1
- package/utils/event-pattern.util.d.ts +1 -0
- package/utils/expression.util.d.ts +35 -0
- package/utils/index.d.ts +2 -0
- package/utils/permission-cache-key.util.d.ts +3 -0
- package/utils/query-helpers.util.d.ts +2 -2
- package/utils/safe-regex.util.d.ts +10 -0
- package/fesm/270.js +0 -659
package/README.md
CHANGED
|
@@ -164,8 +164,28 @@ 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
|
+
An endpoint left out of a per-endpoint `security` map is never public: `insertMany` / `updateMany` take
|
|
168
|
+
the security of `insert` / `update`, `getByIds` / `getByFilter` that of `getById` (else `getAll`), and
|
|
169
|
+
`bulkUpsert` requires both `insert` and `update` (their permissions combined with AND). Anything still
|
|
170
|
+
unset - including a controller with no `security` option at all - requires a JWT. List an endpoint as
|
|
171
|
+
`'public'` explicitly to open it.
|
|
172
|
+
|
|
173
|
+
`PermissionGuard` fails closed on an empty requirement: `@RequirePermission()` with no codes, `''`, `[]`
|
|
174
|
+
or `{ permissions: [] }` is a 403 for every user (and a 401 without one), never a pass.
|
|
175
|
+
|
|
176
|
+
`IdempotencyInterceptor` (on `insert` / `insert-many`) replays the stored response for a repeated
|
|
177
|
+
`X-Idempotency-Key` only to the same tenant, user and endpoint, and releases the key when the request
|
|
178
|
+
fails, so a retry after an error is processed again rather than answered with 409.
|
|
179
|
+
|
|
167
180
|
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
181
|
|
|
182
|
+
### Company scoping
|
|
183
|
+
|
|
184
|
+
`applyCompanyFilter(query, { isCompanyFeatureEnabled, entityAlias }, user)`, `buildCompanyWhereCondition(where, enabled, user)`
|
|
185
|
+
and `validateCompanyOwnership(entity, user, enabled, name)` (`@flusys/nestjs-shared/utils`) keep a user to their own company
|
|
186
|
+
when the company feature is on. A logged-in user without a `companyId` matches nothing (and may not use another company's
|
|
187
|
+
row) - never every company's data. Passing no user at all (`null` / `undefined`) is a system call and is left unscoped.
|
|
188
|
+
|
|
169
189
|
### Savepoints in a shared transaction
|
|
170
190
|
|
|
171
191
|
`withSavepoint(queryRunner, fn)` (`@flusys/nestjs-shared/utils`) runs `fn` inside a savepoint of an
|
|
@@ -259,33 +279,88 @@ All exceptions produce: `{ success: false, message, messageKey,messageVariables:
|
|
|
259
279
|
|
|
260
280
|
## 7. Hybrid Cache
|
|
261
281
|
|
|
262
|
-
|
|
263
|
-
|
|
282
|
+
`CacheModule.forRoot(isGlobal = true, memoryTtl = 60_000, memorySize = 5000)` provides one `HybridCache` under `CACHE_INSTANCE`. The store is chosen by `USE_CACHE_LABEL`:
|
|
283
|
+
|
|
284
|
+
| `USE_CACHE_LABEL` | Data store | Stamps / claims | Use when |
|
|
285
|
+
| ------------------ | ------------------------------------------ | --------------------------- | ------------------------------------------ |
|
|
286
|
+
| `memory` (default) | in-process LRU | in-process | **one instance only** - nothing is shared |
|
|
287
|
+
| `redis` | Redis (`REDIS_URL`) | Redis (`SET NX`) | several instances |
|
|
288
|
+
| `hybrid` | in-process L1 + Redis L2 | Redis (`SET NX`) | several instances, hot immutable reads |
|
|
289
|
+
|
|
290
|
+
`memory` mode is single-instance only: invalidations, claims and one-time values live in the process, so a second instance never sees them. Run more than one instance with `redis` or `hybrid`.
|
|
291
|
+
|
|
292
|
+
### API
|
|
293
|
+
|
|
294
|
+
| Method | Meaning |
|
|
295
|
+
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
296
|
+
| `get(key, { skipMemory? })` | Read; L1 first in `hybrid` unless `skipMemory`. Only `undefined` is a miss. |
|
|
297
|
+
| `set(key, value, ttl?, { skipMemory? })`| Write with `ttl` ms, else the default (`memoryTtl`) - on every layer, Redis included, so nothing lives forever. |
|
|
298
|
+
| `del(key)` | Delete from every layer (other instances' L1 copies are **not** reached). |
|
|
299
|
+
| `getStamp(name)` / `bumpStamp(name)` | Version stamp: created at random when absent, moved by `bumpStamp` atomically for every instance. |
|
|
300
|
+
| `claim(name, ttl)` / `releaseClaim(name)` | Atomic first-wins lock (Redis `SET NX PX`); `true` only for the first caller while it lives. |
|
|
301
|
+
| `take(key, ttl)` | Atomic read-and-delete of a one-time value: exactly one caller across all instances receives it. |
|
|
264
302
|
|
|
303
|
+
### Rules
|
|
304
|
+
|
|
305
|
+
1. **L1 values must be immutable for their key.** In `hybrid` mode the in-process layer of other instances is never invalidated, so `del` or an overwrite does not reach them. A key whose value changes in place - sessions, revocation markers, one-time state, counters, flags - must use `{ skipMemory: true }` on **both** `get` and `set`.
|
|
306
|
+
2. **One-time values use `take`**, never `get` + `del` (two concurrent requests would both read the value). The claim behind `take` is per value, so a fresh value stored under the same key (a resent code) can be taken again.
|
|
307
|
+
3. **Locks and de-duplication use `claim`** and release it when done; the ttl bounds how long a crashed instance holds it.
|
|
308
|
+
4. **Invalidate by stamp, after commit.** Embed `getStamp()` in data keys and `bumpStamp()` to invalidate - never track key lists. Bump **after** the transaction commits: a bump inside it lets a concurrent reader re-cache old rows under the new stamp.
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
265
311
|
@Injectable()
|
|
266
312
|
export class MyService {
|
|
267
|
-
constructor(@Inject(
|
|
268
|
-
|
|
269
|
-
async getData(key: string) {
|
|
270
|
-
const cached = await this.cache.get(key);
|
|
271
|
-
if (cached) return cached;
|
|
272
|
-
const data = await this.fetchFromDb();
|
|
273
|
-
await this.cache.set(key, data, 3600); // TTL in seconds
|
|
274
|
-
return data;
|
|
275
|
-
}
|
|
313
|
+
constructor(@Inject(CACHE_INSTANCE) private readonly cache: HybridCache) {}
|
|
276
314
|
|
|
277
|
-
async
|
|
278
|
-
|
|
315
|
+
async consumeResetToken(tokenHash: string) {
|
|
316
|
+
return this.cache.take<IResetState>(`reset:${tokenHash}`, 15 * 60_000);
|
|
279
317
|
}
|
|
280
|
-
|
|
281
|
-
|
|
318
|
+
|
|
319
|
+
async runOnce(jobId: string, work: () => Promise<void>) {
|
|
320
|
+
if (!(await this.cache.claim(`job:${jobId}`, 60_000))) return;
|
|
321
|
+
try {
|
|
322
|
+
await work();
|
|
323
|
+
} finally {
|
|
324
|
+
await this.cache.releaseClaim(`job:${jobId}`);
|
|
325
|
+
}
|
|
282
326
|
}
|
|
283
327
|
}
|
|
284
328
|
```
|
|
285
329
|
|
|
286
|
-
|
|
330
|
+
### ApiService caching
|
|
287
331
|
|
|
288
|
-
|
|
332
|
+
With `isCacheable = true`, `findById` and `getAll` are cached under `[tenant_<id>_]entity_<name>_<id_x|all>_<stamp>_<sha256(query)>`:
|
|
333
|
+
|
|
334
|
+
- The stamp (one per entity in `cacheDependencies()`, joined) is read **before** the query, so a write that commits mid-read moves the stamp and the stale result lands under a key no later read asks for.
|
|
335
|
+
- Cache failures on the read path (stamp, get, set) are logged and the read goes to the database.
|
|
336
|
+
- `insert` / `insertMany` / `update` / `updateMany` / `bulkUpsert` / `delete` call `invalidateCache()` after commit - whether the service is cacheable or not, because another service may cache the same entity. A failed invalidation is logged, never fails the committed write.
|
|
337
|
+
- `after*Operation` hooks run **before** commit - never invalidate in them.
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
// A cached read that joins or embeds another entity must depend on it
|
|
341
|
+
protected override cacheDependencies(): string[] {
|
|
342
|
+
return [this.entityName, TASK_MANAGER_EVENT_ENTITIES.TASK];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// A service that writes another entity directly (repository, query runner, cascade) bumps it after commit
|
|
346
|
+
await this.utilsService.clearCache(OTHER_ENTITY_NAME, this.cacheManager, this.cacheTenant());
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
`UtilsService`: `getCacheStamp(cache, entityNames, tenantId?)`, `getCacheKey(entityName, params, entityId, tenantId, stamp)`, `clearCache(entityName, cache, tenantId?)` (bumps the stamp; logs instead of throwing).
|
|
350
|
+
|
|
351
|
+
A cached result must depend only on the SQL it ran: anything else (current time, config, the user beyond what the query filters on, feature flags) belongs in the key or the read must not be cached.
|
|
352
|
+
|
|
353
|
+
**Multi-tenant keys:** one cache serves every tenant, so `ApiService` prefixes its keys and stamps 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 calls `UtilsService` itself must pass the same tenant: `cacheTenantId(dataSourceProvider)` from `@flusys/nestjs-shared/utils`, or `this.cacheTenant()` inside an `ApiService`.
|
|
354
|
+
|
|
355
|
+
### Permission cache
|
|
356
|
+
|
|
357
|
+
A user's codes are cached under `[tenant:<id>:]<format>:v:<user stamp>` - the scope key from `buildPermissionCacheKey` (user, or company + branch with `enableCompanyFeature`) plus one stamp per user. `resolvePermissionCacheKey(cache, options, config)` gives the key (resolve it before reading grants from the database, write under that same key); `invalidatePermissionCache(cache, userId, config)` bumps the stamp and drops every company / branch scope of the user on every instance. The tenant prefix is added only when `config.multiTenant` is set - a single database ignores a tenant header.
|
|
358
|
+
|
|
359
|
+
`SharedPermissionCacheService.getPermissions` reads that key and, on a miss (first request, expiry, invalidation), falls back to `PERMISSION_RESOLVER` when it is provided (nestjs-iam); without one, a miss is "no permissions". `setPermissions` writes the current key; `clearPermissions` bumps the user stamp.
|
|
360
|
+
|
|
361
|
+
### Idempotency
|
|
362
|
+
|
|
363
|
+
`IdempotencyInterceptor` keys `X-Idempotency-Key` by tenant, user and endpoint. A stored response is replayed (read with `skipMemory`); otherwise the request `claim`s the key (409 `system.duplicate.request` while another request holds it), stores its response for 24 h with `skipMemory`, and releases the claim on success and on error so a failed request can be retried.
|
|
289
364
|
|
|
290
365
|
## 8. Hybrid Event Bus
|
|
291
366
|
|
|
@@ -412,7 +487,8 @@ so `enabled: false` silences the module everywhere. `delete` and `restore` carry
|
|
|
412
487
|
there is no row left to attach.
|
|
413
488
|
|
|
414
489
|
Payloads are walked before they leave the process: credential-like fields become
|
|
415
|
-
`[REDACTED]
|
|
490
|
+
`[REDACTED]` (matched case and separator blind - `apiKey`, `api_key`, `X-API-KEY`,
|
|
491
|
+
`private-key` alike; `@LogAction({ includeParams: true })` uses the same redaction), a relation that loops back becomes `[CIRCULAR]`, anything past 8 levels deep
|
|
416
492
|
becomes `[TRUNCATED]`, and a Buffer becomes `[BINARY]`. Saved TypeORM rows with
|
|
417
493
|
bidirectional relations are therefore safe to publish. The `config` blob on a
|
|
418
494
|
`storageConfig` or `emailConfig` row is redacted whole - S3, Azure, SFTP and SMTP
|
|
@@ -807,6 +883,31 @@ async listForCurrentBranch(query: SelectQueryBuilder<Invoice>, user: ILoggedUser
|
|
|
807
883
|
}
|
|
808
884
|
```
|
|
809
885
|
|
|
886
|
+
## 10. Expressions
|
|
887
|
+
|
|
888
|
+
A JSON expression tree any package can store and evaluate (`@flusys/nestjs-shared/interfaces` for the types, `/utils` for the engine). Pure functions, no Nest dependencies; every slot that takes a value takes another expression.
|
|
889
|
+
|
|
890
|
+
| `type` | Shape | Result |
|
|
891
|
+
| --- | --- | --- |
|
|
892
|
+
| `literal` | `{ value }` | the value |
|
|
893
|
+
| `field_ref` | `{ ref }` | `ctx.resolveRef(ref)` |
|
|
894
|
+
| `arithmetic` | `{ op, operands[] }` | `sum`, `subtract`, `multiply`, `divide`, `modulo`, `power`, `average`, `min`, `max`; blank operands count as 0 |
|
|
895
|
+
| `concat` | `{ parts[], separator? }` | joined text; with a separator, blank parts are skipped |
|
|
896
|
+
| `template` | `{ template }` | `"{{ ref }}"` placeholders filled through `resolveRef` |
|
|
897
|
+
| `function` | `{ name, args[] }` | see `EXPRESSION_FUNCTIONS`: text (incl. `REGEX_EXTRACT` / `REGEX_REPLACE` / `REGEX_TEST`), number, date (UTC) and `COALESCE` |
|
|
898
|
+
| `if` | `{ condition, whenTrue, whenFalse? }` | `condition` is an AND / OR group of `{ left, comparison, right? }`, groups nest |
|
|
899
|
+
|
|
900
|
+
```typescript
|
|
901
|
+
import { evaluateExpression, assertValidExpression, isExpressionError } from '@flusys/nestjs-shared/utils';
|
|
902
|
+
|
|
903
|
+
assertValidExpression(expr, { isKnownRef: (ref) => fieldIds.has(ref) }); // on save
|
|
904
|
+
const value = evaluateExpression(expr, { resolveRef: (ref) => data[ref] });
|
|
905
|
+
```
|
|
906
|
+
|
|
907
|
+
- Errors are `ExpressionError { code, variables }` (plain, not HTTP) - map `code` to your own message key; check with `isExpressionError()`, not `instanceof`.
|
|
908
|
+
- Limits (`EXPRESSION_LIMITS`): depth 16, 500 nodes, 4000-char templates, 100k-char text results.
|
|
909
|
+
- Regex runs on RE2 via `safeRegexProblem()` / `compileSafeRegex()` (`SAFE_REGEX_LIMITS`): linear time, pattern length / counted-repeat caps. Never `new RegExp` on author input.
|
|
910
|
+
|
|
810
911
|
## License
|
|
811
912
|
|
|
812
913
|
MIT © FLUSYS
|
|
@@ -25,6 +25,7 @@ export declare function createApiController<CreateDtoT extends object, UpdateDto
|
|
|
25
25
|
readonly enabledEndpoints: ApiEndpoint[] | "all";
|
|
26
26
|
service: ServiceT;
|
|
27
27
|
isEnabled(endpoint: ApiEndpoint): boolean;
|
|
28
|
+
assertEnabled(endpoint: ApiEndpoint): void;
|
|
28
29
|
insert(addDto: CreateDtoT, user: ILoggedUserInfo | null): Promise<SingleResponseDto<ResponseDtoT>>;
|
|
29
30
|
insertMany(addDto: CreateDtoT[], user: ILoggedUserInfo | null): Promise<BulkResponseDto<ResponseDtoT>>;
|
|
30
31
|
getById(id: string, body: GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<ResponseDtoT>>;
|
|
@@ -23,9 +23,16 @@ export declare abstract class ApiService<CreateDtoT extends object, UpdateDtoT e
|
|
|
23
23
|
private repositoryInitialized;
|
|
24
24
|
private readonly _entity;
|
|
25
25
|
private readonly _dataSourceProvider;
|
|
26
|
+
private readonly logger;
|
|
26
27
|
constructor(entityName: string, cacheManager: HybridCache, utilsService: UtilsService, _loggerName: string, isCacheable: boolean | undefined, moduleName: string, dataSourceProvider: IDataSourceProvider, entity: EntityTarget<EntityT>);
|
|
27
28
|
protected getDataSourceProvider(): IDataSourceProvider;
|
|
28
29
|
protected cacheTenant(): string | undefined;
|
|
30
|
+
protected cacheDependencies(): string[];
|
|
31
|
+
protected bypassListCache(_filterAndPaginationDto: FilterAndPaginationDto): boolean;
|
|
32
|
+
invalidateCache(): Promise<void>;
|
|
33
|
+
private readCacheStamp;
|
|
34
|
+
private readCached;
|
|
35
|
+
private writeCached;
|
|
29
36
|
protected ensureDataSourceRepository(): Promise<void>;
|
|
30
37
|
protected resolveRepositories(entities: EntityTarget<any>[]): Promise<Repository<any>[]>;
|
|
31
38
|
insert(dto: CreateDtoT, user: ILoggedUserInfo | null): Promise<InterfaceT>;
|
|
@@ -42,8 +49,6 @@ export declare abstract class ApiService<CreateDtoT extends object, UpdateDtoT e
|
|
|
42
49
|
delete(option: DeleteDto, user: ILoggedUserInfo | null): Promise<null>;
|
|
43
50
|
protected publishLifecycleEvents(groups: IEventGroup<EntityT>[], user: ILoggedUserInfo | null): Promise<void>;
|
|
44
51
|
protected publishDomainAction(action: string, input?: Omit<IPublishDomainEventInput, 'module' | 'entity' | 'action'>): Promise<void>;
|
|
45
|
-
clearCacheForAll(): Promise<void>;
|
|
46
|
-
clearCacheForId(entities: EntityT[]): Promise<void>;
|
|
47
52
|
private handleError;
|
|
48
53
|
private ensureArray;
|
|
49
54
|
private executeInTransaction;
|
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
export type CacheMode = 'memory' | 'redis' | 'hybrid';
|
|
2
|
+
export interface ICacheAccessOptions {
|
|
3
|
+
skipMemory?: boolean;
|
|
4
|
+
}
|
|
1
5
|
export declare class HybridCache {
|
|
6
|
+
private readonly mode;
|
|
7
|
+
private readonly defaultTtl;
|
|
2
8
|
private memory?;
|
|
3
9
|
private redis?;
|
|
10
|
+
private redisStore?;
|
|
11
|
+
private localAtomic?;
|
|
4
12
|
constructor(memoryTtl?: number, memorySize?: number);
|
|
5
|
-
|
|
6
|
-
|
|
13
|
+
getMode(): CacheMode;
|
|
14
|
+
get<T>(key: string, options?: ICacheAccessOptions): Promise<T | undefined>;
|
|
15
|
+
set<T>(key: string, value: T, ttl?: number, options?: ICacheAccessOptions): Promise<void>;
|
|
7
16
|
del(key: string): Promise<void>;
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
getStamp(name: string): Promise<string>;
|
|
18
|
+
bumpStamp(name: string): Promise<void>;
|
|
19
|
+
claim(name: string, ttl: number): Promise<boolean>;
|
|
20
|
+
releaseClaim(name: string): Promise<void>;
|
|
21
|
+
take<T>(key: string, ttl: number): Promise<T | undefined>;
|
|
22
|
+
private rawKey;
|
|
10
23
|
}
|
package/constants/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare const EVENT_BUS_MODULE_OPTIONS = "EVENT_BUS_MODULE_OPTIONS";
|
|
|
8
8
|
export declare const IDEMPOTENCY_KEY_HEADER = "x-idempotency-key";
|
|
9
9
|
export declare const REQUEST_ID_HEADER = "x-request-id";
|
|
10
10
|
export declare const CLIENT_TYPE_HEADER = "x-client-type";
|
|
11
|
+
export declare const TENANT_ID_PATTERN: RegExp;
|
|
11
12
|
export declare const PERMISSIONS_CACHE_PREFIX = "my-permissions";
|
|
12
13
|
export declare const IDEMPOTENCY_CACHE_PREFIX = "idempotency";
|
|
13
14
|
export declare const DEFAULT_EVENT_EXCHANGE = "flusys.events";
|
|
@@ -51,6 +51,9 @@ export declare const COMPANY_ACTION_PERMISSIONS: {
|
|
|
51
51
|
readonly READ: "company-action.read";
|
|
52
52
|
readonly ASSIGN: "company-action.assign";
|
|
53
53
|
};
|
|
54
|
+
export declare const CROSS_COMPANY_PERMISSIONS: {
|
|
55
|
+
readonly ASSIGN: "cross-company.assign";
|
|
56
|
+
};
|
|
54
57
|
export declare const FILE_PERMISSIONS: {
|
|
55
58
|
readonly CREATE: "file.create";
|
|
56
59
|
readonly READ: "file.read";
|
|
@@ -239,6 +242,9 @@ export declare const PERMISSIONS: {
|
|
|
239
242
|
readonly READ: "company-action.read";
|
|
240
243
|
readonly ASSIGN: "company-action.assign";
|
|
241
244
|
};
|
|
245
|
+
readonly CROSS_COMPANY: {
|
|
246
|
+
readonly ASSIGN: "cross-company.assign";
|
|
247
|
+
};
|
|
242
248
|
readonly FILE: {
|
|
243
249
|
readonly CREATE: "file.create";
|
|
244
250
|
readonly READ: "file.read";
|
|
@@ -258,6 +264,9 @@ export declare const PERMISSIONS: {
|
|
|
258
264
|
readonly UPDATE: "storage-config.update";
|
|
259
265
|
readonly DELETE: "storage-config.delete";
|
|
260
266
|
};
|
|
267
|
+
readonly UPLOAD_CONFIG: {
|
|
268
|
+
readonly DELETE: "upload-config.delete";
|
|
269
|
+
};
|
|
261
270
|
readonly EMAIL_CONFIG: {
|
|
262
271
|
readonly CREATE: "email-config.create";
|
|
263
272
|
readonly READ: "email-config.read";
|
package/fesm/183.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as __rspack_external_class_validator_7b99ef4d from "class-validator";
|
|
|
4
4
|
export const __rspack_esm_id = 183;
|
|
5
5
|
export const __rspack_esm_ids = [183];
|
|
6
6
|
export const __webpack_modules__ = {
|
|
7
|
-
|
|
7
|
+
3746(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
8
8
|
|
|
9
9
|
// EXPORTS
|
|
10
10
|
__webpack_require__.d(__webpack_exports__, {
|
|
@@ -24,9 +24,9 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
// EXTERNAL MODULE: external "@nestjs/swagger"
|
|
27
|
-
var swagger_ = __webpack_require__(
|
|
27
|
+
var swagger_ = __webpack_require__(6176);
|
|
28
28
|
// EXTERNAL MODULE: external "class-validator"
|
|
29
|
-
var external_class_validator_ = __webpack_require__(
|
|
29
|
+
var external_class_validator_ = __webpack_require__(5421);
|
|
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;
|
|
@@ -106,7 +106,7 @@ _ts_decorate([
|
|
|
106
106
|
], DeleteDto.prototype, "deletedById", void 0);
|
|
107
107
|
|
|
108
108
|
// EXTERNAL MODULE: external "class-transformer"
|
|
109
|
-
var external_class_transformer_ = __webpack_require__(
|
|
109
|
+
var external_class_transformer_ = __webpack_require__(5812);
|
|
110
110
|
;// CONCATENATED MODULE: ./projects/nestjs-shared/src/dtos/pagination.dto.ts
|
|
111
111
|
function pagination_dto_ts_decorate(decorators, target, key, desc) {
|
|
112
112
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -777,19 +777,19 @@ MessageResponseDto = response_payload_dto_ts_decorate([
|
|
|
777
777
|
|
|
778
778
|
|
|
779
779
|
},
|
|
780
|
-
|
|
780
|
+
6176(module) {
|
|
781
781
|
|
|
782
782
|
module.exports = __rspack_external__nestjs_swagger_7cd450b5;
|
|
783
783
|
|
|
784
784
|
|
|
785
785
|
},
|
|
786
|
-
|
|
786
|
+
5812(module) {
|
|
787
787
|
|
|
788
788
|
module.exports = __rspack_external_class_transformer_c5a479fb;
|
|
789
789
|
|
|
790
790
|
|
|
791
791
|
},
|
|
792
|
-
|
|
792
|
+
5421(module) {
|
|
793
793
|
|
|
794
794
|
module.exports = __rspack_external_class_validator_7b99ef4d;
|
|
795
795
|
|