itlab-internal-services 2.16.4 → 2.16.6

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 (48) hide show
  1. package/dist/classes/document/index.d.ts +1 -0
  2. package/dist/classes/document/index.js +3 -1
  3. package/dist/classes/document/likeable-document.class.d.ts +3 -1
  4. package/dist/classes/document/likeable-document.class.js +5 -1
  5. package/dist/classes/document/timestamps-document.class.d.ts +200 -0
  6. package/dist/classes/document/timestamps-document.class.js +27 -0
  7. package/dist/classes/document/viewable-document.class.d.ts +3 -1
  8. package/dist/classes/document/viewable-document.class.js +5 -1
  9. package/dist/classes/entity-map.class.d.ts +21 -0
  10. package/dist/classes/entity-map.class.js +28 -0
  11. package/dist/classes/fetch-options/base-options.class.d.ts +2 -0
  12. package/dist/classes/fetch-options/base-options.class.js +17 -0
  13. package/dist/classes/fetch-options/comments-options.class.d.ts +8 -0
  14. package/dist/classes/fetch-options/comments-options.class.js +14 -0
  15. package/dist/classes/fetch-options/content-options.class.d.ts +8 -1
  16. package/dist/classes/fetch-options/content-options.class.js +14 -0
  17. package/dist/classes/fetch-options/drafted-options.class.d.ts +7 -2
  18. package/dist/classes/fetch-options/drafted-options.class.js +12 -1
  19. package/dist/classes/fetch-options/index.d.ts +7 -6
  20. package/dist/classes/fetch-options/index.js +21 -13
  21. package/dist/classes/fetch-options/liked-by-options.class.d.ts +7 -0
  22. package/dist/classes/fetch-options/liked-by-options.class.js +27 -0
  23. package/dist/classes/fetch-options/timestamps-options.class.d.ts +12 -0
  24. package/dist/classes/fetch-options/timestamps-options.class.js +38 -0
  25. package/dist/classes/fetch-options/viewed-by-options.class.d.ts +10 -2
  26. package/dist/classes/fetch-options/viewed-by-options.class.js +35 -1
  27. package/dist/classes/index.d.ts +1 -0
  28. package/dist/classes/index.js +3 -1
  29. package/dist/classes/task-manager.class.d.ts +0 -34
  30. package/dist/classes/task-manager.class.js +0 -54
  31. package/dist/decorators/authenticated-account.decorator.d.ts +1 -1
  32. package/dist/index.d.ts +0 -1
  33. package/dist/index.js +0 -1
  34. package/dist/middleware/http-logging.middleware.js +1 -11
  35. package/dist/modules/services/providers/accounts.service.d.ts +15 -0
  36. package/dist/modules/services/providers/accounts.service.js +45 -2
  37. package/dist/modules/services/providers/mail/dtos/event-cancel-mail.dto.d.ts +4 -0
  38. package/dist/pipes/restricted-fields.pipe.d.ts +1 -24
  39. package/dist/pipes/restricted-fields.pipe.js +22 -20
  40. package/dist/types/has-timestamps.type.d.ts +4 -0
  41. package/dist/types/has-timestamps.type.js +2 -0
  42. package/dist/types/index.d.ts +1 -0
  43. package/dist/types/index.js +1 -0
  44. package/package.json +1 -1
  45. package/dist/interceptors/attribute-sanitizer.interceptor.d.ts +0 -68
  46. package/dist/interceptors/attribute-sanitizer.interceptor.js +0 -154
  47. package/dist/interceptors/index.d.ts +0 -1
  48. package/dist/interceptors/index.js +0 -17
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.LikedByOptions = LikedByOptions;
13
+ exports.populateLikedBy = populateLikedBy;
13
14
  const swagger_1 = require("@nestjs/swagger");
14
15
  const class_validator_1 = require("class-validator");
15
16
  const transform_1 = require("../../transform");
@@ -22,5 +23,31 @@ function LikedByOptions(Base) {
22
23
  (0, class_validator_1.IsOptional)(),
23
24
  __metadata("design:type", Boolean)
24
25
  ], LikedByOptions.prototype, "includeLikedBy", void 0);
26
+ __decorate([
27
+ (0, swagger_1.ApiPropertyOptional)({}),
28
+ (0, transform_1.BooleanTransform)(),
29
+ (0, class_validator_1.IsOptional)(),
30
+ __metadata("design:type", Boolean)
31
+ ], LikedByOptions.prototype, "includeLikedByIds", void 0);
25
32
  return LikedByOptions;
