itlab-internal-services 2.16.1 → 2.16.3

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 (201) hide show
  1. package/dist/classes/document/commentable-document.class.d.ts +200 -0
  2. package/dist/classes/document/commentable-document.class.js +24 -0
  3. package/dist/classes/document/content-document.class.d.ts +200 -0
  4. package/dist/classes/document/content-document.class.js +24 -0
  5. package/dist/classes/document/index.d.ts +4 -0
  6. package/dist/classes/document/index.js +11 -0
  7. package/dist/classes/document/likeable-document.class.d.ts +205 -0
  8. package/dist/classes/document/likeable-document.class.js +70 -0
  9. package/dist/classes/document/viewable-document.class.d.ts +205 -0
  10. package/dist/classes/document/viewable-document.class.js +67 -0
  11. package/dist/classes/document-updater.class.d.ts +40 -0
  12. package/dist/classes/document-updater.class.js +58 -0
  13. package/dist/classes/fetch-options/base-options.class.d.ts +18 -0
  14. package/dist/classes/fetch-options/base-options.class.js +81 -0
  15. package/dist/classes/fetch-options/comments-options.class.d.ts +6 -0
  16. package/dist/classes/fetch-options/comments-options.class.js +26 -0
  17. package/dist/classes/fetch-options/content-options.class.d.ts +7 -0
  18. package/dist/classes/fetch-options/content-options.class.js +32 -0
  19. package/dist/classes/fetch-options/drafted-options.class.d.ts +9 -0
  20. package/dist/classes/fetch-options/drafted-options.class.js +34 -0
  21. package/dist/classes/fetch-options/index.d.ts +6 -0
  22. package/dist/classes/fetch-options/index.js +15 -0
  23. package/dist/classes/fetch-options/liked-by-options.class.d.ts +8 -0
  24. package/dist/classes/fetch-options/liked-by-options.class.js +28 -0
  25. package/dist/classes/fetch-options/viewed-by-options.class.d.ts +9 -0
  26. package/dist/classes/fetch-options/viewed-by-options.class.js +28 -0
  27. package/dist/classes/index.d.ts +2 -2
  28. package/dist/classes/index.js +17 -3
  29. package/dist/classes/task-manager.class.d.ts +2 -2
  30. package/dist/classes/task-manager.class.js +4 -0
  31. package/dist/decorators/has-permission.decorator.d.ts +3 -0
  32. package/dist/decorators/has-permission.decorator.js +26 -0
  33. package/dist/decorators/index.d.ts +2 -0
  34. package/dist/decorators/index.js +2 -0
  35. package/dist/decorators/jwt.decorator.d.ts +1 -1
  36. package/dist/decorators/jwt.decorator.js +13 -11
  37. package/dist/decorators/schema-with-critical-keys.decorator.d.ts +12 -0
  38. package/dist/decorators/schema-with-critical-keys.decorator.js +16 -0
  39. package/dist/factories/index.d.ts +1 -0
  40. package/dist/factories/index.js +5 -0
  41. package/dist/factories/virtuals.factory.d.ts +80 -0
  42. package/dist/factories/virtuals.factory.js +172 -0
  43. package/dist/functions/create-schema.function.d.ts +3 -0
  44. package/dist/functions/create-schema.function.js +33 -0
  45. package/dist/functions/index.d.ts +1 -1
  46. package/dist/functions/index.js +3 -3
  47. package/dist/index.d.ts +6 -0
  48. package/dist/index.js +10 -0
  49. package/dist/likeable.interface.d.ts +42 -0
  50. package/dist/likeable.interface.js +48 -0
  51. package/dist/modules/_old/comment/comment.controller.d.ts +35 -0
  52. package/dist/modules/_old/comment/comment.controller.js +86 -0
  53. package/dist/modules/_old/comment/comment.model.d.ts +29 -0
  54. package/dist/modules/_old/comment/comment.model.js +43 -0
  55. package/dist/modules/_old/comment/comment.module-definition.d.ts +45 -0
  56. package/dist/modules/{comment → _old/comment}/comment.module-definition.js +2 -1
  57. package/dist/modules/_old/comment/comment.module.d.ts +22 -0
  58. package/dist/modules/_old/comment/comment.module.js +71 -0
  59. package/dist/modules/_old/comment/comment.service.d.ts +54 -0
  60. package/dist/modules/_old/comment/comment.service.js +133 -0
  61. package/dist/modules/_old/comment/index.d.ts +3 -0
  62. package/dist/modules/_old/comment/index.js +9 -0
  63. package/dist/modules/_old/content/content.module-definition.d.ts +5 -0
  64. package/dist/modules/_old/content/content.module-definition.js +8 -0
  65. package/dist/modules/_old/content/content.module.d.ts +31 -0
  66. package/dist/modules/_old/content/content.module.js +60 -0
  67. package/dist/modules/_old/content/content.service.d.ts +50 -0
  68. package/dist/modules/_old/content/content.service.js +145 -0
  69. package/dist/modules/_old/content/index.d.ts +2 -0
  70. package/dist/modules/_old/content/index.js +7 -0
  71. package/dist/modules/_old/database/database-module-options.interface.d.ts +41 -0
  72. package/dist/modules/_old/database/database.liveness-controller.d.ts +27 -0
  73. package/dist/modules/_old/database/database.liveness-controller.js +80 -0
  74. package/dist/modules/_old/database/database.module.d.ts +41 -0
  75. package/dist/modules/_old/database/database.module.js +97 -0
  76. package/dist/modules/_old/database/index.d.ts +6 -0
  77. package/dist/modules/_old/database/index.js +13 -0
  78. package/dist/modules/_old/database/lock-service/lock.schema.d.ts +38 -0
  79. package/dist/modules/_old/database/lock-service/lock.schema.js +51 -0
  80. package/dist/modules/_old/database/lock-service/lock.service.d.ts +53 -0
  81. package/dist/modules/_old/database/lock-service/lock.service.js +103 -0
  82. package/dist/modules/_old/database/model-service/dbs/hub-account.db.d.ts +28 -0
  83. package/dist/modules/_old/database/model-service/dbs/hub-account.db.js +44 -0
  84. package/dist/modules/_old/database/model-service/dbs/hub-books.db.d.ts +23 -0
  85. package/dist/modules/_old/database/model-service/dbs/hub-books.db.js +45 -0
  86. package/dist/modules/_old/database/model-service/dbs/hub-comments.db.d.ts +29 -0
  87. package/dist/modules/_old/database/model-service/dbs/hub-comments.db.js +68 -0
  88. package/dist/modules/_old/database/model-service/dbs/hub-content.db.d.ts +24 -0
  89. package/dist/modules/_old/database/model-service/dbs/hub-content.db.js +49 -0
  90. package/dist/modules/_old/database/model-service/dbs/hub-demo-hive.db.d.ts +23 -0
  91. package/dist/modules/_old/database/model-service/dbs/hub-demo-hive.db.js +45 -0
  92. package/dist/modules/_old/database/model-service/dbs/hub-events.db.d.ts +24 -0
  93. package/dist/modules/_old/database/model-service/dbs/hub-events.db.js +49 -0
  94. package/dist/modules/_old/database/model-service/dbs/hub-hackschool.db.d.ts +60 -0
  95. package/dist/modules/_old/database/model-service/dbs/hub-hackschool.db.js +106 -0
  96. package/dist/modules/_old/database/model-service/dbs/hub-newsroom.db.d.ts +25 -0
  97. package/dist/modules/_old/database/model-service/dbs/hub-newsroom.db.js +53 -0
  98. package/dist/modules/_old/database/model-service/dbs/hub-podcasts.db.d.ts +23 -0
  99. package/dist/modules/_old/database/model-service/dbs/hub-podcasts.db.js +45 -0
  100. package/dist/modules/_old/database/model-service/dbs/hub-team.db.d.ts +22 -0
  101. package/dist/modules/_old/database/model-service/dbs/hub-team.db.js +41 -0
  102. package/dist/modules/_old/database/model-service/dbs/hub-tech-radar.db.d.ts +42 -0
  103. package/dist/modules/_old/database/model-service/dbs/hub-tech-radar.db.js +81 -0
  104. package/dist/modules/_old/database/model-service/model.service.d.ts +8465 -0
  105. package/dist/modules/_old/database/model-service/model.service.js +136 -0
  106. package/dist/modules/_old/database/populate-service/populate.service.d.ts +73 -0
  107. package/dist/modules/_old/database/populate-service/populate.service.js +163 -0
  108. package/dist/modules/_old/database/service-mapper-service/service-mapper.service.d.ts +32 -0
  109. package/dist/modules/_old/database/service-mapper-service/service-mapper.service.js +73 -0
  110. package/dist/modules/_old/fetch/fetch.module.d.ts +31 -0
  111. package/dist/modules/_old/fetch/fetch.module.js +60 -0
  112. package/dist/modules/_old/fetch/fetch.service.d.ts +153 -0
  113. package/dist/modules/_old/fetch/fetch.service.js +274 -0
  114. package/dist/modules/_old/fetch/index.d.ts +2 -0
  115. package/dist/modules/_old/fetch/index.js +7 -0
  116. package/dist/modules/_old/index.d.ts +5 -0
  117. package/dist/modules/{comment → _old}/index.js +5 -2
  118. package/dist/modules/_old/like/index.d.ts +1 -0
  119. package/dist/modules/_old/like/index.js +5 -0
  120. package/dist/modules/_old/like/like.controller.d.ts +41 -0
  121. package/dist/modules/_old/like/like.controller.js +125 -0
  122. package/dist/modules/_old/like/like.module-definition.d.ts +20 -0
  123. package/dist/modules/_old/like/like.module-definition.js +8 -0
  124. package/dist/modules/_old/like/like.module.d.ts +21 -0
  125. package/dist/modules/_old/like/like.module.js +67 -0
  126. package/dist/modules/_old/like/like.service.d.ts +61 -0
  127. package/dist/modules/_old/like/like.service.js +103 -0
  128. package/dist/modules/authentication/guards/jwt-auth.guard.d.ts +1 -1
  129. package/dist/modules/authentication/guards/jwt-auth.guard.js +5 -3
  130. package/dist/modules/authentication/guards/permissions.guard.d.ts +1 -3
  131. package/dist/modules/authentication/guards/permissions.guard.js +2 -8
  132. package/dist/modules/authentication/guards/service-auth.guard.d.ts +0 -4
  133. package/dist/modules/authentication/guards/service-auth.guard.js +10 -13
  134. package/dist/modules/{comment/comment-module-options.interface.d.ts → comments/comments-module-options.interface.d.ts} +3 -2
  135. package/dist/modules/comments/comments-module-options.interface.js +2 -0
  136. package/dist/modules/{comment/comment.controller.d.ts → comments/comments.controller.d.ts} +7 -6
  137. package/dist/modules/{comment/comment.controller.js → comments/comments.controller.js} +14 -14
  138. package/dist/modules/comments/comments.module-definition.d.ts +4 -0
  139. package/dist/modules/comments/comments.module-definition.js +7 -0
  140. package/dist/modules/{comment/comment.module.d.ts → comments/comments.module.d.ts} +6 -6
  141. package/dist/modules/{comment/comment.module.js → comments/comments.module.js} +17 -16
  142. package/dist/modules/{comment/comment.service.d.ts → comments/comments.service.d.ts} +35 -9
  143. package/dist/modules/comments/comments.service.js +165 -0
  144. package/dist/modules/comments/index.d.ts +3 -0
  145. package/dist/modules/{services/providers/comments → comments}/index.js +2 -0
  146. package/dist/modules/index.d.ts +1 -1
  147. package/dist/modules/index.js +1 -1
  148. package/dist/modules/like/like-module-options.interface.d.ts +1 -0
  149. package/dist/modules/like/like.controller.d.ts +3 -2
  150. package/dist/modules/like/like.controller.js +4 -4
  151. package/dist/modules/like/like.module.js +1 -1
  152. package/dist/modules/like/like.service.d.ts +0 -16
  153. package/dist/modules/like/like.service.js +9 -28
  154. package/dist/modules/merge/merge-module-options.interface.d.ts +1 -0
  155. package/dist/modules/merge/merge.controller.d.ts +3 -2
  156. package/dist/modules/merge/merge.controller.js +4 -4
  157. package/dist/modules/merge/merge.module.js +1 -1
  158. package/dist/modules/services/providers/accounts.service.js +4 -0
  159. package/dist/modules/services/providers/index.d.ts +0 -1
  160. package/dist/modules/services/providers/index.js +0 -1
  161. package/dist/modules/services/services.module.js +0 -1
  162. package/dist/pipes/index.d.ts +1 -0
  163. package/dist/pipes/index.js +1 -0
  164. package/dist/pipes/restricted-fields.pipe.d.ts +35 -0
  165. package/dist/pipes/restricted-fields.pipe.js +83 -0
  166. package/dist/properties/content-return-type.property.d.ts +4 -0
  167. package/dist/properties/content-return-type.property.js +12 -7
  168. package/dist/properties/content.property.d.ts +7 -2
  169. package/dist/properties/content.property.js +11 -3
  170. package/dist/properties/index.d.ts +2 -4
  171. package/dist/properties/index.js +5 -5
  172. package/dist/transform/index.d.ts +2 -0
  173. package/dist/transform/index.js +2 -0
  174. package/dist/transform/mongo-id.transform.d.ts +4 -0
  175. package/dist/transform/mongo-id.transform.js +13 -0
  176. package/dist/transform/mongo-ids.transform.d.ts +4 -0
  177. package/dist/transform/mongo-ids.transform.js +16 -0
  178. package/dist/types/duplicable-model.type.d.ts +10 -0
  179. package/dist/types/duplicable-model.type.js +2 -0
  180. package/dist/types/index.d.ts +1 -0
  181. package/dist/types/index.js +1 -0
  182. package/dist/types/likeable.type.d.ts +4 -3
  183. package/dist/types/viewable.type.d.ts +4 -3
  184. package/dist/viewable.interface.d.ts +42 -0
  185. package/dist/viewable.interface.js +48 -0
  186. package/package.json +1 -1
  187. package/dist/classes/schema-builder.class.d.ts +0 -75
  188. package/dist/classes/schema-builder.class.js +0 -109
  189. package/dist/modules/comment/comment.module-definition.d.ts +0 -4
  190. package/dist/modules/comment/comment.service.js +0 -99
  191. package/dist/modules/comment/index.d.ts +0 -2
  192. package/dist/modules/services/providers/comments/comments.service-definition.d.ts +0 -1
  193. package/dist/modules/services/providers/comments/comments.service-definition.js +0 -4
  194. package/dist/modules/services/providers/comments/comments.service.d.ts +0 -60
  195. package/dist/modules/services/providers/comments/comments.service.js +0 -139
  196. package/dist/modules/services/providers/comments/index.d.ts +0 -1
  197. package/dist/properties/likeable.properties.d.ts +0 -1
  198. package/dist/properties/likeable.properties.js +0 -66
  199. package/dist/properties/viewable.properties.d.ts +0 -1
  200. package/dist/properties/viewable.properties.js +0 -66
  201. /package/dist/modules/{comment/comment-module-options.interface.js → _old/database/database-module-options.interface.js} +0 -0
