itlab-internal-services 2.16.0 → 2.16.1

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 (74) hide show
  1. package/dist/classes/document-merger.class.js +2 -1
  2. package/dist/classes/index.d.ts +3 -1
  3. package/dist/classes/index.js +5 -3
  4. package/dist/classes/schema-builder.class.d.ts +75 -0
  5. package/dist/classes/schema-builder.class.js +109 -0
  6. package/dist/classes/task-manager.class.d.ts +71 -0
  7. package/dist/classes/task-manager.class.js +99 -0
  8. package/dist/exceptions/bad-parameter.exception.js +2 -1
  9. package/dist/index.d.ts +3 -3
  10. package/dist/index.js +3 -3
  11. package/dist/interceptors/attribute-sanitizer.interceptor.d.ts +68 -0
  12. package/dist/interceptors/attribute-sanitizer.interceptor.js +154 -0
  13. package/dist/interceptors/index.d.ts +1 -0
  14. package/dist/interceptors/index.js +17 -0
  15. package/dist/middleware/http-logging.middleware.d.ts +19 -0
  16. package/dist/middleware/http-logging.middleware.js +50 -0
  17. package/dist/middleware/index.d.ts +1 -0
  18. package/dist/middleware/index.js +17 -0
  19. package/dist/modules/authentication/guards/jwt-auth.guard.js +1 -7
  20. package/dist/modules/authentication/guards/permissions.guard.js +4 -3
  21. package/dist/modules/authentication/guards/service-auth.guard.js +1 -1
  22. package/dist/modules/comment/comment-module-options.interface.d.ts +2 -2
  23. package/dist/modules/comment/comment.controller.d.ts +5 -5
  24. package/dist/modules/comment/comment.controller.js +3 -3
  25. package/dist/modules/comment/comment.service.d.ts +3 -3
  26. package/dist/modules/comment/comment.service.js +1 -1
  27. package/dist/modules/like/like-module-options.interface.d.ts +2 -2
  28. package/dist/modules/like/like.controller.d.ts +2 -2
  29. package/dist/modules/like/like.controller.js +2 -2
  30. package/dist/modules/services/providers/accounts.service.js +2 -0
  31. package/dist/modules/services/providers/books.service.js +2 -0
  32. package/dist/modules/services/providers/changelog.service.js +2 -0
  33. package/dist/modules/services/providers/comments/comments.service.d.ts +3 -3
  34. package/dist/modules/services/providers/comments/comments.service.js +2 -1
  35. package/dist/modules/services/providers/content/{content-types.d.ts → content-return-types.d.ts} +3 -4
  36. package/dist/modules/services/providers/content/{content-types.js → content-return-types.js} +2 -2
  37. package/dist/modules/services/providers/content/content.service.d.ts +7 -5
  38. package/dist/modules/services/providers/content/content.service.js +29 -12
  39. package/dist/modules/services/providers/content/index.d.ts +1 -0
  40. package/dist/modules/services/providers/demo-hive.service.js +2 -0
  41. package/dist/modules/services/providers/events.service.js +2 -0
  42. package/dist/modules/services/providers/hackschool.service.js +2 -0
  43. package/dist/modules/services/providers/ideas.service.js +2 -0
  44. package/dist/modules/services/providers/lunch-roulette.service.js +2 -0
  45. package/dist/modules/services/providers/mail/mail.service.js +1 -1
  46. package/dist/modules/services/providers/newletter.service.js +2 -0
  47. package/dist/modules/services/providers/newsroom.service.js +2 -0
  48. package/dist/modules/services/providers/podcasts.service.js +2 -0
  49. package/dist/modules/services/providers/search/search.service.js +1 -1
  50. package/dist/modules/services/providers/team.service.js +2 -0
  51. package/dist/modules/services/providers/tech-radar.service.js +2 -0
  52. package/dist/properties/content-return-type.property.d.ts +7 -0
  53. package/dist/properties/content-return-type.property.js +22 -0
  54. package/dist/properties/index.d.ts +3 -0
  55. package/dist/properties/index.js +7 -1
  56. package/dist/properties/likeable.properties.d.ts +1 -0
  57. package/dist/properties/likeable.properties.js +66 -0
  58. package/dist/properties/viewable.properties.d.ts +1 -0
  59. package/dist/properties/viewable.properties.js +66 -0
  60. package/dist/types/index.d.ts +2 -0
  61. package/dist/types/index.js +18 -0
  62. package/dist/types/likeable.type.d.ts +15 -0
  63. package/dist/types/likeable.type.js +2 -0
  64. package/dist/types/viewable.type.d.ts +15 -0
  65. package/dist/types/viewable.type.js +2 -0
  66. package/package.json +2 -2
  67. package/dist/classes/document-updater.class.d.ts +0 -39
  68. package/dist/classes/document-updater.class.js +0 -57
  69. package/dist/http-logger.middleware.d.ts +0 -12
  70. package/dist/http-logger.middleware.js +0 -43
  71. package/dist/likeable.interface.d.ts +0 -41
  72. package/dist/likeable.interface.js +0 -48
  73. package/dist/viewable.interface.d.ts +0 -41
  74. package/dist/viewable.interface.js +0 -48
