bozonx-social-media-posting 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1003 -0
  3. package/dist/src/app.constants.d.ts +8 -0
  4. package/dist/src/app.constants.js +9 -0
  5. package/dist/src/app.constants.js.map +1 -0
  6. package/dist/src/common/enums/body-format.enum.d.ts +12 -0
  7. package/dist/src/common/enums/body-format.enum.js +14 -0
  8. package/dist/src/common/enums/body-format.enum.js.map +1 -0
  9. package/dist/src/common/enums/error-code.enum.d.ts +12 -0
  10. package/dist/src/common/enums/error-code.enum.js +14 -0
  11. package/dist/src/common/enums/error-code.enum.js.map +1 -0
  12. package/dist/src/common/enums/index.d.ts +3 -0
  13. package/dist/src/common/enums/index.js +4 -0
  14. package/dist/src/common/enums/index.js.map +1 -0
  15. package/dist/src/common/enums/post-type.enum.d.ts +28 -0
  16. package/dist/src/common/enums/post-type.enum.js +30 -0
  17. package/dist/src/common/enums/post-type.enum.js.map +1 -0
  18. package/dist/src/common/filters/all-exceptions.filter.d.ts +13 -0
  19. package/dist/src/common/filters/all-exceptions.filter.js +103 -0
  20. package/dist/src/common/filters/all-exceptions.filter.js.map +1 -0
  21. package/dist/src/common/helpers/media-input.helper.d.ts +73 -0
  22. package/dist/src/common/helpers/media-input.helper.js +122 -0
  23. package/dist/src/common/helpers/media-input.helper.js.map +1 -0
  24. package/dist/src/common/interceptors/shutdown.interceptor.d.ts +12 -0
  25. package/dist/src/common/interceptors/shutdown.interceptor.js +41 -0
  26. package/dist/src/common/interceptors/shutdown.interceptor.js.map +1 -0
  27. package/dist/src/common/interfaces/logger.interface.d.ts +44 -0
  28. package/dist/src/common/interfaces/logger.interface.js +44 -0
  29. package/dist/src/common/interfaces/logger.interface.js.map +1 -0
  30. package/dist/src/common/services/shutdown.module.d.ts +2 -0
  31. package/dist/src/common/services/shutdown.module.js +18 -0
  32. package/dist/src/common/services/shutdown.module.js.map +1 -0
  33. package/dist/src/common/services/shutdown.service.d.ts +40 -0
  34. package/dist/src/common/services/shutdown.service.js +122 -0
  35. package/dist/src/common/services/shutdown.service.js.map +1 -0
  36. package/dist/src/common/types/index.d.ts +1 -0
  37. package/dist/src/common/types/index.js +2 -0
  38. package/dist/src/common/types/index.js.map +1 -0
  39. package/dist/src/common/types/media-input.type.d.ts +29 -0
  40. package/dist/src/common/types/media-input.type.js +2 -0
  41. package/dist/src/common/types/media-input.type.js.map +1 -0
  42. package/dist/src/common/validators/body-length.validator.d.ts +24 -0
  43. package/dist/src/common/validators/body-length.validator.js +57 -0
  44. package/dist/src/common/validators/body-length.validator.js.map +1 -0
  45. package/dist/src/common/validators/channel-id.validator.d.ts +19 -0
  46. package/dist/src/common/validators/channel-id.validator.js +58 -0
  47. package/dist/src/common/validators/channel-id.validator.js.map +1 -0
  48. package/dist/src/common/validators/has-content.validator.d.ts +23 -0
  49. package/dist/src/common/validators/has-content.validator.js +57 -0
  50. package/dist/src/common/validators/has-content.validator.js.map +1 -0
  51. package/dist/src/common/validators/media-input.validator.d.ts +44 -0
  52. package/dist/src/common/validators/media-input.validator.js +112 -0
  53. package/dist/src/common/validators/media-input.validator.js.map +1 -0
  54. package/dist/src/common/validators/media-priority.validator.d.ts +19 -0
  55. package/dist/src/common/validators/media-priority.validator.js +38 -0
  56. package/dist/src/common/validators/media-priority.validator.js.map +1 -0
  57. package/dist/src/config/app.config.d.ts +33 -0
  58. package/dist/src/config/app.config.js +83 -0
  59. package/dist/src/config/app.config.js.map +1 -0
  60. package/dist/src/config/library.config.d.ts +51 -0
  61. package/dist/src/config/library.config.js +197 -0
  62. package/dist/src/config/library.config.js.map +1 -0
  63. package/dist/src/config/yaml-config.dto.d.ts +37 -0
  64. package/dist/src/config/yaml-config.dto.js +152 -0
  65. package/dist/src/config/yaml-config.dto.js.map +1 -0
  66. package/dist/src/config/yaml.config.d.ts +14 -0
  67. package/dist/src/config/yaml.config.js +72 -0
  68. package/dist/src/config/yaml.config.js.map +1 -0
  69. package/dist/src/index.d.ts +19 -0
  70. package/dist/src/index.js +17 -0
  71. package/dist/src/index.js.map +1 -0
  72. package/dist/src/library.d.ts +57 -0
  73. package/dist/src/library.js +92 -0
  74. package/dist/src/library.js.map +1 -0
  75. package/dist/src/modules/app-config/app-config.module.d.ts +2 -0
  76. package/dist/src/modules/app-config/app-config.module.js +26 -0
  77. package/dist/src/modules/app-config/app-config.module.js.map +1 -0
  78. package/dist/src/modules/app-config/app-config.service.d.ts +14 -0
  79. package/dist/src/modules/app-config/app-config.service.js +18 -0
  80. package/dist/src/modules/app-config/app-config.service.js.map +1 -0
  81. package/dist/src/modules/app-config/interfaces/app-config.interface.d.ts +31 -0
  82. package/dist/src/modules/app-config/interfaces/app-config.interface.js +2 -0
  83. package/dist/src/modules/app-config/interfaces/app-config.interface.js.map +1 -0
  84. package/dist/src/modules/app-config/nest-config.service.d.ts +41 -0
  85. package/dist/src/modules/app-config/nest-config.service.js +91 -0
  86. package/dist/src/modules/app-config/nest-config.service.js.map +1 -0
  87. package/dist/src/modules/health/health.controller.d.ts +12 -0
  88. package/dist/src/modules/health/health.controller.js +33 -0
  89. package/dist/src/modules/health/health.controller.js.map +1 -0
  90. package/dist/src/modules/health/health.module.d.ts +2 -0
  91. package/dist/src/modules/health/health.module.js +17 -0
  92. package/dist/src/modules/health/health.module.js.map +1 -0
  93. package/dist/src/modules/media/media.module.d.ts +2 -0
  94. package/dist/src/modules/media/media.module.js +18 -0
  95. package/dist/src/modules/media/media.module.js.map +1 -0
  96. package/dist/src/modules/media/media.service.d.ts +15 -0
  97. package/dist/src/modules/media/media.service.js +49 -0
  98. package/dist/src/modules/media/media.service.js.map +1 -0
  99. package/dist/src/modules/platforms/base/auth-validator-registry.service.d.ts +25 -0
  100. package/dist/src/modules/platforms/base/auth-validator-registry.service.js +50 -0
  101. package/dist/src/modules/platforms/base/auth-validator-registry.service.js.map +1 -0
  102. package/dist/src/modules/platforms/base/auth-validator.interface.d.ts +16 -0
  103. package/dist/src/modules/platforms/base/auth-validator.interface.js +2 -0
  104. package/dist/src/modules/platforms/base/auth-validator.interface.js.map +1 -0
  105. package/dist/src/modules/platforms/base/index.d.ts +4 -0
  106. package/dist/src/modules/platforms/base/index.js +5 -0
  107. package/dist/src/modules/platforms/base/index.js.map +1 -0
  108. package/dist/src/modules/platforms/base/platform-registry.service.d.ts +31 -0
  109. package/dist/src/modules/platforms/base/platform-registry.service.js +54 -0
  110. package/dist/src/modules/platforms/base/platform-registry.service.js.map +1 -0
  111. package/dist/src/modules/platforms/base/platform.interface.d.ts +39 -0
  112. package/dist/src/modules/platforms/base/platform.interface.js +2 -0
  113. package/dist/src/modules/platforms/base/platform.interface.js.map +1 -0
  114. package/dist/src/modules/platforms/platforms.module.d.ts +13 -0
  115. package/dist/src/modules/platforms/platforms.module.js +59 -0
  116. package/dist/src/modules/platforms/platforms.module.js.map +1 -0
  117. package/dist/src/modules/platforms/telegram/telegram-auth.validator.d.ts +19 -0
  118. package/dist/src/modules/platforms/telegram/telegram-auth.validator.js +51 -0
  119. package/dist/src/modules/platforms/telegram/telegram-auth.validator.js.map +1 -0
  120. package/dist/src/modules/platforms/telegram/telegram-type-detector.service.d.ts +18 -0
  121. package/dist/src/modules/platforms/telegram/telegram-type-detector.service.js +47 -0
  122. package/dist/src/modules/platforms/telegram/telegram-type-detector.service.js.map +1 -0
  123. package/dist/src/modules/platforms/telegram/telegram.platform.d.ts +58 -0
  124. package/dist/src/modules/platforms/telegram/telegram.platform.js +434 -0
  125. package/dist/src/modules/platforms/telegram/telegram.platform.js.map +1 -0
  126. package/dist/src/modules/post/base-post.service.d.ts +64 -0
  127. package/dist/src/modules/post/base-post.service.js +99 -0
  128. package/dist/src/modules/post/base-post.service.js.map +1 -0
  129. package/dist/src/modules/post/dto/index.d.ts +3 -0
  130. package/dist/src/modules/post/dto/index.js +4 -0
  131. package/dist/src/modules/post/dto/index.js.map +1 -0
  132. package/dist/src/modules/post/dto/post-request.dto.d.ts +56 -0
  133. package/dist/src/modules/post/dto/post-request.dto.js +195 -0
  134. package/dist/src/modules/post/dto/post-request.dto.js.map +1 -0
  135. package/dist/src/modules/post/dto/post-response.dto.d.ts +41 -0
  136. package/dist/src/modules/post/dto/post-response.dto.js +2 -0
  137. package/dist/src/modules/post/dto/post-response.dto.js.map +1 -0
  138. package/dist/src/modules/post/dto/preview-response.dto.d.ts +33 -0
  139. package/dist/src/modules/post/dto/preview-response.dto.js +2 -0
  140. package/dist/src/modules/post/dto/preview-response.dto.js.map +1 -0
  141. package/dist/src/modules/post/idempotency.service.d.ts +95 -0
  142. package/dist/src/modules/post/idempotency.service.js +229 -0
  143. package/dist/src/modules/post/idempotency.service.js.map +1 -0
  144. package/dist/src/modules/post/post.controller.d.ts +13 -0
  145. package/dist/src/modules/post/post.controller.js +97 -0
  146. package/dist/src/modules/post/post.controller.js.map +1 -0
  147. package/dist/src/modules/post/post.module.d.ts +2 -0
  148. package/dist/src/modules/post/post.module.js +25 -0
  149. package/dist/src/modules/post/post.module.js.map +1 -0
  150. package/dist/src/modules/post/post.service.d.ts +62 -0
  151. package/dist/src/modules/post/post.service.js +325 -0
  152. package/dist/src/modules/post/post.service.js.map +1 -0
  153. package/dist/src/modules/post/preview.service.d.ts +23 -0
  154. package/dist/src/modules/post/preview.service.js +69 -0
  155. package/dist/src/modules/post/preview.service.js.map +1 -0
  156. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  157. package/package.json +102 -0