@@ -0,0 +1,83 @@
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
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.RestrictedFieldsPipe = void 0;
16
+ exports.Restricted = Restricted;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@nestjs/core");
19
+ const class_validator_1 = require("class-validator");
20
+ const itlab_functions_1 = require("itlab-functions");
21
+ const modules_1 = require("../modules");
22
+ const service_auth_guard_1 = require("../modules/authentication/guards/service-auth.guard");
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
+ /**
42
+ * RestrictedFieldsPipe
43
+ *
44
+ * Global pipe that inspects incoming DTOs for properties decorated with `@Restricted`.
45
+ * If the current request's account lacks the required permissions,
46
+ * the corresponding properties are stripped from the DTO.
47
+ *
48
+ * This ensures that sensitive fields are never accidentally
49
+ * processed further down the request lifecycle.
50
+ */
51
+ let RestrictedFieldsPipe = class RestrictedFieldsPipe {
52
+ constructor(request, authenticationOptions, reflector) {
53
+ this.request = request;
54
+ this.authenticationOptions = authenticationOptions;
55
+ this.reflector = reflector;
56
+ }
57
+ transform(value, metadata) {
58
+ var _a, _b, _c;
59
+ // Allow trusted service-to-service calls (skip restriction checks)
60
+ const serviceToken = this.request.header(service_auth_guard_1.SERVICE_AUTH_HEADER_KEY);
61
+ if (serviceToken === this.authenticationOptions.k8sToken)
62
+ return value;
63
+ // Only process object payloads (primitives remain unchanged)
64
+ if (!(0, class_validator_1.isObject)(value))
65
+ return value;
66
+ // Determine the permissions available to this account
67
+ const grantedPerms = (_b = (_a = this.request.account) === null || _a === void 0 ? void 0 : _a.perms) !== null && _b !== void 0 ? _b : [];
68
+ const restrictions = this.reflector.get(RESTRICTED_METADATA_KEY, (_c = metadata.metatype) === null || _c === void 0 ? void 0 : _c.prototype);
69
+ for (const [propertyKey, requiredPerms] of Object.entries(restrictions)) {
70
+ if (requiredPerms.length && !(0, itlab_functions_1.hasSomePermission)(requiredPerms, grantedPerms)) {
71
+ delete value[propertyKey];
72
+ }
73
+ }
74
+ return value;
75
+ }
76
+ };
77
+ exports.RestrictedFieldsPipe = RestrictedFieldsPipe;
78
+ exports.RestrictedFieldsPipe = RestrictedFieldsPipe = __decorate([
79
+ (0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
80
+ __param(0, (0, common_1.Inject)(core_1.REQUEST)),
81
+ __param(1, (0, modules_1.InjectAuthenticationOptions)()),
82
+ __metadata("design:paramtypes", [Object, Object, core_1.Reflector])
83
+ ], RestrictedFieldsPipe);
@@ -1,7 +1,11 @@
1
+ import { ApiPropertyOptions } from '@nestjs/swagger';
1
2
  import { ContentReturnType } from '../modules';
2
3
  type PropertyContentReturnTypeOptions = {
3
4
  optional?: boolean;
4
5
  default?: ContentReturnType;
5
6
  };
7
+ export declare function isSupportedContentType(value: unknown): value is ContentReturnType;
6
8
  export declare function PropertyContentReturnType(options?: PropertyContentReturnTypeOptions): PropertyDecorator;
9
+ export declare function ApiPropertyContentReturnType(options?: ApiPropertyOptions): PropertyDecorator;
10
+ export declare function ApiPropertyOptionalContentReturnType(options?: ApiPropertyOptions): PropertyDecorator;
7
11
  export {};
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSupportedContentType = isSupportedContentType;
3
4
  exports.PropertyContentReturnType = PropertyContentReturnType;
5
+ exports.ApiPropertyContentReturnType = ApiPropertyContentReturnType;
6
+ exports.ApiPropertyOptionalContentReturnType = ApiPropertyOptionalContentReturnType;
4
7
  const common_1 = require("@nestjs/common");
5
8
  const swagger_1 = require("@nestjs/swagger");
6
9
  const class_transformer_1 = require("class-transformer");
@@ -10,13 +13,15 @@ function isSupportedContentType(value) {
10
13
  return content_return_types_1.supportedContentReturnTypes.some((type) => type === value);
11
14
  }
12
15
  function PropertyContentReturnType(options = {}) {
13
- const decorators = [
14
- (0, swagger_1.ApiProperty)(Object.assign({ description: 'In which format should the content be returned', examples: [...content_return_types_1.supportedContentReturnTypes] }, options)),
15
- (0, class_transformer_1.Transform)(({ value }) => (isSupportedContentType(value) ? value : options.default)),
16
- (0, class_validator_1.IsIn)(content_return_types_1.supportedContentReturnTypes, { message: 'Invalid content return type' }),
17
- ];
16
+ const ContentTypeTransform = () => (0, class_transformer_1.Transform)(({ value }) => (isSupportedContentType(value) ? value : options.default || undefined));
18
17
  if (options.optional) {
19
- decorators.push(common_1.Optional);
18
+ return (0, common_1.applyDecorators)(ContentTypeTransform(), (0, class_validator_1.IsIn)([...content_return_types_1.supportedContentReturnTypes, undefined], { message: 'Invalid content return type' }), (0, class_validator_1.IsOptional)());
20
19
  }
21
- return (0, common_1.applyDecorators)(...decorators);
20
+ return (0, common_1.applyDecorators)(ContentTypeTransform(), (0, class_validator_1.IsIn)([...content_return_types_1.supportedContentReturnTypes], { message: 'Invalid content return type' }));
21
+ }
22
+ function ApiPropertyContentReturnType(options = {}) {
23
+ return (0, swagger_1.ApiProperty)(Object.assign({ description: 'In which format should the content be returned', enum: content_return_types_1.supportedContentReturnTypes }, options));
24
+ }
25
+ function ApiPropertyOptionalContentReturnType(options = {}) {
26
+ return (0, swagger_1.ApiPropertyOptional)(Object.assign({ description: 'In which format should the content be returned', enum: [undefined, ...content_return_types_1.supportedContentReturnTypes], default: undefined }, options));
22
27
  }
@@ -7,7 +7,12 @@ import { ApiPropertyOptions } from '@nestjs/swagger';
7
7
  * - Transforms empty arrays into `undefined` to prevent saving invalid content.
8
8
  * - Adds Swagger documentation with the ability to override options.
9
9
  *
10
- * @param {ApiPropertyOptions} [options={}] - Optional Swagger property settings.
11
10
  * @returns {PropertyDecorator} - Combined decorator for Swagger, validation, and transformation.
12
11
  */
13
- export declare function PropertyContent(options?: ApiPropertyOptions): PropertyDecorator;
12
+ export declare function PropertyContent(): PropertyDecorator;
13
+ /**
14
+ *
15
+ * @param {ApiPropertyOptions} [options={}] - Optional Swagger property settings.
16
+ * @returns
17
+ */
18
+ export declare function ApiPropertyContent(options?: ApiPropertyOptions): PropertyDecorator;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PropertyContent = PropertyContent;
4
+ exports.ApiPropertyContent = ApiPropertyContent;
4
5
  const common_1 = require("@nestjs/common");
5
6
  const swagger_1 = require("@nestjs/swagger");
6
7
  const class_transformer_1 = require("class-transformer");
@@ -13,11 +14,10 @@ const class_validator_1 = require("class-validator");
13
14
  * - Transforms empty arrays into `undefined` to prevent saving invalid content.
14
15
  * - Adds Swagger documentation with the ability to override options.
15
16
  *
16
- * @param {ApiPropertyOptions} [options={}] - Optional Swagger property settings.
17
17
  * @returns {PropertyDecorator} - Combined decorator for Swagger, validation, and transformation.
18
18
  */
19
- function PropertyContent(options = {}) {
20
- return (0, common_1.applyDecorators)((0, swagger_1.ApiProperty)(Object.assign({ example: [] }, options)),
19
+ function PropertyContent() {
20
+ return (0, common_1.applyDecorators)(
21
21
  // Transforms values: ensures empty or invalid arrays are sanitized to undefined
22
22
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
23
23
  (0, class_transformer_1.Transform)(({ value }) => ((0, class_validator_1.arrayMinSize)(value, 1) ? value : undefined)),
@@ -26,3 +26,11 @@ function PropertyContent(options = {}) {
26
26
  message: 'Der Inhalt muss mindestens 1 Element haben',
27
27
  }));
28
28
  }
29
+ /**
30
+ *
31
+ * @param {ApiPropertyOptions} [options={}] - Optional Swagger property settings.
32
+ * @returns
33
+ */
34
+ function ApiPropertyContent(options = {}) {
35
+ return (0, swagger_1.ApiProperty)(Object.assign({ example: [] }, options));
36
+ }
@@ -1,4 +1,2 @@
1
- export { PropertyContentReturnType } from './content-return-type.property';
2
- export { PropertyContent } from './content.property';
3
- export { PropertiesLikeable } from './likeable.properties';
4
- export { PropertiesViewable } from './viewable.properties';
1
+ export { ApiPropertyContentReturnType, ApiPropertyOptionalContentReturnType, isSupportedContentType, PropertyContentReturnType, } from './content-return-type.property';
2
+ export { ApiPropertyContent, PropertyContent } from './content.property';
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PropertiesViewable = exports.PropertiesLikeable = exports.PropertyContent = exports.PropertyContentReturnType = void 0;
3
+ exports.PropertyContent = exports.ApiPropertyContent = exports.PropertyContentReturnType = exports.isSupportedContentType = exports.ApiPropertyOptionalContentReturnType = exports.ApiPropertyContentReturnType = void 0;
4
4
  var content_return_type_property_1 = require("./content-return-type.property");
5
+ Object.defineProperty(exports, "ApiPropertyContentReturnType", { enumerable: true, get: function () { return content_return_type_property_1.ApiPropertyContentReturnType; } });
6
+ Object.defineProperty(exports, "ApiPropertyOptionalContentReturnType", { enumerable: true, get: function () { return content_return_type_property_1.ApiPropertyOptionalContentReturnType; } });
7
+ Object.defineProperty(exports, "isSupportedContentType", { enumerable: true, get: function () { return content_return_type_property_1.isSupportedContentType; } });
5
8
  Object.defineProperty(exports, "PropertyContentReturnType", { enumerable: true, get: function () { return content_return_type_property_1.PropertyContentReturnType; } });
6
9
  var content_property_1 = require("./content.property");
10
+ Object.defineProperty(exports, "ApiPropertyContent", { enumerable: true, get: function () { return content_property_1.ApiPropertyContent; } });
7
11
  Object.defineProperty(exports, "PropertyContent", { enumerable: true, get: function () { return content_property_1.PropertyContent; } });
8
- var likeable_properties_1 = require("./likeable.properties");
9
- Object.defineProperty(exports, "PropertiesLikeable", { enumerable: true, get: function () { return likeable_properties_1.PropertiesLikeable; } });
10
- var viewable_properties_1 = require("./viewable.properties");
11
- Object.defineProperty(exports, "PropertiesViewable", { enumerable: true, get: function () { return viewable_properties_1.PropertiesViewable; } });
@@ -1,5 +1,7 @@
1
1
  export * from './boolean.transform';
2
2
  export * from './image-url.transform';
3
+ export * from './mongo-id.transform';
4
+ export * from './mongo-ids.transform';
3
5
  export * from './number.transform';
4
6
  export * from './string-array.transform';
5
7
  export * from './string.transform';
@@ -16,6 +16,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./boolean.transform"), exports);
18
18
  __exportStar(require("./image-url.transform"), exports);
19
+ __exportStar(require("./mongo-id.transform"), exports);
20
+ __exportStar(require("./mongo-ids.transform"), exports);
19
21
  __exportStar(require("./number.transform"), exports);
20
22
  __exportStar(require("./string-array.transform"), exports);
21
23
  __exportStar(require("./string.transform"), exports);
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @returns {PropertyDecorator} - Transforms a property to a boolean.
3
+ */
4
+ export declare function MongoIdTransform(): PropertyDecorator;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoIdTransform = MongoIdTransform;
4
+ const class_transformer_1 = require("class-transformer");
5
+ const class_validator_1 = require("class-validator");
6
+ /**
7
+ * @returns {PropertyDecorator} - Transforms a property to a boolean.
8
+ */
9
+ function MongoIdTransform() {
10
+ return (0, class_transformer_1.Transform)(({ value }) => {
11
+ return (0, class_validator_1.isMongoId)(value) ? String(value) : undefined;
12
+ });
13
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @returns {PropertyDecorator} - Transforms a property to a boolean.
3
+ */
4
+ export declare function MongoIdsTransform(): PropertyDecorator;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MongoIdsTransform = MongoIdsTransform;
4
+ const class_transformer_1 = require("class-transformer");
5
+ const class_validator_1 = require("class-validator");
6
+ /**
7
+ * @returns {PropertyDecorator} - Transforms a property to a boolean.
8
+ */
9
+ function MongoIdsTransform() {
10
+ return (0, class_transformer_1.Transform)(({ value }) => {
11
+ if (!(0, class_validator_1.isArray)(value))
12
+ return undefined;
13
+ const mongoIds = value.filter((v) => (0, class_validator_1.isMongoId)(v));
14
+ return Array.from(new Set(mongoIds));
15
+ });
16
+ }
@@ -0,0 +1,10 @@
1
+ import { Document, Model } from 'mongoose';
2
+ export type DuplicableModel<TBase extends Document> = Model<TBase> & {
3
+ /**
4
+ * Checks if a document is a duplicate based on critical keys.
5
+ * This will be overridden when the schema is created.
6
+ * @param dto - Data to check for duplicates
7
+ * @param document - Existing document (optional)
8
+ */
9
+ isDuplicate(dto: Partial<Omit<TBase, keyof Document>>, target?: TBase): Promise<boolean>;
10
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +1,3 @@
1
+ export * from './duplicable-model.type';
1
2
  export * from './likeable.type';
2
3
  export * from './viewable.type';
@@ -14,5 +14,6 @@ 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
+ __exportStar(require("./duplicable-model.type"), exports);
17
18
  __exportStar(require("./likeable.type"), exports);
18
19
  __exportStar(require("./viewable.type"), exports);
@@ -6,10 +6,11 @@ import { User } from '../models';
6
6
  * - `likes`: computed total number of likes.
7
7
  * - `likedBy`: optional populated list of User objects.
8
8
  */
9
- export type Likeable = {
9
+ export type IsLikeable = {
10
10
  _likedBy: string[];
11
11
  likes: number;
12
12
  likedBy?: User[];
13
- addLike(accountId: string): Promise<void>;
14
- removeLike(accountId: string): Promise<void>;
13
+ addLike(accountId: string): Promise<number>;
14
+ removeLike(accountId: string): Promise<number>;
15
+ hasLiked(accountId: string): boolean;
15
16
  };
@@ -6,10 +6,11 @@ import { User } from '../models';
6
6
  * - `views`: computed total number of views.
7
7
  * - `viewedBy`: optional populated list of User objects.
8
8
  */
9
- export type Viewable = {
9
+ export type IsViewable = {
10
10
  _viewedBy: string[];
11
11
  views: number;
12
12
  viewedBy?: User[];
13
- addView(accountId: string): Promise<void>;
14
- removeView(accountId: string): Promise<void>;
13
+ addView(accountId: string): Promise<number>;
14
+ removeView(accountId: string): Promise<number>;
15
+ hasViewed(accountId: string): boolean;
15
16
  };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * TODO: REMOVE
3
+ * Interface for entities that track user views. This allows the system to monitor
4
+ * which accounts have viewed an item and how many total views it has received.
5
+ *
6
+ * Used to enable features such as view analytics, popularity ranking, or recommendation systems.
7
+ */
8
+ export interface Viewable {
9
+ /**
10
+ * List of account IDs who have viewed this entity.
11
+ */
12
+ _viewedBy: string[];
13
+ /**
14
+ * Count of total views.
15
+ */
16
+ views: number;
17
+ }
18
+ /**
19
+ * Mongoose schema decorator for the `_viewedBy` field, which tracks unique viewer IDs.
20
+ * Initialized as an empty array to ensure a consistent schema across documents.
21
+ *
22
+ * @returns {PropertyDecorator} - Mongoose configuration for tracking viewers.
23
+ */
24
+ export declare function PropertyViewedBy(): PropertyDecorator;
25
+ /**
26
+ * Swagger schema decorator for the `_viewedBy` field. Used in OpenAPI documentation
27
+ * to describe which users have viewed the entity.
28
+ *
29
+ * It enhances API clarity for clients consuming entities that support view tracking.
30
+ *
31
+ * @returns {PropertyDecorator} - Swagger metadata for the `viewedBy` field.
32
+ */
33
+ export declare function ApiViewedBy(): PropertyDecorator;
34
+ /**
35
+ * Swagger schema decorator for the `views` field. Communicates to API consumers
36
+ * the meaning and default value of the view count.
37
+ *
38
+ * Helps visualize popularity or engagement metrics in API tooling.
39
+ *
40
+ * @returns {PropertyDecorator} - Swagger metadata for the `views` field.
41
+ */
42
+ export declare function ApiViews(): PropertyDecorator;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PropertyViewedBy = PropertyViewedBy;
4
+ exports.ApiViewedBy = ApiViewedBy;
5
+ exports.ApiViews = ApiViews;
6
+ const mongoose_1 = require("@nestjs/mongoose");
7
+ const swagger_1 = require("@nestjs/swagger");
8
+ const models_1 = require("./models");
9
+ /**
10
+ * Mongoose schema decorator for the `_viewedBy` field, which tracks unique viewer IDs.
11
+ * Initialized as an empty array to ensure a consistent schema across documents.
12
+ *
13
+ * @returns {PropertyDecorator} - Mongoose configuration for tracking viewers.
14
+ */
15
+ function PropertyViewedBy() {
16
+ return (0, mongoose_1.Prop)({ required: true, default: () => [] });
17
+ }
18
+ /**
19
+ * Swagger schema decorator for the `_viewedBy` field. Used in OpenAPI documentation
20
+ * to describe which users have viewed the entity.
21
+ *
22
+ * It enhances API clarity for clients consuming entities that support view tracking.
23
+ *
24
+ * @returns {PropertyDecorator} - Swagger metadata for the `viewedBy` field.
25
+ */
26
+ function ApiViewedBy() {
27
+ return (0, swagger_1.ApiProperty)({
28
+ name: 'viewedBy',
29
+ type: [models_1.Account],
30
+ default: [],
31
+ description: 'Accounts that have viewed this entity.',
32
+ });
33
+ }
34
+ /**
35
+ * Swagger schema decorator for the `views` field. Communicates to API consumers
36
+ * the meaning and default value of the view count.
37
+ *
38
+ * Helps visualize popularity or engagement metrics in API tooling.
39
+ *
40
+ * @returns {PropertyDecorator} - Swagger metadata for the `views` field.
41
+ */
42
+ function ApiViews() {
43
+ return (0, swagger_1.ApiProperty)({
44
+ type: Number,
45
+ default: 0,
46
+ description: 'Total number of views this entity has received.',
47
+ });
48
+ }
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.1",
7
+ "version": "2.16.3",
8
8
  "type": "commonjs",
9
9
  "files": [
10
10
  "dist"
@@ -1,75 +0,0 @@
1
- import { Type } from '@nestjs/common';
2
- import { Document, Model, Schema } from 'mongoose';
3
- import { Likeable, Viewable } from '../types';
4
- /**
5
- * Options that determine how the schema should be extended.
6
- *
7
- * @template TClass - The document type for the schema.
8
- */
9
- export type SchemaBuilderOptions<TClass extends Document> = {
10
- /** Whether this schema should support view tracking. */
11
- viewable?: boolean;
12
- /** Whether this schema should support like tracking. */
13
- likeable?: boolean;
14
- /**
15
- * A set of keys that uniquely identify the document.
16
- * These keys are used when checking for duplicates.
17
- */
18
- criticalKeys?: (keyof Omit<TClass, keyof Document>)[];
19
- };
20
- /**
21
- * Computes the augmented document type based on SchemaOptions.
22
- */
23
- export type SchemaBuilderDocument<TClass extends Document, TOptions extends SchemaBuilderOptions<TClass>> = TClass & (TOptions['viewable'] extends true ? Viewable : object) & (TOptions['likeable'] extends true ? Likeable : object);
24
- /**
25
- * Extends a standard Mongoose model with custom static methods
26
- * injected by the SchemaBuilder.
27
- */
28
- export type SchemaBuilderModel<TClass extends Document> = Model<TClass> & {
29
- /**
30
- * Checks if the given object is a duplicate of an existing document.
31
- *
32
- * @param dto - Partial object with properties to check for duplicates.
33
- * @param updateTarget - The document being updated, if applicable.
34
- * @returns {Promise<boolean>} - True if a duplicate exists, false otherwise.
35
- */
36
- isDuplicate(dto: Partial<TClass>, updateTarget?: TClass): Promise<boolean>;
37
- };
38
- /**
39
- * Generic builder for creating extended Mongoose schemas.
40
- *
41
- * This class wraps Nest's SchemaFactory and automatically injects common
42
- * behaviors such as:
43
- * - View tracking (who viewed, view counts)
44
- * - Like tracking (who liked, like counts)
45
- * - Duplicate checking based on critical keys
46
- *
47
- * @template TClass - A class extending Mongoose Document.
48
- */
49
- export declare class SchemaBuilder<TClass extends Document> {
50
- private schema;
51
- readonly options: SchemaBuilderOptions<TClass>;
52
- constructor(target: Type<TClass>, options?: SchemaBuilderOptions<TClass>);
53
- /**
54
- * Adds interaction tracking (likes or views) to a schema.
55
- * This method generalizes the shared logic between "viewable" and "likeable".
56
- *
57
- * @param field - The internal array field storing account IDs. (e.g. _viewedBy or _likedBy)
58
- * @param counter - The numeric counter field tracking totals. (e.g. views or likes)
59
- */
60
- provideInteraction(field: string, counter: string): this;
61
- /**
62
- * Adds a duplicate-checking static method to the schema.
63
- * This method compares critical keys to detect conflicts.
64
- */
65
- private provideDuplicateChecker;
66
- /**
67
- * Finalizes the schema and injects any selected behaviors (viewable, likeable, duplicate checking).
68
- *
69
- * @returns An object containing:
70
- * - `schema`: The Mongoose schema.
71
- * - `modelType`: A strongly typed model with additional static methods.
72
- * - `documentType`: The inferred document type with injected properties.
73
- */
74
- build(): Schema;
75
- }
@@ -1,109 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SchemaBuilder = void 0;
4
- const mongoose_1 = require("@nestjs/mongoose");
5
- const class_validator_1 = require("class-validator");
6
- /**
7
- * Generic builder for creating extended Mongoose schemas.
8
- *
9
- * This class wraps Nest's SchemaFactory and automatically injects common
10
- * behaviors such as:
11
- * - View tracking (who viewed, view counts)
12
- * - Like tracking (who liked, like counts)
13
- * - Duplicate checking based on critical keys
14
- *
15
- * @template TClass - A class extending Mongoose Document.
16
- */
17
- class SchemaBuilder {
18
- constructor(target, options = {}) {
19
- this.schema = mongoose_1.SchemaFactory.createForClass(target);
20
- this.options = options;
21
- /**
22
- * Create a wildcard index required for CosmosDB to support sorting on all fields.
23
- *
24
- * This is a workaround for CosmosDB's partial MongoDB API compatibility.
25
- * See: https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/indexing#wildcard-indexes
26
- */
27
- this.schema.index({ '$**': 1 }, { name: 'Sort Index' });
28
- this.provideDuplicateChecker();
29
- }
30
- /**
31
- * Adds interaction tracking (likes or views) to a schema.
32
- * This method generalizes the shared logic between "viewable" and "likeable".
33
- *
34
- * @param field - The internal array field storing account IDs. (e.g. _viewedBy or _likedBy)
35
- * @param counter - The numeric counter field tracking totals. (e.g. views or likes)
36
- */
37
- provideInteraction(field, counter) {
38
- // Add fields to the schema
39
- this.schema.add({ [field]: { type: [String], default: [] }, [counter]: { type: Number, default: 0 } });
40
- // Expose a virtual property (without underscore) for convenience
41
- this.schema.virtual(field.replace(/^_/, ''));
42
- // Add method to increment counter
43
- this.schema.methods[`add${counter[0].toUpperCase() + counter.slice(1)}`] = async function (accountId) {
44
- if (!(0, class_validator_1.isMongoId)(accountId))
45
- return Number(this[counter]);
46
- // Ensure uniqueness by converting to a Set
47
- this[field] = Array.from(new Set([...this[field], accountId]));
48
- this[counter] = this[field].length;
49
- await this.save({ timestamps: false });
50
- return this[counter];
51
- };
52
- // Add method to decrement counter
53
- this.schema.methods[`remove${counter[0].toUpperCase() + counter.slice(1)}`] = async function (accountId) {
54
- if (!(0, class_validator_1.isMongoId)(accountId))
55
- return Number(this[counter]);
56
- // Remove the accountId from the list
57
- this[field] = this[field].filter((id) => id !== accountId);
58
- this[counter] = this[field].length;
59
- await this.save({ timestamps: false });
60
- return this[counter];
61
- };
62
- return this;
63
- }
64
- /**
65
- * Adds a duplicate-checking static method to the schema.
66
- * This method compares critical keys to detect conflicts.
67
- */
68
- provideDuplicateChecker() {
69
- var _a;
70
- const criticalKeys = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.criticalKeys) || [];
71
- this.schema.statics.isDuplicate = async function (dto, updateTarget) {
72
- var _a;
73
- if (criticalKeys.length === 0)
74
- return false;
75
- // Build a filter using the critical keys
76
- const filterQuery = criticalKeys.reduce((query, key) => {
77
- if (dto && key in dto)
78
- query[String(key)] = dto[key];
79
- else if (updateTarget && key in updateTarget)
80
- query[String(key)] = updateTarget[key];
81
- return query;
82
- }, {});
83
- // If a matching document exists, check whether it’s the same entity
84
- const potentialDuplicate = await this.findOne(filterQuery);
85
- if (!potentialDuplicate)
86
- return false;
87
- const potentialId = potentialDuplicate._id.toString().toLowerCase();
88
- const targetId = (_a = updateTarget === null || updateTarget === void 0 ? void 0 : updateTarget._id) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase();
89
- return potentialId !== targetId;
90
- };
91
- }
92
- /**
93
- * Finalizes the schema and injects any selected behaviors (viewable, likeable, duplicate checking).
94
- *
95
- * @returns An object containing:
96
- * - `schema`: The Mongoose schema.
97
- * - `modelType`: A strongly typed model with additional static methods.
98
- * - `documentType`: The inferred document type with injected properties.
99
- */
100
- build() {
101
- var _a, _b;
102
- if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.viewable)
103
- this.provideInteraction('_viewedBy', 'views');
104
- if ((_b = this.options) === null || _b === void 0 ? void 0 : _b.likeable)
105
- this.provideInteraction('_likedBy', 'likes');
106
- return this.schema;
107
- }
108
- }
109
- exports.SchemaBuilder = SchemaBuilder;
@@ -1,4 +0,0 @@
1
- /**
2
- * Dependency injection token for CommentModule options.
3
- */
4
- export declare const COMMENT_MODULE_OPTIONS_TOKEN: unique symbol;