@@ -0,0 +1 @@
1
+ export * from './attribute-sanitizer.interceptor';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./attribute-sanitizer.interceptor"), exports);
@@ -0,0 +1,19 @@
1
+ import { NestMiddleware } from '@nestjs/common';
2
+ /**
3
+ * HttpLoggingMiddleware
4
+ *
5
+ * This middleware logs incoming HTTP requests and their corresponding responses
6
+ * for improved observability. It is primarily intended for non-internal routes,
7
+ * so it avoids noisy or repetitive logging of system, health check, API, or
8
+ * Swagger documentation endpoints.
9
+ *
10
+ * Logging includes:
11
+ * - HTTP method
12
+ * - Original request URL
13
+ * - Response status code and status message
14
+ *
15
+ * Errors in the 4xx range are logged at the "warn" level, while all other logs
16
+ * use the standard "log" level. This helps distinguish between client errors
17
+ * and normal traffic or server issues.
18
+ */
19
+ export declare const HttpLoggingMiddleware: NestMiddleware['use'];
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpLoggingMiddleware = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const logger = new common_1.Logger('HTTP');
6
+ const excludedPaths = ['/alive', '/favicon.ico'];
7
+ /**
8
+ * HttpLoggingMiddleware
9
+ *
10
+ * This middleware logs incoming HTTP requests and their corresponding responses
11
+ * for improved observability. It is primarily intended for non-internal routes,
12
+ * so it avoids noisy or repetitive logging of system, health check, API, or
13
+ * Swagger documentation endpoints.
14
+ *
15
+ * Logging includes:
16
+ * - HTTP method
17
+ * - Original request URL
18
+ * - Response status code and status message
19
+ *
20
+ * Errors in the 4xx range are logged at the "warn" level, while all other logs
21
+ * use the standard "log" level. This helps distinguish between client errors
22
+ * and normal traffic or server issues.
23
+ */
24
+ const HttpLoggingMiddleware = (req, res, next) => {
25
+ const { method, url } = req;
26
+ // Define a small set of non-critical paths to exclude from logs
27
+ // Determine whether this request should be ignored for logging
28
+ const isSwagger = url.includes('swagger');
29
+ const isApiInternal = url.startsWith('/api');
30
+ const isExcluded = excludedPaths.includes(url);
31
+ if (isSwagger || isApiInternal || isExcluded) {
32
+ // Skip logging altogether for ignored paths to reduce clutter
33
+ next();
34
+ return;
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
+ });
47
+ // Continue to next middleware or request handler
48
+ next();
49
+ };
50
+ exports.HttpLoggingMiddleware = HttpLoggingMiddleware;
@@ -0,0 +1 @@
1
+ export * from './http-logging.middleware';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./http-logging.middleware"), exports);
@@ -20,7 +20,6 @@ const jwt_1 = require("@nestjs/jwt");
20
20
  const swagger_1 = require("@nestjs/swagger");
21
21
  const authentication_options_parameter_1 = require("../authentication-options.parameter");
22
22
  const public_guard_1 = require("./public.guard");
23
- const service_auth_guard_1 = require("./service-auth.guard");
24
23
  /**
25
24
  * Guard implementing JWT authentication for routes.
26
25
  * Skips authentication for public routes and service requests.
@@ -64,10 +63,5 @@ function extractBearerToken(request) {
64
63
  }
65
64
  /** Decorator enforcing JWT authentication on routes/controllers */
66
65
  function RequireJwtAuth() {
67
- return (0, common_1.applyDecorators)((0, common_1.UseGuards)(JwtAuthGuard), (0, swagger_1.ApiSecurity)('Service Token'), (0, swagger_1.ApiHeader)({
68
- allowEmptyValue: true,
69
- name: service_auth_guard_1.SERVICE_AUTH_HEADER_KEY,
70
- description: 'Token for service authentication',
71
- required: false,
72
- }), (0, swagger_1.ApiBearerAuth)('Auth Token'), (0, swagger_1.ApiUnauthorizedResponse)({ description: 'Unauthorized: Invalid or missing JWT' }));
66
+ return (0, common_1.applyDecorators)((0, common_1.UseGuards)(JwtAuthGuard), (0, swagger_1.ApiBearerAuth)('Auth Token'), (0, swagger_1.ApiUnauthorizedResponse)({ description: 'Unauthorized: Invalid or missing JWT' }));
73
67
  }