26
33
  }
34
+ async function populateLikedBy(options, items, accountsService) {
35
+ if (options.includeLikedBy) {
36
+ const userMap = await accountsService.getUserMap(items.map((item) => item._likedBy));
37
+ items.forEach((item) => {
38
+ item.likedBy = userMap.getMultiple(item._likedBy);
39
+ });
40
+ }
41
+ items.forEach((item) => {
42
+ item.likes = Math.max(item._likedBy.length, item.likes); // TODO: Tmp Fix
43
+ if (!options.includeLikedBy) {
44
+ delete item.likedBy;
45
+ }
46
+ if (!options.includeLikedByIds) {
47
+ delete item._likedBy;
48
+ }
49
+ if (!(options.includeLikedBy || options.includeLikedByIds)) {
50
+ delete item.likes;
51
+ }
52
+ });
53
+ }
@@ -0,0 +1,12 @@
1
+ import { HasTimestamps } from '../../types';
2
+ export declare function TimestampsOptions<TBase extends new (...args: any[]) => any>(Base: TBase, options: {
3
+ requiredPermissions: string[];
4
+ }): {
5
+ new (...args: any[]): {
6
+ [x: string]: any;
7
+ includeTimestamps?: boolean;
8
+ };
9
+ } & TBase;
10
+ export declare function populateTimestamps<TOptions extends {
11
+ includeTimestamps?: boolean;
12
+ }, TItems extends HasTimestamps>(options: TOptions, items: TItems[], additionalKeys?: (keyof TItems)[]): void;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TimestampsOptions = TimestampsOptions;
13
+ exports.populateTimestamps = populateTimestamps;
14
+ const swagger_1 = require("@nestjs/swagger");
15
+ const class_validator_1 = require("class-validator");
16
+ const pipes_1 = require("../../pipes");
17
+ const transform_1 = require("../../transform");
18
+ function TimestampsOptions(Base, options) {
19
+ class TimestampsOptions extends Base {
20
+ }
21
+ __decorate([
22
+ (0, swagger_1.ApiPropertyOptional)({}),
23
+ (0, transform_1.BooleanTransform)(),
24
+ (0, class_validator_1.IsOptional)(),
25
+ (0, pipes_1.Restricted)(options.requiredPermissions),
26
+ __metadata("design:type", Boolean)
27
+ ], TimestampsOptions.prototype, "includeTimestamps", void 0);
28
+ return TimestampsOptions;
29
+ }
30
+ function populateTimestamps(options, items, additionalKeys = []) {
31
+ if (!options.includeTimestamps) {
32
+ items.forEach((item) => {
33
+ delete item.createdAt;
34
+ delete item.updatedAt;
35
+ additionalKeys.forEach((key) => delete item[key]);
36
+ });
37
+ }
38
+ }
@@ -1,9 +1,17 @@
1
- export declare function ViewedByOptions<TBase extends new (...args: any[]) => any>(Base: TBase, options?: {
2
- requiredPermissions?: string[];
1
+ import { AccountsService } from '../../modules';
2
+ import { IsViewable } from '../../types';
3
+ export declare function ViewedByOptions<TBase extends new (...args: any[]) => any>(Base: TBase, options: {
4
+ requiredPermissions: string[];
3
5
  }): {
4
6
  new (...args: any[]): {
5
7
  [x: string]: any;
6
8
  includeViewedBy?: boolean;
9
+ includeViewedByIds?: boolean;
7
10
  viewedBy?: string;
8
11
  };
9
12
  } & TBase;
13
+ export declare function populateViewedBy(options: {
14
+ includeViewedBy?: boolean;
15
+ includeViewedByIds?: boolean;
16
+ viewedBy?: string;
17
+ }, items: IsViewable[], accountsService: AccountsService): Promise<void>;
@@ -10,8 +10,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ViewedByOptions = ViewedByOptions;
13
+ exports.populateViewedBy = populateViewedBy;
13
14
  const swagger_1 = require("@nestjs/swagger");
14
15
  const class_validator_1 = require("class-validator");
16
+ const rxjs_1 = require("rxjs");
15
17
  const pipes_1 = require("../../pipes");
16
18
  const transform_1 = require("../../transform");
17
19
  function ViewedByOptions(Base, options) {
@@ -21,8 +23,40 @@ function ViewedByOptions(Base, options) {
21
23
  (0, swagger_1.ApiPropertyOptional)({}),
22
24
  (0, transform_1.BooleanTransform)(),
23
25
  (0, class_validator_1.IsOptional)(),
24
- (0, pipes_1.Restricted)(options === null || options === void 0 ? void 0 : options.requiredPermissions),
26
+ (0, pipes_1.Restricted)(options.requiredPermissions),
25
27
  __metadata("design:type", Boolean)
26
28
  ], ViewedByOptions.prototype, "includeViewedBy", void 0);
29
+ __decorate([
30
+ (0, swagger_1.ApiPropertyOptional)({}),
31
+ (0, transform_1.BooleanTransform)(),
32
+ (0, class_validator_1.IsOptional)(),
33
+ (0, pipes_1.Restricted)(options.requiredPermissions),
34
+ __metadata("design:type", Boolean)
35
+ ], ViewedByOptions.prototype, "includeViewedByIds", void 0);
27
36
  return ViewedByOptions;
28
37
  }
38
+ async function populateViewedBy(options, items, accountsService) {
39
+ if (options.viewedBy) {
40
+ items.forEach((item) => {
41
+ item.addView(options.viewedBy).then(rxjs_1.noop);
42
+ });
43
+ }
44
+ if (options.includeViewedBy) {
45
+ const userMap = await accountsService.getUserMap(items.map((item) => item._viewedBy));
46
+ items.forEach((item) => {
47
+ item.viewedBy = userMap.getMultiple(item._viewedBy);
48
+ });
49
+ }
50
+ items.forEach((item) => {
51
+ item.views = Math.max(item._viewedBy.length, item.views); // TODO: Tmp Fix
52
+ if (!options.includeViewedBy) {
53
+ delete item.viewedBy;
54
+ }
55
+ if (!options.includeViewedByIds) {
56
+ delete item._viewedBy;
57
+ }
58
+ if (!(options.includeViewedBy || options.includeViewedByIds)) {
59
+ delete item.views;
60
+ }
61
+ });
62
+ }
@@ -1,5 +1,6 @@
1
1
  export * from './document';
2
2
  export * from './fetch-options';
3
3
  export { DocumentMerger } from './document-merger.class';
4
+ export { EntityMap } from './entity-map.class';
4
5
  export { ReportCategory } from './report-category.class';
5
6
  export { TaskManager } from './task-manager.class';
@@ -14,11 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.TaskManager = exports.ReportCategory = exports.DocumentMerger = void 0;
17
+ exports.TaskManager = exports.ReportCategory = exports.EntityMap = exports.DocumentMerger = void 0;
18
18
  __exportStar(require("./document"), exports);
19
19
  __exportStar(require("./fetch-options"), exports);
20
20
  var document_merger_class_1 = require("./document-merger.class");
21
21
  Object.defineProperty(exports, "DocumentMerger", { enumerable: true, get: function () { return document_merger_class_1.DocumentMerger; } });
22
+ var entity_map_class_1 = require("./entity-map.class");
23
+ Object.defineProperty(exports, "EntityMap", { enumerable: true, get: function () { return entity_map_class_1.EntityMap; } });
22
24
  var report_category_class_1 = require("./report-category.class");
23
25
  Object.defineProperty(exports, "ReportCategory", { enumerable: true, get: function () { return report_category_class_1.ReportCategory; } });
24
26
  var task_manager_class_1 = require("./task-manager.class");
@@ -1,5 +1,3 @@
1
- import { Account, User } from '../models';
2
- import { AccountsService } from '../modules';
3
1
  /**
4
2
  * TaskManager is a utility class that collects asynchronous tasks
5
3
  * and executes them in parallel.
@@ -17,38 +15,6 @@ import { AccountsService } from '../modules';
17
15
  */
18
16
  export declare class TaskManager {
19
17
  private tasks;
20
- /**
21
- * Fetches all users for the given ID groups and returns a mapping.
22
- * Ensures each user is fetched only once.
23
- * @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
24
- * @param accountsService Service responsible for fetching users
25
- * @returns Map of userId -> user
26
- */
27
- static fetchAndMapUsers(userIdGroups: string[][], accountsService: AccountsService): Promise<Map<string, User>>;
28
- /**
29
- * Fetches all users for the given ID groups and returns a mapping.
30
- * Ensures each user is fetched only once.
31
- * @param accountIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
32
- * @param accountsService Service responsible for fetching users
33
- * @returns Map of userId -> user
34
- */
35
- static fetchAndMapAccounts(accountIdGroups: string[][], accountsService: AccountsService): Promise<Map<string, Account>>;
36
- /**
37
- * Maps an array of IDs to user objects using a userMap.
38
- * Filters out any IDs that don’t have a corresponding user.
39
- * @param userIds Array of user IDs to map
40
- * @param userMap Map of userId -> user object
41
- * @returns Array of user objects
42
- */
43
- static mapIdsToUsers(userIds: string[], userMap: Map<string, User>): User[];
44
- /**
45
- * Maps an array of IDs to user objects using a userMap.
46
- * Filters out any IDs that don’t have a corresponding user.
47
- * @param accountIds Array of user IDs to map
48
- * @param accountMap Map of userId -> user object
49
- * @returns Array of user objects
50
- */
51
- static mapIdsToAccounts(accountIds: string[], accountMap: Map<string, Account>): Account[];
52
18
  /**
53
19
  * Adds a new asynchronous task to the queue.
54
20
  *
@@ -20,60 +20,6 @@ class TaskManager {
20
20
  constructor() {
21
21
  this.tasks = [];
22
22
  }
23
- /**
24
- * Fetches all users for the given ID groups and returns a mapping.
25
- * Ensures each user is fetched only once.
26
- * @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
27
- * @param accountsService Service responsible for fetching users
28
- * @returns Map of userId -> user
29
- */
30
- static async fetchAndMapUsers(userIdGroups, accountsService) {
31
- // Collect all unique user IDs across all groups
32
- const uniqueUserIds = new Set(userIdGroups.flat());
33
- if (uniqueUserIds.size === 0)
34
- return new Map();
35
- // Fetch all users once
36
- const userCollection = await accountsService.getUserCollection(Array.from(uniqueUserIds));
37
- // Build a map for quick lookup
38
- return new Map(userCollection.map((user) => [user.id, user]));
39
- }
40
- /**
41
- * Fetches all users for the given ID groups and returns a mapping.
42
- * Ensures each user is fetched only once.
43
- * @param accountIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
44
- * @param accountsService Service responsible for fetching users
45
- * @returns Map of userId -> user
46
- */
47
- static async fetchAndMapAccounts(accountIdGroups, accountsService) {
48
- // Collect all unique user IDs across all groups
49
- const uniqueAccountIds = new Set(accountIdGroups.flat());
50
- if (uniqueAccountIds.size === 0)
51
- return new Map();
52
- // Fetch all users once
53
- const accountCollection = await accountsService.getAccountCollection(Array.from(uniqueAccountIds));
54
- // Build a map for quick lookup
55
- return new Map(accountCollection.map((account) => [account.id, account]));
56
- }
57
- /**
58
- * Maps an array of IDs to user objects using a userMap.
59
- * Filters out any IDs that don’t have a corresponding user.
60
- * @param userIds Array of user IDs to map
61
- * @param userMap Map of userId -> user object
62
- * @returns Array of user objects
63
- */
64
- static mapIdsToUsers(userIds, userMap) {
65
- return userIds.map((userId) => userMap.get(userId)).filter(Boolean);
66
- }
67
- /**
68
- * Maps an array of IDs to user objects using a userMap.
69
- * Filters out any IDs that don’t have a corresponding user.
70
- * @param accountIds Array of user IDs to map
71
- * @param accountMap Map of userId -> user object
72
- * @returns Array of user objects
73
- */
74
- static mapIdsToAccounts(accountIds, accountMap) {
75
- return accountIds.map((accountId) => accountMap.get(accountId)).filter(Boolean);
76
- }
77
23
  /**
78
24
  * Adds a new asynchronous task to the queue.
79
25
  *
@@ -14,4 +14,4 @@ import { Account } from '../models';
14
14
  * @param {ExecutionContext} executionContext - The context of the current request.
15
15
  * @returns {Account[keyof Account] | Account} The requested account attribute or full account object.
16
16
  */
17
- export declare const AuthenticatedAccount: (...dataOrPipes: (keyof Account | import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>>)[]) => ParameterDecorator;
17
+ export declare const AuthenticatedAccount: (...dataOrPipes: (import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>> | keyof Account)[]) => ParameterDecorator;
package/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@ export * from './controllers';
3
3
  export * from './decorators';
4
4
  export * from './exceptions';
5
5
  export * from './functions';
6
- export * from './interceptors';
7
6
  export * from './middleware';
8
7
  export * from './models';
9
8
  export * from './modules';
package/dist/index.js CHANGED
@@ -20,7 +20,6 @@ __exportStar(require("./controllers"), exports);
20
20
  __exportStar(require("./decorators"), exports);
21
21
  __exportStar(require("./exceptions"), exports);
22
22
  __exportStar(require("./functions"), exports);
23
- __exportStar(require("./interceptors"), exports);
24
23
  __exportStar(require("./middleware"), exports);
25
24
  __exportStar(require("./models"), exports);
26
25
  __exportStar(require("./modules"), exports);
@@ -33,17 +33,7 @@ const HttpLoggingMiddleware = (req, res, next) => {
33
33
  next();
34
34
  return;
35
35
  }
36
- // Defer logging until after the response has finished,
37
- // ensuring accurate status information
38
- res.on('finish', () => {
39
- const { statusCode, statusMessage } = res;
40
- // Construct a standardized log message
41
- const logMessage = `${method} ${url} - ${statusCode} (${statusMessage})`;
42
- // Client errors (4xx) are logged at warn level for visibility
43
- // All other responses use standard log level
44
- const logLevel = statusCode >= 400 && statusCode < 500 ? 'warn' : 'log';
45
- logger[logLevel](logMessage);
46
- });
36
+ logger.log(`Handle ${method} ${url}`);
47
37
  // Continue to next middleware or request handler
48
38
  next();
49
39
  };
@@ -1,4 +1,5 @@
1
1
  import { ConfigService } from '@nestjs/config';
2
+ import { EntityMap } from '../../../classes';
2
3
  import { Account, User } from '../../../models';
3
4
  import { AuthenticationModuleOptions } from '../../authentication';
4
5
  import { BaseHttpService } from '../base-http.service';
@@ -35,6 +36,13 @@ export declare class AccountsService extends BaseHttpService {
35
36
  * @returns {Promise<Account[]>} Resolves to an array of account objects (empty if none found).
36
37
  */
37
38
  getAccountCollection(accountIds: string[]): Promise<Account[]>;
39
+ /**
40
+ * Fetches all accounts for the given ID groups and returns a mapping.
41
+ * Ensures each account is fetched only once.
42
+ * @param accountIdGroups Array of arrays of account IDs (e.g., authors, likedBy, viewedBy)
43
+ * @returns Map of accountId -> Account
44
+ */
45
+ getAccountMap(accountIdGroups: string[][]): Promise<EntityMap<Account>>;
38
46
  /**
39
47
  * Retrieves a single user entry derived from an account.
40
48
  *
@@ -49,4 +57,11 @@ export declare class AccountsService extends BaseHttpService {
49
57
  * @returns {Promise<User[]>} Resolves to a list of users (empty array if none found).
50
58
  */
51
59
  getUserCollection(userIds: string[]): Promise<User[]>;
60
+ /**
61
+ * Fetches all users for the given ID groups and returns a mapping.
62
+ * Ensures each user is fetched only once.
63
+ * @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
64
+ * @returns Map of userId -> user
65
+ */
66
+ getUserMap(userIdGroups: string[][]): Promise<EntityMap<User>>;
52
67
  }
@@ -15,9 +15,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.AccountsService = void 0;
16
16
  const common_1 = require("@nestjs/common");
17
17
  const config_1 = require("@nestjs/config");
18
+ const itlab_functions_1 = require("itlab-functions");
19
+ const classes_1 = require("../../../classes");
18
20
  const authentication_1 = require("../../authentication");
19
21
  const base_http_service_1 = require("../base-http.service");
20
22
  const base_urls_1 = require("../base-urls");
23
+ const chunkSize = 100;
21
24
  /**
22
25
  * AccountsService
23
26
  *
@@ -57,7 +60,27 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
57
60
  async getAccountCollection(accountIds) {
58
61
  if (accountIds.length === 0)
59
62
  return [];
60
- return this.fetchResourceCollection(`internal/accounts`, { params: { ids: accountIds } });
63
+ const chunkedAccountIds = (0, itlab_functions_1.createChunks)(accountIds, chunkSize);
64
+ const chunkedAccounts = chunkedAccountIds.map((accountIds) => {
65
+ return this.fetchResourceCollection(`internal/accounts`, { params: { ids: accountIds } });
66
+ });
67
+ return (await Promise.all(chunkedAccounts)).flat();
68
+ }
69
+ /**
70
+ * Fetches all accounts for the given ID groups and returns a mapping.
71
+ * Ensures each account is fetched only once.
72
+ * @param accountIdGroups Array of arrays of account IDs (e.g., authors, likedBy, viewedBy)
73
+ * @returns Map of accountId -> Account
74
+ */
75
+ async getAccountMap(accountIdGroups) {
76
+ // Collect all unique account IDs across all groups
77
+ const uniqueAccountIds = new Set(accountIdGroups.flat());
78
+ if (uniqueAccountIds.size === 0)
79
+ return new classes_1.EntityMap();
80
+ // Fetch all accounts once
81
+ const accountCollection = await this.getAccountCollection(Array.from(uniqueAccountIds));
82
+ // Build a map for quick lookup
83
+ return new classes_1.EntityMap(accountCollection);
61
84
  }
62
85
  /**
63
86
  * Retrieves a single user entry derived from an account.
@@ -77,7 +100,27 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
77
100
  async getUserCollection(userIds) {
78
101
  if (userIds.length === 0)
79
102
  return [];
80
- return this.fetchResourceCollection(`internal/users`, { params: { ids: userIds } });
103
+ const chunkedUserIds = (0, itlab_functions_1.createChunks)(userIds, chunkSize);
104
+ const chunkedUsers = chunkedUserIds.map((userIds) => {
105
+ return this.fetchResourceCollection(`internal/users`, { params: { ids: userIds } });
106
+ });
107
+ return (await Promise.all(chunkedUsers)).flat();
108
+ }
109
+ /**
110
+ * Fetches all users for the given ID groups and returns a mapping.
111
+ * Ensures each user is fetched only once.
112
+ * @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
113
+ * @returns Map of userId -> user
114
+ */
115
+ async getUserMap(userIdGroups) {
116
+ // Collect all unique user IDs across all groups
117
+ const uniqueUserIds = new Set(userIdGroups.flat());
118
+ if (uniqueUserIds.size === 0)
119
+ return new classes_1.EntityMap();
120
+ // Fetch all users once
121
+ const userCollection = await this.getUserCollection(Array.from(uniqueUserIds));
122
+ // Build a map for quick lookup
123
+ return new classes_1.EntityMap(userCollection);
81
124
  }
82
125
  };