@@ -0,0 +1,18 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Module } from '@nestjs/common';
8
+ import { ShutdownService } from './shutdown.service.js';
9
+ let ShutdownModule = class ShutdownModule {
10
+ };
11
+ ShutdownModule = __decorate([
12
+ Module({
13
+ providers: [ShutdownService],
14
+ exports: [ShutdownService],
15
+ })
16
+ ], ShutdownModule);
17
+ export { ShutdownModule };
18
+ //# sourceMappingURL=shutdown.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.module.js","sourceRoot":"","sources":["../../../../src/common/services/shutdown.module.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAMjD,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,cAAc;IAJ1B,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,eAAe,CAAC;QAC5B,OAAO,EAAE,CAAC,eAAe,CAAC;KAC3B,CAAC;GACW,cAAc,CAAG"}
@@ -0,0 +1,40 @@
1
+ import { OnApplicationShutdown, OnModuleDestroy } from '@nestjs/common';
2
+ /**
3
+ * Service to manage graceful shutdown
4
+ * Tracks in-flight requests and signals shutdown state to the application
5
+ * Thread-safe implementation to prevent race conditions
6
+ */
7
+ export declare class ShutdownService implements OnApplicationShutdown, OnModuleDestroy {
8
+ private readonly logger;
9
+ private isShuttingDown;
10
+ private inFlightRequests;
11
+ private shutdownResolve?;
12
+ private operationLock;
13
+ constructor();
14
+ /**
15
+ * Check if the application is shutting down
16
+ */
17
+ get shuttingDown(): boolean;
18
+ /**
19
+ * Increment in-flight request counter atomically
20
+ */
21
+ trackRequest(): void;
22
+ /**
23
+ * Decrement in-flight request counter atomically and resolve shutdown if no requests remain
24
+ */
25
+ untrackRequest(): void;
26
+ /**
27
+ * Get the current count of in-flight requests
28
+ */
29
+ getInFlightRequestsCount(): number;
30
+ /**
31
+ * Called by NestJS when shutdown signal is received
32
+ * Waits for all in-flight requests to complete with timeout
33
+ */
34
+ onApplicationShutdown(signal?: string): Promise<void>;
35
+ /**
36
+ * Called by NestJS when module is being destroyed
37
+ * Cleanup internal state
38
+ */
39
+ onModuleDestroy(): void;
40
+ }
@@ -0,0 +1,122 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var ShutdownService_1;
11
+ import { Injectable, Logger } from '@nestjs/common';
12
+ import { GRACEFUL_SHUTDOWN_TIMEOUT_MS } from '../../app.constants.js';
13
+ /**
14
+ * Service to manage graceful shutdown
15
+ * Tracks in-flight requests and signals shutdown state to the application
16
+ * Thread-safe implementation to prevent race conditions
17
+ */
18
+ let ShutdownService = ShutdownService_1 = class ShutdownService {
19
+ logger = new Logger(ShutdownService_1.name);
20
+ isShuttingDown = false;
21
+ inFlightRequests = 0;
22
+ shutdownResolve;
23
+ operationLock = false;
24
+ constructor() { }
25
+ /**
26
+ * Check if the application is shutting down
27
+ */
28
+ get shuttingDown() {
29
+ return this.isShuttingDown;
30
+ }
31
+ /**
32
+ * Increment in-flight request counter atomically
33
+ */
34
+ trackRequest() {
35
+ // Wait for any ongoing operation to complete
36
+ while (this.operationLock) {
37
+ // Busy wait (acceptable for very short operations)
38
+ }
39
+ this.operationLock = true;
40
+ try {
41
+ this.inFlightRequests++;
42
+ this.logger.debug(`Request tracked. In-flight requests: ${this.inFlightRequests}`, 'ShutdownService');
43
+ }
44
+ finally {
45
+ this.operationLock = false;
46
+ }
47
+ }
48
+ /**
49
+ * Decrement in-flight request counter atomically and resolve shutdown if no requests remain
50
+ */
51
+ untrackRequest() {
52
+ // Wait for any ongoing operation to complete
53
+ while (this.operationLock) {
54
+ // Busy wait (acceptable for very short operations)
55
+ }
56
+ this.operationLock = true;
57
+ try {
58
+ this.inFlightRequests--;
59
+ this.logger.debug(`Request untracked. In-flight requests: ${this.inFlightRequests}`, 'ShutdownService');
60
+ // Check if we should resolve shutdown
61
+ if (this.isShuttingDown && this.inFlightRequests <= 0 && this.shutdownResolve) {
62
+ this.logger.log('All in-flight requests completed during shutdown', 'ShutdownService');
63
+ this.shutdownResolve();
64
+ this.shutdownResolve = undefined;
65
+ }
66
+ }
67
+ finally {
68
+ this.operationLock = false;
69
+ }
70
+ }
71
+ /**
72
+ * Get the current count of in-flight requests
73
+ */
74
+ getInFlightRequestsCount() {
75
+ return this.inFlightRequests;
76
+ }
77
+ /**
78
+ * Called by NestJS when shutdown signal is received
79
+ * Waits for all in-flight requests to complete with timeout
80
+ */
81
+ async onApplicationShutdown(signal) {
82
+ this.logger.log(`Received shutdown signal: ${signal ?? 'unknown'}. In-flight requests: ${this.inFlightRequests}`, 'ShutdownService');
83
+ this.isShuttingDown = true;
84
+ if (this.inFlightRequests > 0) {
85
+ this.logger.log(`Waiting for ${this.inFlightRequests} in-flight requests to complete...`, 'ShutdownService');
86
+ const startTime = Date.now();
87
+ // Wait for requests to complete with timeout
88
+ await Promise.race([
89
+ new Promise(resolve => {
90
+ this.shutdownResolve = resolve;
91
+ }),
92
+ new Promise(resolve => {
93
+ setTimeout(() => {
94
+ this.logger.warn(`Shutdown timeout reached. Remaining in-flight requests: ${this.inFlightRequests}`, 'ShutdownService');
95
+ resolve();
96
+ }, GRACEFUL_SHUTDOWN_TIMEOUT_MS);
97
+ }),
98
+ ]);
99
+ const duration = Date.now() - startTime;
100
+ this.logger.log(`Shutdown wait completed in ${duration}ms. Remaining requests: ${this.inFlightRequests}`, 'ShutdownService');
101
+ }
102
+ else {
103
+ this.logger.log('No in-flight requests, shutting down immediately', 'ShutdownService');
104
+ }
105
+ }
106
+ /**
107
+ * Called by NestJS when module is being destroyed
108
+ * Cleanup internal state
109
+ */
110
+ onModuleDestroy() {
111
+ this.logger.debug('ShutdownService module destroyed', 'ShutdownService');
112
+ this.shutdownResolve = undefined;
113
+ this.inFlightRequests = 0;
114
+ this.isShuttingDown = false;
115
+ }
116
+ };
117
+ ShutdownService = ShutdownService_1 = __decorate([
118
+ Injectable(),
119
+ __metadata("design:paramtypes", [])
120
+ ], ShutdownService);
121
+ export { ShutdownService };
122
+ //# sourceMappingURL=shutdown.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shutdown.service.js","sourceRoot":"","sources":["../../../../src/common/services/shutdown.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export type { MediaInput, MediaInputObject } from './media-input.type.js';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/common/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Media type for explicit type specification in media arrays
3
+ * Used in albums to avoid auto-detection by URL extension
4
+ */
5
+ export type MediaType = 'image' | 'video' | 'audio' | 'document';
6
+ /**
7
+ * MediaInput type
8
+ * Always an object with src and optional parameters
9
+ * For single media fields (cover, video, audio, document): hasSpoiler is optional
10
+ * For media arrays: type should be specified to override auto-detection
11
+ */
12
+ export type MediaInput = MediaInputObject;
13
+ export interface MediaInputObject {
14
+ /**
15
+ * Media source (URL or Telegram file_id)
16
+ */
17
+ src: string;
18
+ /**
19
+ * Hide media with spoiler animation (for shocking content)
20
+ * Supported by Telegram Bot API 5.6+
21
+ */
22
+ hasSpoiler?: boolean;
23
+ /**
24
+ * Explicit media type specification
25
+ * For single media fields (cover, video, audio, document) this is ignored
26
+ * For media[] arrays this overrides auto-detection by URL extension
27
+ */
28
+ type?: MediaType;
29
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=media-input.type.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-input.type.js","sourceRoot":"","sources":["../../../../src/common/types/media-input.type.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { ValidationOptions, ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
2
+ /** Absolute maximum body length limit in characters (cannot be exceeded) */
3
+ export declare const MAX_BODY_LIMIT = 500000;
4
+ /**
5
+ * Validator constraint for body field with dynamic max length
6
+ * Uses maxBody from request (capped at MAX_BODY_LIMIT)
7
+ */
8
+ export declare class IsValidBodyLengthConstraint implements ValidatorConstraintInterface {
9
+ /**
10
+ * Validates body length against maxBody or MAX_BODY_LIMIT
11
+ * @param value - Body string to validate
12
+ * @param args - Validation arguments containing the object
13
+ * @returns True if valid, false otherwise
14
+ */
15
+ validate(value: any, args: ValidationArguments): boolean;
16
+ defaultMessage(args: ValidationArguments): string;
17
+ }
18
+ /**
19
+ * Decorator factory for body length validation
20
+ * Validates body against maxBody parameter or default max length
21
+ * @param validationOptions - Optional validation options
22
+ * @returns Property decorator
23
+ */
24
+ export declare function IsValidBodyLength(validationOptions?: ValidationOptions): (object: Object, propertyName: string) => void;
@@ -0,0 +1,57 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { registerDecorator, ValidatorConstraint, } from 'class-validator';
8
+ /** Absolute maximum body length limit in characters (cannot be exceeded) */
9
+ export const MAX_BODY_LIMIT = 500_000;
10
+ /**
11
+ * Validator constraint for body field with dynamic max length
12
+ * Uses maxBody from request (capped at MAX_BODY_LIMIT)
13
+ */
14
+ let IsValidBodyLengthConstraint = class IsValidBodyLengthConstraint {
15
+ /**
16
+ * Validates body length against maxBody or MAX_BODY_LIMIT
17
+ * @param value - Body string to validate
18
+ * @param args - Validation arguments containing the object
19
+ * @returns True if valid, false otherwise
20
+ */
21
+ validate(value, args) {
22
+ if (typeof value !== 'string') {
23
+ return false;
24
+ }
25
+ const obj = args.object;
26
+ // Use maxBody from request if provided, otherwise use absolute limit
27
+ const maxLength = Math.min(obj.maxBody || MAX_BODY_LIMIT, MAX_BODY_LIMIT);
28
+ return value.length <= maxLength;
29
+ }
30
+ defaultMessage(args) {
31
+ const obj = args.object;
32
+ const maxLength = Math.min(obj.maxBody || MAX_BODY_LIMIT, MAX_BODY_LIMIT);
33
+ return `Body length must not exceed ${maxLength} characters`;
34
+ }
35
+ };
36
+ IsValidBodyLengthConstraint = __decorate([
37
+ ValidatorConstraint({ name: 'isValidBodyLength', async: false })
38
+ ], IsValidBodyLengthConstraint);
39
+ export { IsValidBodyLengthConstraint };
40
+ /**
41
+ * Decorator factory for body length validation
42
+ * Validates body against maxBody parameter or default max length
43
+ * @param validationOptions - Optional validation options
44
+ * @returns Property decorator
45
+ */
46
+ export function IsValidBodyLength(validationOptions) {
47
+ return function (object, propertyName) {
48
+ registerDecorator({
49
+ target: object.constructor,
50
+ propertyName: propertyName,
51
+ options: validationOptions,
52
+ constraints: [],
53
+ validator: IsValidBodyLengthConstraint,
54
+ });
55
+ };
56
+ }
57
+ //# sourceMappingURL=body-length.validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"body-length.validator.js","sourceRoot":"","sources":["../../../../src/common/validators/body-length.validator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACL,iBAAiB,EAGjB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC;;;GAGG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,KAAU,EAAE,IAAyB;QAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,MAAa,CAAC;QAC/B,qEAAqE;QACrE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,cAAc,EAAE,cAAc,CAAC,CAAC;QAE1E,OAAO,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC;IACnC,CAAC;IAED,cAAc,CAAC,IAAyB;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAa,CAAC;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,cAAc,EAAE,cAAc,CAAC,CAAC;QAC1E,OAAO,+BAA+B,SAAS,aAAa,CAAC;IAC/D,CAAC;CACF,CAAA;AAxBY,2BAA2B;IADvC,mBAAmB,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;GACpD,2BAA2B,CAwBvC;;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,iBAAqC;IACrE,OAAO,UAAU,MAAc,EAAE,YAAoB;QACnD,iBAAiB,CAAC;YAChB,MAAM,EAAE,MAAM,CAAC,WAAW;YAC1B,YAAY,EAAE,YAAY;YAC1B,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,EAAE;YACf,SAAS,EAAE,2BAA2B;SACvC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { ValidationOptions, ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
2
+ /**
3
+ * Validator constraint for channelId field
4
+ * Validates that channelId is either a string or a number
5
+ * Allows formats like:
6
+ * - String: "@mychannel", "-100123456789", "123456789"
7
+ * - Number: 123456789, -100123456789
8
+ */
9
+ export declare class IsChannelIdConstraint implements ValidatorConstraintInterface {
10
+ validate(value: any, args: ValidationArguments): boolean;
11
+ defaultMessage(args: ValidationArguments): string;
12
+ }
13
+ /**
14
+ * Decorator factory for channelId validation
15
+ * Use on DTO properties that accept channelId
16
+ * @param validationOptions - Optional validation options
17
+ * @returns Property decorator
18
+ */
19
+ export declare function IsChannelId(validationOptions?: ValidationOptions): (object: object, propertyName: string) => void;
@@ -0,0 +1,58 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { registerDecorator, ValidatorConstraint, } from 'class-validator';
8
+ /**
9
+ * Validator constraint for channelId field
10
+ * Validates that channelId is either a string or a number
11
+ * Allows formats like:
12
+ * - String: "@mychannel", "-100123456789", "123456789"
13
+ * - Number: 123456789, -100123456789
14
+ */
15
+ let IsChannelIdConstraint = class IsChannelIdConstraint {
16
+ validate(value, args) {
17
+ // Allow undefined/null for optional fields
18
+ if (value === undefined || value === null) {
19
+ return true;
20
+ }
21
+ // Check if it's a string or number
22
+ if (typeof value === 'string') {
23
+ // String must not be empty
24
+ return value.trim().length > 0;
25
+ }
26
+ if (typeof value === 'number') {
27
+ // Number must be a valid integer
28
+ return Number.isInteger(value);
29
+ }
30
+ return false;
31
+ }
32
+ defaultMessage(args) {
33
+ return 'channelId must be a non-empty string or an integer number';
34
+ }
35
+ };
36
+ IsChannelIdConstraint = __decorate([
37
+ ValidatorConstraint({ name: 'isChannelId', async: false })
38
+ ], IsChannelIdConstraint);
39
+ export { IsChannelIdConstraint };
40
+ /**
41
+ * Decorator factory for channelId validation
42
+ * Use on DTO properties that accept channelId
43
+ * @param validationOptions - Optional validation options
44
+ * @returns Property decorator
45
+ */
46
+ export function IsChannelId(validationOptions) {
47
+ return function (object, propertyName) {
48
+ registerDecorator({
49
+ name: 'isChannelId',
50
+ target: object.constructor,
51
+ propertyName: propertyName,
52
+ options: validationOptions,
53
+ constraints: [],
54
+ validator: IsChannelIdConstraint,
55
+ });
56
+ };
57
+ }
58
+ //# sourceMappingURL=channel-id.validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-id.validator.js","sourceRoot":"","sources":["../../../../src/common/validators/channel-id.validator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACH,iBAAiB,EAGjB,mBAAmB,GAEtB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;GAMG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAC9B,QAAQ,CAAC,KAAU,EAAE,IAAyB;QAC1C,2CAA2C;QAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,mCAAmC;QACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,2BAA2B;YAC3B,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,iCAAiC;YACjC,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,cAAc,CAAC,IAAyB;QACpC,OAAO,2DAA2D,CAAC;IACvE,CAAC;CACJ,CAAA;AAxBY,qBAAqB;IADjC,mBAAmB,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;GAC9C,qBAAqB,CAwBjC;;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,iBAAqC;IAC7D,OAAO,UAAU,MAAc,EAAE,YAAoB;QACjD,iBAAiB,CAAC;YACd,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,MAAM,CAAC,WAAW;YAC1B,YAAY,EAAE,YAAY;YAC1B,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,EAAE;YACf,SAAS,EAAE,qBAAqB;SACnC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { ValidationOptions, ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
2
+ /**
3
+ * Validator constraint for ensuring post has content
4
+ * Checks that either body or at least one media field is provided
5
+ */
6
+ export declare class HasContentConstraint implements ValidatorConstraintInterface {
7
+ /**
8
+ * Validates that post has either body or media content
9
+ * @param _value - Not used (class-level validator)
10
+ * @param args - Validation arguments containing the object
11
+ * @returns True if valid, false otherwise
12
+ */
13
+ validate(_value: any, args: ValidationArguments): any;
14
+ defaultMessage(_args: ValidationArguments): string;
15
+ }
16
+ /**
17
+ * Decorator factory for content validation
18
+ * Validates that post has either body or media content
19
+ * This is a class-level decorator
20
+ * @param validationOptions - Optional validation options
21
+ * @returns Class decorator
22
+ */
23
+ export declare function HasContent(validationOptions?: ValidationOptions): (object: Function) => void;
@@ -0,0 +1,57 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { registerDecorator, ValidatorConstraint, } from 'class-validator';
8
+ /**
9
+ * Validator constraint for ensuring post has content
10
+ * Checks that either body or at least one media field is provided
11
+ */
12
+ let HasContentConstraint = class HasContentConstraint {
13
+ /**
14
+ * Validates that post has either body or media content
15
+ * @param _value - Not used (class-level validator)
16
+ * @param args - Validation arguments containing the object
17
+ * @returns True if valid, false otherwise
18
+ */
19
+ validate(_value, args) {
20
+ const obj = args.object;
21
+ // Check if body is a non-empty string
22
+ const hasBody = typeof obj.body === 'string' && obj.body.trim().length > 0;
23
+ // Check if at least one media field is provided (ignore falsy values like false, null, undefined, '')
24
+ const hasMedia = (obj.cover && typeof obj.cover === 'object') ||
25
+ (obj.video && typeof obj.video === 'object') ||
26
+ (obj.audio && typeof obj.audio === 'object') ||
27
+ (obj.document && typeof obj.document === 'object') ||
28
+ (Array.isArray(obj.media) && obj.media.length > 0);
29
+ return hasBody || hasMedia;
30
+ }
31
+ defaultMessage(_args) {
32
+ return 'Post must have either body text or at least one media field (cover, video, audio, document, or media)';
33
+ }
34
+ };
35
+ HasContentConstraint = __decorate([
36
+ ValidatorConstraint({ name: 'hasContent', async: false })
37
+ ], HasContentConstraint);
38
+ export { HasContentConstraint };
39
+ /**
40
+ * Decorator factory for content validation
41
+ * Validates that post has either body or media content
42
+ * This is a class-level decorator
43
+ * @param validationOptions - Optional validation options
44
+ * @returns Class decorator
45
+ */
46
+ export function HasContent(validationOptions) {
47
+ return function (object) {
48
+ registerDecorator({
49
+ target: object,
50
+ propertyName: '',
51
+ options: validationOptions,
52
+ constraints: [],
53
+ validator: HasContentConstraint,
54
+ });
55
+ };
56
+ }
57
+ //# sourceMappingURL=has-content.validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-content.validator.js","sourceRoot":"","sources":["../../../../src/common/validators/has-content.validator.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACH,iBAAiB,EAGjB,mBAAmB,GAEtB,MAAM,iBAAiB,CAAC;AAEzB;;;GAGG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC7B;;;;;OAKG;IACH,QAAQ,CAAC,MAAW,EAAE,IAAyB;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,MAAa,CAAC;QAE/B,sCAAsC;QACtC,MAAM,OAAO,GAAG,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;QAE3E,sGAAsG;QACtG,MAAM,QAAQ,GACV,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC5C,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC5C,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC;YAC5C,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,CAAC;YAClD,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEvD,OAAO,OAAO,IAAI,QAAQ,CAAC;IAC/B,CAAC;IAED,cAAc,CAAC,KAA0B;QACrC,OAAO,uGAAuG,CAAC;IACnH,CAAC;CACJ,CAAA;AA3BY,oBAAoB;IADhC,mBAAmB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;GAC7C,oBAAoB,CA2BhC;;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,iBAAqC;IAC5D,OAAO,UAAU,MAAgB;QAC7B,iBAAiB,CAAC;YACd,MAAM,EAAE,MAAM;YACd,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,iBAAiB;YAC1B,WAAW,EAAE,EAAE;YACf,SAAS,EAAE,oBAAoB;SAClC,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { ValidationOptions, ValidationArguments, ValidatorConstraintInterface } from 'class-validator';
2
+ /**
3
+ * Validator constraint for MediaInput type
4
+ * Validates that a value is an object with src property
5
+ */
6
+ export declare class IsMediaInputConstraint implements ValidatorConstraintInterface {
7
+ /**
8
+ * Validates MediaInput value
9
+ * Accepts only an object with src property (max 500 characters)
10
+ * @param value - Value to validate
11
+ * @param args - Validation arguments
12
+ * @returns True if valid, false otherwise
13
+ */
14
+ validate(value: any, args: ValidationArguments): boolean;
15
+ defaultMessage(args: ValidationArguments): string;
16
+ }
17
+ /**
18
+ * Decorator factory for MediaInput validation
19
+ * Use on DTO properties that accept MediaInput type
20
+ * @param validationOptions - Optional validation options
21
+ * @returns Property decorator
22
+ */
23
+ export declare function IsMediaInput(validationOptions?: ValidationOptions): (object: Object, propertyName: string) => void;
24
+ /**
25
+ * Validator constraint for MediaInput array type
26
+ * Validates that each item in the array is a valid MediaInput
27
+ */
28
+ export declare class IsMediaInputArrayConstraint implements ValidatorConstraintInterface {
29
+ /**
30
+ * Validates array of MediaInput values
31
+ * @param value - Array to validate
32
+ * @param args - Validation arguments
33
+ * @returns True if all items are valid MediaInput, false otherwise
34
+ */
35
+ validate(value: any, args: ValidationArguments): boolean;
36
+ defaultMessage(args: ValidationArguments): string;
37
+ }
38
+ /**
39
+ * Decorator factory for MediaInput array validation
40
+ * Use on DTO properties that accept MediaInput[] type
41
+ * @param validationOptions - Optional validation options
42
+ * @returns Property decorator
43
+ */
44
+ export declare function IsMediaInputArray(validationOptions?: ValidationOptions): (object: Object, propertyName: string) => void;
@@ -0,0 +1,112 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { registerDecorator, ValidatorConstraint, } from 'class-validator';
8
+ /** Maximum length for URL and fileId strings */
9
+ const MAX_MEDIA_STRING_LENGTH = 500;
10
+ /**
11
+ * Validator constraint for MediaInput type
12
+ * Validates that a value is an object with src property
13
+ */
14
+ let IsMediaInputConstraint = class IsMediaInputConstraint {
15
+ /**
16
+ * Validates MediaInput value
17
+ * Accepts only an object with src property (max 500 characters)
18
+ * @param value - Value to validate
19
+ * @param args - Validation arguments
20
+ * @returns True if valid, false otherwise
21
+ */
22
+ validate(value, args) {
23
+ // Optional field - allow null/undefined/false
24
+ if (value === null || value === undefined || value === false) {
25
+ return true;
26
+ }
27
+ // Must be an object with src property
28
+ if (typeof value === 'object' && value !== null) {
29
+ const hasSrc = typeof value.src === 'string';
30
+ const hasSpoiler = value.hasSpoiler === undefined || typeof value.hasSpoiler === 'boolean';
31
+ const hasType = value.type === undefined || typeof value.type === 'string';
32
+ // Validate string length
33
+ if (hasSrc && value.src.length > MAX_MEDIA_STRING_LENGTH) {
34
+ return false;
35
+ }
36
+ // Must have src, and hasSpoiler/type must be correct types if present
37
+ return hasSrc && value.src.length > 0 && hasSpoiler && hasType;
38
+ }
39
+ return false;
40
+ }
41
+ defaultMessage(args) {
42
+ return `MediaInput must be an object with src (max ${MAX_MEDIA_STRING_LENGTH} characters), optional hasSpoiler boolean, and optional type string`;
43
+ }
44
+ };
45
+ IsMediaInputConstraint = __decorate([
46
+ ValidatorConstraint({ name: 'isMediaInput', async: false })
47
+ ], IsMediaInputConstraint);
48
+ export { IsMediaInputConstraint };
49
+ /**
50
+ * Decorator factory for MediaInput validation
51
+ * Use on DTO properties that accept MediaInput type
52
+ * @param validationOptions - Optional validation options
53
+ * @returns Property decorator
54
+ */
55
+ export function IsMediaInput(validationOptions) {
56
+ return function (object, propertyName) {
57
+ registerDecorator({
58
+ target: object.constructor,
59
+ propertyName: propertyName,
60
+ options: validationOptions,
61
+ constraints: [],
62
+ validator: IsMediaInputConstraint,
63
+ });
64
+ };
65
+ }
66
+ /**
67
+ * Validator constraint for MediaInput array type
68
+ * Validates that each item in the array is a valid MediaInput
69
+ */
70
+ let IsMediaInputArrayConstraint = class IsMediaInputArrayConstraint {
71
+ /**
72
+ * Validates array of MediaInput values
73
+ * @param value - Array to validate
74
+ * @param args - Validation arguments
75
+ * @returns True if all items are valid MediaInput, false otherwise
76
+ */
77
+ validate(value, args) {
78
+ if (!value) {
79
+ return true; // Optional field
80
+ }
81
+ if (!Array.isArray(value)) {
82
+ return false;
83
+ }
84
+ const validator = new IsMediaInputConstraint();
85
+ return value.every(item => validator.validate(item, args));
86
+ }
87
+ defaultMessage(args) {
88
+ return `Property "media" must be an array of objects. Example: [{"src": "https://example.com/image.jpg", "type": "image"}]. Each item must have src (max ${MAX_MEDIA_STRING_LENGTH} characters), optional hasSpoiler boolean, and optional type string`;
89
+ }
90
+ };
91
+ IsMediaInputArrayConstraint = __decorate([
92
+ ValidatorConstraint({ name: 'isMediaInputArray', async: false })
93
+ ], IsMediaInputArrayConstraint);
94
+ export { IsMediaInputArrayConstraint };
95
+ /**
96
+ * Decorator factory for MediaInput array validation
97
+ * Use on DTO properties that accept MediaInput[] type
98
+ * @param validationOptions - Optional validation options
99
+ * @returns Property decorator
100
+ */
101
+ export function IsMediaInputArray(validationOptions) {
102
+ return function (object, propertyName) {
103
+ registerDecorator({
104
+ target: object.constructor,
105
+ propertyName: propertyName,
106
+ options: validationOptions,
107
+ constraints: [],
108
+ validator: IsMediaInputArrayConstraint,
109
+ });
110
+ };
111
+ }
112
+ //# sourceMappingURL=media-input.validator.js.map