@@ -38,7 +38,7 @@ let PermissionsGuard = class PermissionsGuard {
38
38
  const requiredPermissions = this.reflector.get(PERMISSIONS_METADATA_KEY, context.getHandler());
39
39
  if (hasRequiredPermissions(context, requiredPermissions))
40
40
  return true;
41
- throw new common_1.ForbiddenException(`Insufficient permissions: ${requiredPermissions.join(',')}`);
41
+ throw new common_1.ForbiddenException(`Insufficient permissions: ${(0, itlab_functions_1.formatList)(requiredPermissions, 'or')}`);
42
42
  }
43
43
  };
44
44
  exports.PermissionsGuard = PermissionsGuard;
@@ -49,12 +49,13 @@ exports.PermissionsGuard = PermissionsGuard = __decorate([
49
49
  ], PermissionsGuard);
50
50
  /** Check if account has required permissions */
51
51
  function hasRequiredPermissions(context, requiredPermissions) {
52
- if (requiredPermissions || requiredPermissions.length === 0)
52
+ // If no permissions are specified, allow unrestricted access.
53
+ if (!requiredPermissions || requiredPermissions.length === 0)
53
54
  return true;
54
55
  const { account } = context.switchToHttp().getRequest();
55
56
  return (0, class_validator_1.arrayMinSize)(account === null || account === void 0 ? void 0 : account.perms, 1) && (0, itlab_functions_1.hasSomePermission)(requiredPermissions, account.perms);
56
57
  }
57
58
  /** Decorator enforcing permissions on routes/controllers */
58
59
  function RequirePermissions(...permissions) {
59
- return (0, common_1.applyDecorators)((0, common_1.SetMetadata)(PERMISSIONS_METADATA_KEY, permissions), (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, PermissionsGuard), (0, swagger_1.ApiBearerAuth)('Auth Token'), (0, swagger_1.ApiForbiddenResponse)({ description: `Insufficient permissions: ${permissions.join(', ')}` }));
60
+ return (0, common_1.applyDecorators)((0, common_1.SetMetadata)(PERMISSIONS_METADATA_KEY, permissions), (0, common_1.UseGuards)(jwt_auth_guard_1.JwtAuthGuard, PermissionsGuard), (0, swagger_1.ApiBearerAuth)('Auth Token'), (0, swagger_1.ApiForbiddenResponse)({ description: `Insufficient permissions: ${(0, itlab_functions_1.formatList)(permissions, 'or')}` }));
60
61
  }