83
126
  exports.AccountsService = AccountsService;
@@ -4,6 +4,10 @@ import { MailRecipient } from '../models';
4
4
  */
5
5
  export type EventCancelMailDto = {
6
6
  recipient: MailRecipient;
7
+ /**
8
+ * Mode of participation (e.g., in person, online).
9
+ */
10
+ participation?: string;
7
11
  /**
8
12
  * Title of the event that has been cancelled.
9
13
  * @example "Meetup"
@@ -1,8 +1,3 @@
1
- import { ArgumentMetadata, PipeTransform } from '@nestjs/common';
2
- import { Reflector } from '@nestjs/core';
3
- import { Request } from 'express';
4
- import { Account } from '../models';
5
- import { AuthenticationModuleOptions } from '../modules';
6
1
  /**
7
2
  * @Restricted Decorator
8
3
  *
@@ -14,22 +9,4 @@ import { AuthenticationModuleOptions } from '../modules';
14
9
  * @param {...string[]} perms - One or more permissions required to retain this field.
15
10
  */
16
11
  export declare function Restricted(perms?: string | string[]): PropertyDecorator;
17
- /**
18
- * RestrictedFieldsPipe
19
- *
20
- * Global pipe that inspects incoming DTOs for properties decorated with `@Restricted`.
21
- * If the current request's account lacks the required permissions,
22
- * the corresponding properties are stripped from the DTO.
23
- *
24
- * This ensures that sensitive fields are never accidentally
25
- * processed further down the request lifecycle.
26
- */
27
- export declare class RestrictedFieldsPipe implements PipeTransform {
28
- private readonly request;
29
- private readonly authenticationOptions;
30
- private readonly reflector;
31
- constructor(request: Request & {
32
- account?: Account;
33
- }, authenticationOptions: AuthenticationModuleOptions, reflector: Reflector);
34
- transform(value: unknown, metadata: ArgumentMetadata): any;
35
- }
12
+ export declare function UseRestricted(): ClassDecorator;
@@ -12,8 +12,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.RestrictedFieldsPipe = void 0;
16
15
  exports.Restricted = Restricted;
16
+ exports.UseRestricted = UseRestricted;
17
17
  const common_1 = require("@nestjs/common");
18
18
  const core_1 = require("@nestjs/core");
19
19
  const class_validator_1 = require("class-validator");
@@ -21,23 +21,6 @@ const itlab_functions_1 = require("itlab-functions");
21
21
  const modules_1 = require("../modules");
22
22
  const service_auth_guard_1 = require("../modules/authentication/guards/service-auth.guard");
23
23
  const RESTRICTED_METADATA_KEY = Symbol('itlab-restricted-metadata');
24
- /**
25
- * @Restricted Decorator
26
- *
27
- * Marks a DTO property as restricted to specific permissions.
28
- * When a request passes through the global `RestrictedFieldsPipe`,
29
- * these properties will be removed if the requesting account does not
30
- * have all required permissions.
31
- *
32
- * @param {...string[]} perms - One or more permissions required to retain this field.
33
- */
34
- function Restricted(perms) {
35
- return (target, propertyKey) => {
36
- // Store metadata without touching the property descriptor
37
- const existingMetadata = Reflect.getMetadata(RESTRICTED_METADATA_KEY, target) || {};
38
- Reflect.defineMetadata(RESTRICTED_METADATA_KEY, Object.assign(Object.assign({}, existingMetadata), { [propertyKey.toString()]: [perms !== null && perms !== void 0 ? perms : []].flat() }), target);
39
- };
40
- }
41
24
  /**
42
25
  * RestrictedFieldsPipe
43
26
  *
@@ -76,10 +59,29 @@ let RestrictedFieldsPipe = class RestrictedFieldsPipe {
76
59
  return value;
77
60
  }
78
61
  };
79
- exports.RestrictedFieldsPipe = RestrictedFieldsPipe;
80
- exports.RestrictedFieldsPipe = RestrictedFieldsPipe = __decorate([
62
+ RestrictedFieldsPipe = __decorate([
81
63
  (0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
82
64
  __param(0, (0, common_1.Inject)(core_1.REQUEST)),
83
65
  __param(1, (0, modules_1.InjectAuthenticationOptions)()),
84
66
  __metadata("design:paramtypes", [Object, Object, core_1.Reflector])
85
67
  ], RestrictedFieldsPipe);
68
+ /**
69
+ * @Restricted Decorator
70
+ *
71
+ * Marks a DTO property as restricted to specific permissions.
72
+ * When a request passes through the global `RestrictedFieldsPipe`,
73
+ * these properties will be removed if the requesting account does not
74
+ * have all required permissions.
75
+ *
76
+ * @param {...string[]} perms - One or more permissions required to retain this field.
77
+ */
78
+ function Restricted(perms) {
79
+ return (target, propertyKey) => {
80
+ // Store metadata without touching the property descriptor
81
+ const existingMetadata = Reflect.getMetadata(RESTRICTED_METADATA_KEY, target) || {};
82
+ Reflect.defineMetadata(RESTRICTED_METADATA_KEY, Object.assign(Object.assign({}, existingMetadata), { [propertyKey.toString()]: [perms !== null && perms !== void 0 ? perms : []].flat() }), target);
83
+ };
84
+ }
85
+ function UseRestricted() {
86
+ return (0, common_1.applyDecorators)((0, common_1.UsePipes)(RestrictedFieldsPipe));
87
+ }
@@ -0,0 +1,4 @@
1
+ export type HasTimestamps = {
2
+ createdAt: Date;
3
+ updatedAt: Date;
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,4 @@
1
1
  export * from './duplicable-model.type';
2
+ export * from './has-timestamps.type';
2
3
  export * from './likeable.type';
3
4
  export * from './viewable.type';
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./duplicable-model.type"), exports);
18
+ __exportStar(require("./has-timestamps.type"), exports);
18
19
  __exportStar(require("./likeable.type"), exports);
19
20
  __exportStar(require("./viewable.type"), exports);
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "name": "Timo Scheuermann",
5
5
  "email": "timo.scheuermann@sv-informatik.de"
6
6
  },
7
- "version": "2.16.4",
7
+ "version": "2.16.6",
8
8
  "type": "commonjs",
9
9
  "files": [
10
10
  "dist"