@@ -56,7 +56,7 @@ function isServiceRequest(context, requiredk8sToken) {
56
56
  * Decorator for routes/controllers accessible only by internal services.
57
57
  */
58
58
  function RequireServiceAuth() {
59
- return (0, common_1.applyDecorators)((0, common_1.UseGuards)(ServiceAuthGuard), (0, swagger_1.ApiTags)('Internal'), (0, swagger_1.ApiSecurity)('Service Token'), (0, swagger_1.ApiHeader)({
59
+ return (0, common_1.applyDecorators)((0, common_1.UseGuards)(ServiceAuthGuard), (0, swagger_1.ApiSecurity)('Service Token'), (0, swagger_1.ApiHeader)({
60
60
  name: exports.SERVICE_AUTH_HEADER_KEY,
61
61
  description: 'Token for service authentication',
62
62
  allowEmptyValue: true,
@@ -21,10 +21,10 @@ export type CommentModuleOptions<T extends Document> = {
21
21
  */
22
22
  model: ModelDefinition;
23
23
  /**
24
- * Optional suffix used to customize the controller route.
24
+ * Suffix used to customize the controller route.
25
25
  * For example, setting this to "news" will expose routes comment `/comment/news/:id`.
26
26
  */
27
- routeSuffix?: string;
27
+ routeSuffix: string;
28
28
  /**
29
29
  * Field name on the resource document representing a single owner's ID.
30
30
  * Enables access control and filtering of comments by ownership.
@@ -1,4 +1,4 @@
1
- import { LabCommentPopulated, LabContentRichtext } from 'itlab-functions';
1
+ import { LabComment, LabContentRichtext } from 'itlab-functions';
2
2
  import { CommentService } from './comment.service';
3
3
  /**
4
4
  * Factory function for creating a CommentController bound to a specific route suffix.
@@ -7,10 +7,10 @@ import { CommentService } from './comment.service';
7
7
  * we generate one dynamically. This ensures DRY principles while still
8
8
  * supporting custom routes (e.g. `/comment/news` or `/comment/event`).
9
9
  *
10
- * @param {string} [routeSuffix] - Optional suffix appended to the "comment" route.
10
+ * @param {string} routeSuffix - Suffix appended to the "comment" route.
11
11
  * @returns A dynamically generated controller class.
12
12
  */
13
- export declare function createCommentController(routeSuffix?: string): {
13
+ export declare function createCommentController(routeSuffix: string): {
14
14
  new (commentService: CommentService): {
15
15
  readonly commentService: CommentService;
16
16
  /**
@@ -22,8 +22,8 @@ export declare function createCommentController(routeSuffix?: string): {
22
22
  * @param {string} resourceId - MongoDB ObjectId of the resource being commented on.
23
23
  * @param {string} accountId - Authenticated user's account ID.
24
24
  * @param {LabContentRichtext} comment - Rich text content of the comment.
25
- * @returns {Promise<LabCommentPopulated>} The saved comment object.
25
+ * @returns {Promise<LabComment>} The saved comment object.
26
26
  */
27
- postComment(resourceId: string, accountId: string, comment: LabContentRichtext): Promise<LabCommentPopulated>;
27
+ postComment(resourceId: string, accountId: string, comment: LabContentRichtext): Promise<LabComment>;
28
28
  };
29
29
  };
@@ -27,12 +27,12 @@ const comment_service_1 = require("./comment.service");
27
27
  * we generate one dynamically. This ensures DRY principles while still
28
28
  * supporting custom routes (e.g. `/comment/news` or `/comment/event`).
29
29
  *
30
- * @param {string} [routeSuffix] - Optional suffix appended to the "comment" route.
30
+ * @param {string} routeSuffix - Suffix appended to the "comment" route.
31
31
  * @returns A dynamically generated controller class.
32
32
  */
33
33
  function createCommentController(routeSuffix) {
34
34
  // Normalize route path, removing duplicate/trailing slashes
35
- const normalizedRoute = `comment/${routeSuffix || ''}`.replace(/\/{2,}/g, '/').replace(/\/$/, '');
35
+ const normalizedRoute = `comment/${routeSuffix}`.replace(/\/{2,}/g, '/').replace(/\/$/, '');
36
36
  let CommentController = class CommentController {
37
37
  constructor(commentService) {
38
38
  this.commentService = commentService;
@@ -46,7 +46,7 @@ function createCommentController(routeSuffix) {
46
46
  * @param {string} resourceId - MongoDB ObjectId of the resource being commented on.
47
47
  * @param {string} accountId - Authenticated user's account ID.
48
48
  * @param {LabContentRichtext} comment - Rich text content of the comment.
49
- * @returns {Promise<LabCommentPopulated>} The saved comment object.
49
+ * @returns {Promise<LabComment>} The saved comment object.
50
50
  */
51
51
  async postComment(resourceId, accountId, comment) {
52
52
  return this.commentService.postComment(resourceId, accountId, comment);
@@ -1,5 +1,5 @@
1
1
  import { ConfigService } from '@nestjs/config';
2
- import { LabCommentPopulated, LabContentRichtext } from 'itlab-functions';
2
+ import { LabComment, LabContentRichtext } from 'itlab-functions';
3
3
  import { Connection } from 'mongoose';
4
4
  import { AuthenticationModuleOptions } from '../authentication';
5
5
  import { BaseHttpService } from '../services/base-http.service';
@@ -36,9 +36,9 @@ export declare class CommentService extends BaseHttpService {
36
36
  * @param {string} resourceId - MongoDB ObjectId of the resource being commented on.
37
37
  * @param {string} accountId - Authenticated user ID posting the comment.
38
38
  * @param {LabContentRichtext} richtext - Comment content in rich-text format.
39
- * @returns {Promise<LabCommentPopulated>} Resolves with the saved comment or throws an HTTP exception.
39
+ * @returns {Promise<LabComment>} Resolves with the saved comment or throws an HTTP exception.
40
40
  * @throws {NotFoundException} If the resource does not exist.
41
41
  * @throws {HttpException} If the internal service call fails.
42
42
  */
43
- postComment(resourceId: string, accountId: string, richtext: LabContentRichtext): Promise<LabCommentPopulated>;
43
+ postComment(resourceId: string, accountId: string, richtext: LabContentRichtext): Promise<LabComment>;
44
44
  }
@@ -58,7 +58,7 @@ let CommentService = class CommentService extends base_http_service_1.BaseHttpSe
58
58
  * @param {string} resourceId - MongoDB ObjectId of the resource being commented on.
59
59
  * @param {string} accountId - Authenticated user ID posting the comment.
60
60
  * @param {LabContentRichtext} richtext - Comment content in rich-text format.
61
- * @returns {Promise<LabCommentPopulated>} Resolves with the saved comment or throws an HTTP exception.
61
+ * @returns {Promise<LabComment>} Resolves with the saved comment or throws an HTTP exception.
62
62
  * @throws {NotFoundException} If the resource does not exist.
63
63
  * @throws {HttpException} If the internal service call fails.
64
64
  */
@@ -14,8 +14,8 @@ export type LikeModuleOptions = {
14
14
  */
15
15
  model: ModelDefinition;
16
16
  /**
17
- * Optional suffix used to customize the controller route.
17
+ * Suffix used to customize the controller route.
18
18
  * For example, setting this to "news" will expose routes like `/like/news/:id`.
19
19
  */
20
- routeSuffix?: string;
20
+ routeSuffix: string;
21
21
  };
@@ -6,10 +6,10 @@ import { LikeService } from './like.service';
6
6
  * we generate one dynamically. This ensures DRY principles while still
7
7
  * supporting custom routes (e.g. `/like/news` or `/like/event`).
8
8
  *
9
- * @param {string} [routeSuffix] - Optional suffix appended to the "like" route.
9
+ * @param {string} [routeSuffix] - Suffix appended to the "like" route.
10
10
  * @returns A dynamically generated controller class.
11
11
  */
12
- export declare function createLikeController(routeSuffix?: string): {
12
+ export declare function createLikeController(routeSuffix: string): {
13
13
  new (likeService: LikeService): {
14
14
  readonly likeService: LikeService;
15
15
  /**
@@ -26,12 +26,12 @@ const like_service_1 = require("./like.service");
26
26
  * we generate one dynamically. This ensures DRY principles while still
27
27
  * supporting custom routes (e.g. `/like/news` or `/like/event`).
28
28
  *
29
- * @param {string} [routeSuffix] - Optional suffix appended to the "like" route.
29
+ * @param {string} [routeSuffix] - Suffix appended to the "like" route.
30
30
  * @returns A dynamically generated controller class.
31
31
  */
32
32
  function createLikeController(routeSuffix) {
33
33
  // Normalize route path, removing duplicate/trailing slashes
34
- const normalizedRoute = `like/${routeSuffix || ''}`.replace(/\/{2,}/g, '/').replace(/\/$/, '');
34
+ const normalizedRoute = `like/${routeSuffix}`.replace(/\/{2,}/g, '/').replace(/\/$/, '');
35
35
  let LikeController = class LikeController {
36
36
  constructor(likeService) {
37
37
  this.likeService = likeService;
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.AccountsService = void 0;
16
+ const common_1 = require("@nestjs/common");
16
17
  const config_1 = require("@nestjs/config");
17
18
  const authentication_1 = require("../../authentication");
18
19
  const base_http_service_1 = require("../base-http.service");
@@ -77,6 +78,7 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
77
78
  };
78
79
  exports.AccountsService = AccountsService;
79
80
  exports.AccountsService = AccountsService = __decorate([
81
+ (0, common_1.Injectable)(),
80
82
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
81
83
  __metadata("design:paramtypes", [Object, config_1.ConfigService])
82
84
  ], AccountsService);
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BooksService = void 0;
16
+ const common_1 = require("@nestjs/common");
16
17
  const config_1 = require("@nestjs/config");
17
18
  const authentication_1 = require("../../authentication");
18
19
  const base_http_service_1 = require("../base-http.service");
@@ -48,6 +49,7 @@ let BooksService = class BooksService extends base_http_service_1.BaseHttpServic
48
49
  };
49
50
  exports.BooksService = BooksService;
50
51
  exports.BooksService = BooksService = __decorate([
52
+ (0, common_1.Injectable)(),
51
53
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
52
54
  __metadata("design:paramtypes", [Object, config_1.ConfigService])
53
55
  ], BooksService);
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.ChangelogService = void 0;
16
+ const common_1 = require("@nestjs/common");
16
17
  const config_1 = require("@nestjs/config");
17
18
  const authentication_1 = require("../../authentication");
18
19
  const base_http_service_1 = require("../base-http.service");
@@ -36,6 +37,7 @@ let ChangelogService = class ChangelogService extends base_http_service_1.BaseHt
36
37
  };
37
38
  exports.ChangelogService = ChangelogService;
38
39
  exports.ChangelogService = ChangelogService = __decorate([
40
+ (0, common_1.Injectable)(),
39
41
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
40
42
  __metadata("design:paramtypes", [Object, config_1.ConfigService])
41
43
  ], ChangelogService);
@@ -1,6 +1,6 @@
1
1
  import { DynamicModule } from '@nestjs/common';
2
2
  import { ConfigService } from '@nestjs/config';
3
- import { LabCommentPopulated } from 'itlab-functions';
3
+ import { LabComment } from 'itlab-functions';
4
4
  import { HubResource } from '../../../../hub-resource.enum';
5
5
  import { AuthenticationModuleOptions } from '../../../authentication';
6
6
  import { CacheService } from '../../../cache';
@@ -49,12 +49,12 @@ export declare class CommentsService extends BaseHttpService {
49
49
  * @param resourceId Unique identifier of the resource.
50
50
  * @returns Retrieved comments.
51
51
  */
52
- getPopulatedComments(resourceId: string): Promise<LabCommentPopulated[]>;
52
+ getPopulatedComments(resourceId: string): Promise<LabComment[]>;
53
53
  /**
54
54
  * Retrieves comments from the cache if available; otherwise fetches from the backend.
55
55
  *
56
56
  * @param resourceId Unique identifier of the resource.
57
57
  * @returns Cached or freshly retrieved comments.
58
58
  */
59
- getCachedPopulatedComments(resourceId: string): Promise<LabCommentPopulated[]>;
59
+ getCachedPopulatedComments(resourceId: string): Promise<LabComment[]>;
60
60
  }
@@ -123,13 +123,14 @@ let CommentsService = CommentsService_1 = class CommentsService extends base_htt
123
123
  const fetchPopulatedComments = () => this.getPopulatedComments(resourceId);
124
124
  if (this.cacheService) {
125
125
  const cacheKey = `${this.options.resource}.${resourceId}.populatedComments`;
126
- return this.cacheService.fetchOrStore(cacheKey, fetchPopulatedComments, 30000);
126
+ return this.cacheService.fetchOrStore(cacheKey, fetchPopulatedComments, 60000); // 1 Minute
127
127
  }
128
128
  return fetchPopulatedComments();
129
129
  }
130
130
  };
131
131
  exports.CommentsService = CommentsService;
132
132
  exports.CommentsService = CommentsService = CommentsService_1 = __decorate([
133
+ (0, common_1.Injectable)(),
133
134
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
134
135
  __param(1, (0, services_options_parameter_1.InjectServicesOptions)()),
135
136
  __param(3, (0, common_1.Optional)()),
@@ -2,19 +2,18 @@ import { LabContent, LabContentPopulated } from 'itlab-functions';
2
2
  /**
3
3
  * Constant list of supported digital pass types.
4
4
  */
5
- declare const supportedContentTypes: readonly ["json", "text", "html", "populated"];
5
+ export declare const supportedContentReturnTypes: readonly ["json", "text", "html", "populated"];
6
6
  /**
7
7
  * Union type representing valid pass types.
8
8
  */
9
- export type ContentType = (typeof supportedContentTypes)[number];
9
+ export type ContentReturnType = (typeof supportedContentReturnTypes)[number];
10
10
  /**
11
11
  * Maps each supported pass type to its corresponding DTO.
12
12
  * This enables type-safe payload handling when creating passes.
13
13
  */
14
- export type ContentTypeReturnTypeMap = {
14
+ export type ContentReturnTypeMap = {
15
15
  json: LabContent;
16
16
  text: string;
17
17
  html: LabContent;
18
18
  populated: LabContentPopulated;
19
19
  };
20
- export {};
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.supportedContentReturnTypes = void 0;
3
4
  /**
4
5
  * Constant list of supported digital pass types.
5
6
  */
6
- // eslint-disable-next-line
7
- const supportedContentTypes = ['json', 'text', 'html', 'populated'];
7
+ exports.supportedContentReturnTypes = ['json', 'text', 'html', 'populated'];
@@ -6,7 +6,7 @@ import { AuthenticationModuleOptions } from '../../../authentication';
6
6
  import { CacheService } from '../../../cache';
7
7
  import { BaseHttpService } from '../../base-http.service';
8
8
  import { ServicesModuleOptions } from '../../services-module-options.interface';
9
- import { ContentType, ContentTypeReturnTypeMap } from './content-types';
9
+ import { ContentReturnType, ContentReturnTypeMap } from './content-return-types';
10
10
  /**
11
11
  * Parameter decorator to inject the feature-specific ContentService.
12
12
  */
@@ -41,6 +41,8 @@ export declare class ContentService extends BaseHttpService {
41
41
  * @returns A DynamicModule with a provider for the specified ContentService instance.
42
42
  */
43
43
  static forResource(resource: HubResource): DynamicModule;
44
+ private cacheKey;
45
+ private clearCache;
44
46
  /**
45
47
  * Validates the given content object using the backend service.
46
48
  * Logs the process and throws an HTTP exception if validation fails.
@@ -79,16 +81,16 @@ export declare class ContentService extends BaseHttpService {
79
81
  * Provides default values if content retrieval fails.
80
82
  *
81
83
  * @param resourceId Unique identifier of the resource.
82
- * @param type Format of content to retrieve ('json', 'text', 'html', 'populated').
84
+ * @param returnType Format of content to retrieve ('json', 'text', 'html', 'populated').
83
85
  * @returns Retrieved content in the requested format.
84
86
  */
85
- getContent<Type extends ContentType>(resourceId: string, type: Type): Promise<ContentTypeReturnTypeMap[Type]>;
87
+ getContent<ReturnType extends ContentReturnType>(resourceId: string, returnType: ReturnType): Promise<ContentReturnTypeMap[ReturnType]>;
86
88
  /**
87
89
  * Retrieves content from the cache if available; otherwise fetches from the backend.
88
90
  *
89
91
  * @param resourceId Unique identifier of the resource.
90
- * @param type Format of content to retrieve.
92
+ * @param returnType Format of content to retrieve.
91
93
  * @returns Cached or freshly retrieved content.
92
94
  */
93
- getCachedContent<Type extends ContentType>(resourceId: string, type: Type): Promise<ContentTypeReturnTypeMap[Type]>;
95
+ getCachedContent<ReturnType extends ContentReturnType>(resourceId: string, returnType: ReturnType): Promise<ContentReturnTypeMap[ReturnType]>;
94
96
  }
@@ -23,6 +23,7 @@ const cache_1 = require("../../../cache");
23
23
  const base_http_service_1 = require("../../base-http.service");
24
24
  const base_urls_1 = require("../../base-urls");
25
25
  const services_options_parameter_1 = require("../../services-options.parameter");
26
+ const content_return_types_1 = require("./content-return-types");
26
27
  const content_service_definition_1 = require("./content.service-definition");
27
28
  /**
28
29
  * Parameter decorator to inject the feature-specific ContentService.
@@ -54,6 +55,9 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
54
55
  super('Content', base_urls_1.BaseUrls.ContentService, authenticationOptions, configService);
55
56
  this.options = options;
56
57
  this.cacheService = cacheService;
58
+ this.cacheKey = (resourceId, returnType) => {
59
+ return `${this.options.resource}.${resourceId}.${returnType}Content`;
60
+ };
57
61
  }
58
62
  /**
59
63
  * Factory method to create a dynamic module for a specific Hub resource.
@@ -81,6 +85,17 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
81
85
  ],
82
86
  };
83
87
  }
88
+ clearCache(resourceId) {
89
+ if (this.cacheService) {
90
+ const promises = content_return_types_1.supportedContentReturnTypes.map((returnType) => {
91
+ const cacheKey = this.cacheKey(resourceId, returnType);
92
+ return this.cacheService.remove(cacheKey);
93
+ });
94
+ Promise.all(promises).then(() => {
95
+ this.logger.log(`Content cache for ${this.options.resource} ${resourceId} cleared.`);
96
+ });
97
+ }
98
+ }
84
99
  /**
85
100
  * Validates the given content object using the backend service.
86
101
  * Logs the process and throws an HTTP exception if validation fails.
@@ -119,6 +134,7 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
119
134
  try {
120
135
  await this.client.post(endpoint, { content });
121
136
  this.logger.log(`Content successfully submitted for ${this.options.resource} ${resourceId}.`);
137
+ this.clearCache(resourceId);
122
138
  }
123
139
  catch (error) {
124
140
  const { status, data, message } = this.parseError(error);
@@ -154,6 +170,7 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
154
170
  .delete(endpoint)
155
171
  .then(() => {
156
172
  this.logger.log(`Content removed successfully for ${this.options.resource} (${resourceId}).`);
173
+ this.clearCache(resourceId);
157
174
  })
158
175
  .catch((error) => {
159
176
  const { message } = this.parseError(error);
@@ -165,25 +182,25 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
165
182
  * Provides default values if content retrieval fails.
166
183
  *
167
184
  * @param resourceId Unique identifier of the resource.
168
- * @param type Format of content to retrieve ('json', 'text', 'html', 'populated').
185
+ * @param returnType Format of content to retrieve ('json', 'text', 'html', 'populated').
169
186
  * @returns Retrieved content in the requested format.
170
187
  */
171
- async getContent(resourceId, type) {
172
- const defaultReturnValue = (type === 'text' ? '' : []);
188
+ async getContent(resourceId, returnType) {
189
+ const defaultReturnValue = (returnType === 'text' ? '' : []);
173
190
  if (!this.options.resource) {
174
191
  this.logger.error('Cannot fetch content: Resource type not provided.');
175
192
  return defaultReturnValue;
176
193
  }
177
- const endpoint = `internal/${this.options.resource}/${resourceId}/${type}`;
178
- this.logger.log(`Fetching ${type} content for ${this.options.resource} ${resourceId}...`);
194
+ const endpoint = `internal/${this.options.resource}/${resourceId}/${returnType}`;
195
+ this.logger.log(`Fetching ${returnType} content for ${this.options.resource} ${resourceId}...`);
179
196
  try {
180
197
  const { data } = await this.client.get(endpoint);
181
- this.logger.log(`Successfully retrieved ${type} content for ${this.options.resource} ${resourceId}.`);
198
+ this.logger.log(`Successfully retrieved ${returnType} content for ${this.options.resource} ${resourceId}.`);
182
199
  return data;
183
200
  }
184
201
  catch (error) {
185
202
  const { message } = this.parseError(error);
186
- this.logger.error(`Failed to fetch ${type} content for ${this.options.resource} ${resourceId}: ${message}`);
203
+ this.logger.error(`Failed to fetch ${returnType} content for ${this.options.resource} ${resourceId}: ${message}`);
187
204
  return defaultReturnValue;
188
205
  }
189
206
  }
@@ -191,14 +208,14 @@ let ContentService = ContentService_1 = class ContentService extends base_http_s
191
208
  * Retrieves content from the cache if available; otherwise fetches from the backend.
192
209
  *
193
210
  * @param resourceId Unique identifier of the resource.
194
- * @param type Format of content to retrieve.
211
+ * @param returnType Format of content to retrieve.
195
212
  * @returns Cached or freshly retrieved content.
196
213
  */
197
- async getCachedContent(resourceId, type) {
198
- const fetchContent = () => this.getContent(resourceId, type);
214
+ async getCachedContent(resourceId, returnType) {
215
+ const fetchContent = () => this.getContent(resourceId, returnType);
199
216
  if (this.cacheService) {
200
- const cacheKey = `${this.options.resource}.${resourceId}.${type}Content`;
201
- return this.cacheService.fetchOrStore(cacheKey, fetchContent, 60000);
217
+ const cacheKey = this.cacheKey(resourceId, returnType);
218
+ return this.cacheService.fetchOrStore(cacheKey, fetchContent, 86400000); // 1 day or until updated
202
219
  }
203
220
  return fetchContent();
204
221
  }
@@ -1 +1,2 @@
1
+ export type { ContentReturnType } from './content-return-types';
1
2
  export * from './content.service';
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.DemoHiveService = void 0;
16
+ const common_1 = require("@nestjs/common");
16
17
  const config_1 = require("@nestjs/config");
17
18
  const authentication_1 = require("../../authentication");
18
19
  const base_http_service_1 = require("../base-http.service");
@@ -48,6 +49,7 @@ let DemoHiveService = class DemoHiveService extends base_http_service_1.BaseHttp
48
49
  };
49
50
  exports.DemoHiveService = DemoHiveService;
50
51
  exports.DemoHiveService = DemoHiveService = __decorate([
52
+ (0, common_1.Injectable)(),
51
53
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
52
54
  __metadata("design:paramtypes", [Object, config_1.ConfigService])
53
55
  ], DemoHiveService);
@@ -13,6 +13,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.EventsService = void 0;
16
+ const common_1 = require("@nestjs/common");
16
17
  const config_1 = require("@nestjs/config");
17
18
  const authentication_1 = require("../../authentication");
18
19
  const base_http_service_1 = require("../base-http.service");
@@ -48,6 +49,7 @@ let EventsService = class EventsService extends base_http_service_1.BaseHttpServ
48
49
  };
49
50
  exports.EventsService = EventsService;
50
51
  exports.EventsService = EventsService = __decorate([
52
+ (0, common_1.Injectable)(),
51
53
  __param(0, (0, authentication_1.InjectAuthenticationOptions)()),
52
54
  __metadata("design:paramtypes", [Object, config_1.ConfigService])
53
55
  ], EventsService);