@wabot-dev/framework 0.1.0-beta.4 → 0.1.0-beta.40

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 (154) hide show
  1. package/dist/src/addon/async/pg/PgJobRepository.js +26 -0
  2. package/dist/src/addon/chat-bot/anthropic/AnthropicChatAdapter.js +128 -0
  3. package/dist/src/addon/chat-bot/deepseek/DeepSeekChatAdapter.js +137 -0
  4. package/dist/src/addon/chat-bot/google/GoogleChatAdapter.js +120 -0
  5. package/dist/src/addon/chat-bot/openia/OpenaiChatAdapter.js +111 -0
  6. package/dist/src/{pre-made/repository/chat → addon/chat-bot}/pg/PgChatMemory.js +5 -4
  7. package/dist/src/{pre-made/repository/chat → addon/chat-bot}/pg/PgChatRepository.js +5 -5
  8. package/dist/src/{pre-made/repository/chat → addon/chat-bot}/ram/RamChatRepository.js +2 -2
  9. package/dist/src/addon/chat-controller/cmd/@cmd.js +22 -0
  10. package/dist/src/{channels → addon/chat-controller}/cmd/CmdChannel.js +4 -26
  11. package/dist/src/{channels → addon/chat-controller}/socket/@socket.js +8 -4
  12. package/dist/src/{channels → addon/chat-controller}/socket/SocketChannel.js +5 -23
  13. package/dist/src/{channels → addon/chat-controller}/socket/SocketChannelConfig.js +1 -1
  14. package/dist/src/{channels → addon/chat-controller}/telegram/@telegram.js +8 -4
  15. package/dist/src/{channels → addon/chat-controller}/telegram/TelegramChannel.js +4 -22
  16. package/dist/src/{channels → addon/chat-controller}/whatsapp/@whatsapp.js +8 -4
  17. package/dist/src/{channels → addon/chat-controller}/whatsapp/EnvWhatsAppRepository.js +3 -3
  18. package/dist/src/{channels → addon/chat-controller}/whatsapp/PgWhatsAppRepository.js +1 -1
  19. package/dist/src/{channels/wabot → addon/chat-controller/whatsapp}/WabotDevConnection.js +2 -2
  20. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsApp.js +2 -4
  21. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppChannel.js +6 -18
  22. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppReceiver.js +4 -7
  23. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppReceiverByDevConnection.js +4 -10
  24. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppReceiverByWebHook.js +6 -12
  25. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppSender.js +39 -10
  26. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppSenderByCloudApi.js +10 -13
  27. package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppSenderByDevConnection.js +13 -15
  28. package/dist/src/addon/mindset/html/HtmlModule.js +70 -0
  29. package/dist/src/addon/money/MoneyDto.js +22 -0
  30. package/dist/src/{repository → addon/repository}/pg/PgCrudRepository.js +23 -2
  31. package/dist/src/{repository → addon/repository}/pg/PgRepositoryBase.js +2 -2
  32. package/dist/src/addon/rest-controller/jwt/@jwtGuard.js +17 -0
  33. package/dist/src/addon/rest-controller/jwt/Jwt.js +31 -0
  34. package/dist/src/addon/rest-controller/jwt/JwtAccessAndRefreshTokenDto.js +20 -0
  35. package/dist/src/addon/rest-controller/jwt/JwtConfig.js +28 -0
  36. package/dist/src/addon/rest-controller/jwt/JwtGuardMiddleware.js +45 -0
  37. package/dist/src/addon/rest-controller/jwt/JwtRefreshToken.js +9 -0
  38. package/dist/src/addon/rest-controller/jwt/JwtRefreshTokenRepository.js +21 -0
  39. package/dist/src/addon/rest-controller/jwt/JwtSigner.js +48 -0
  40. package/dist/src/addon/rest-controller/jwt/JwtTokenDto.js +22 -0
  41. package/dist/src/addon/validation/is-boolean/@isBoolean.js +17 -0
  42. package/dist/src/addon/validation/is-boolean/validateIsBoolean.js +12 -0
  43. package/dist/src/addon/validation/is-date/@isDate.js +17 -0
  44. package/dist/src/addon/validation/is-date/validateIsDate.js +16 -0
  45. package/dist/src/addon/validation/is-not-empty/@isNotEmpty.js +17 -0
  46. package/dist/src/addon/validation/is-not-empty/validateIsNotEmpty.js +12 -0
  47. package/dist/src/addon/validation/is-number/@isNumber.js +17 -0
  48. package/dist/src/addon/validation/is-number/validateIsNumber.js +12 -0
  49. package/dist/src/addon/validation/is-present/@isPresent.js +17 -0
  50. package/dist/src/addon/validation/is-present/validateIsPresent.js +12 -0
  51. package/dist/src/addon/validation/is-string/@isString.js +17 -0
  52. package/dist/src/addon/validation/is-string/validateIsString.js +12 -0
  53. package/dist/src/addon/validation/max/@max.js +18 -0
  54. package/dist/src/addon/validation/max/validateMax.js +17 -0
  55. package/dist/src/addon/validation/min/@min.js +18 -0
  56. package/dist/src/addon/validation/min/validateMin.js +17 -0
  57. package/dist/src/core/auth/Auth.js +24 -0
  58. package/dist/src/core/{Persistent.js → entity/Entity.js} +24 -9
  59. package/dist/src/core/env/Env.js +39 -0
  60. package/dist/src/core/error/CustomError.js +15 -0
  61. package/dist/src/core/injection/index.js +4 -0
  62. package/dist/src/core/mapper/Mapper.js +42 -0
  63. package/dist/src/core/random/Random.js +37 -0
  64. package/dist/src/core/storable/Storable.js +8 -0
  65. package/dist/src/core/validation/metadata/@isArray.js +18 -0
  66. package/dist/src/core/validation/metadata/@isModel.js +18 -0
  67. package/dist/src/core/validation/metadata/@isOptional.js +17 -0
  68. package/dist/src/core/validation/metadata/ValidationMetadataStore.js +98 -0
  69. package/dist/src/core/validation/modelInfo.js +9 -0
  70. package/dist/src/core/validation/validate.js +11 -0
  71. package/dist/src/core/validation/validators/validateArray.js +51 -0
  72. package/dist/src/core/validation/validators/validateIsOptional.js +5 -0
  73. package/dist/src/core/validation/validators/validateModel.js +36 -0
  74. package/dist/src/feature/async/@command.js +11 -0
  75. package/dist/src/feature/async/@commandHandler.js +12 -0
  76. package/dist/src/feature/async/Async.js +38 -0
  77. package/dist/src/feature/async/Command.js +9 -0
  78. package/dist/src/feature/async/CommandMetadataStore.js +38 -0
  79. package/dist/src/feature/async/Job.js +24 -0
  80. package/dist/src/feature/async/JobRepository.js +31 -0
  81. package/dist/src/feature/async/JobRunner.js +45 -0
  82. package/dist/src/feature/async/JobsEventsHub.js +24 -0
  83. package/dist/src/feature/async/runCommandHandlers.js +29 -0
  84. package/dist/src/{core/chat → feature/chat-bot}/Chat.js +2 -2
  85. package/dist/src/feature/chat-bot/ChatAdapter.js +7 -0
  86. package/dist/src/feature/chat-bot/ChatBot.js +50 -0
  87. package/dist/src/feature/chat-bot/ChatItem.js +24 -0
  88. package/dist/src/feature/chat-bot/ChatMemory.js +10 -0
  89. package/dist/src/{core/chat/repository/IChatRepository.js → feature/chat-bot/ChatRepository.js} +2 -8
  90. package/dist/src/feature/chat-bot/IChatItem.js +3 -0
  91. package/dist/src/{chatbot → feature/chat-bot}/metadata/@chatBot.js +1 -1
  92. package/dist/src/{chatbot → feature/chat-bot}/metadata/ChatBotMetadataStore.js +1 -1
  93. package/dist/src/{controller/channel → feature/chat-controller}/ChatResolver.js +5 -4
  94. package/dist/src/{controller → feature/chat-controller}/metadata/ControllerMetadataStore.js +1 -1
  95. package/dist/src/{controller → feature/chat-controller}/metadata/controller/@chatController.js +1 -1
  96. package/dist/src/feature/chat-controller/runChatControllers.js +69 -0
  97. package/dist/src/{channels → feature}/express/ExpressProvider.js +2 -4
  98. package/dist/src/{channels → feature}/http/HttpServerProvider.js +2 -2
  99. package/dist/src/{mindset → feature/mindset}/MindsetOperator.js +66 -42
  100. package/dist/src/{mindset → feature/mindset}/metadata/MindsetMetadataStore.js +1 -1
  101. package/dist/src/{mindset → feature/mindset}/metadata/functions/@mindsetFunction.js +1 -1
  102. package/dist/src/{mindset → feature/mindset}/metadata/mindsets/@mindset.js +1 -1
  103. package/dist/src/{mindset → feature/mindset}/metadata/modules/@mindsetModule.js +1 -2
  104. package/dist/src/{mindset → feature/mindset}/metadata/params/@param.js +1 -1
  105. package/dist/src/feature/money/Money.js +61 -0
  106. package/dist/src/feature/rest-controller/injection-tokens.js +4 -0
  107. package/dist/src/feature/rest-controller/metadata/@get.js +19 -0
  108. package/dist/src/feature/rest-controller/metadata/@middleware.js +16 -0
  109. package/dist/src/feature/rest-controller/metadata/@post.js +19 -0
  110. package/dist/src/feature/rest-controller/metadata/@restController.js +15 -0
  111. package/dist/src/feature/rest-controller/metadata/RestControllerMetadataStore.js +50 -0
  112. package/dist/src/feature/rest-controller/runRestControllers.js +88 -0
  113. package/dist/src/{channels → feature}/socket/SocketServerProvider.js +2 -2
  114. package/dist/src/index.d.ts +848 -483
  115. package/dist/src/index.js +122 -76
  116. package/package.json +9 -3
  117. package/dist/src/ai/deepseek/DeepSeekChatBotAdapter.js +0 -106
  118. package/dist/src/ai/openia/OpenaiChatBotAdapter.js +0 -84
  119. package/dist/src/channels/cmd/@cmd.js +0 -18
  120. package/dist/src/chatbot/ChatBot.js +0 -51
  121. package/dist/src/chatbot/ChatBotAdapter.js +0 -72
  122. package/dist/src/controller/channel/UserResolver.js +0 -21
  123. package/dist/src/core/IMessageContext.js +0 -12
  124. package/dist/src/core/chat/ChatItem.js +0 -15
  125. package/dist/src/core/chat/repository/IChatMemory.js +0 -10
  126. package/dist/src/core/user/IUserRepository.js +0 -19
  127. package/dist/src/core/user/User.js +0 -26
  128. package/dist/src/env/WabotEnv.js +0 -27
  129. package/dist/src/injection/index.js +0 -4
  130. package/dist/src/mindset/metadata/params/@isOptional.js +0 -21
  131. package/dist/src/pre-made/module/authentication/AuthenticationModule.js +0 -97
  132. package/dist/src/pre-made/module/authentication/requests/SendOneTimePasswordRequest.js +0 -25
  133. package/dist/src/pre-made/module/authentication/requests/ValidateOneTimePasswordRequest.js +0 -25
  134. package/dist/src/pre-made/module/register-user/RegisterUserModule.js +0 -56
  135. package/dist/src/pre-made/module/register-user/requests/RegisterUserWithEmailRequest.js +0 -25
  136. package/dist/src/pre-made/repository/user/pg/PgUserRepository.js +0 -33
  137. package/dist/src/pre-made/repository/user/ram/RamUserRepository.js +0 -27
  138. package/dist/src/pre-made/service/EmailService.js +0 -13
  139. package/dist/src/pre-made/service/OtpService.js +0 -14
  140. package/dist/src/server/prepareChatContainer.js +0 -43
  141. package/dist/src/server/runChannel.js +0 -27
  142. package/dist/src/server/runServer.js +0 -40
  143. /package/dist/src/{pre-made/repository/chat → addon/chat-bot}/ram/RamChatMemory.js +0 -0
  144. /package/dist/src/{channels → addon/chat-controller}/telegram/TelegramChannelConfig.js +0 -0
  145. /package/dist/src/{channels/wabot → addon/chat-controller/whatsapp}/WabotDevSocketContracts.js +0 -0
  146. /package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppChannelConfig.js +0 -0
  147. /package/dist/src/{channels → addon/chat-controller}/whatsapp/WhatsAppRepository.js +0 -0
  148. /package/dist/src/{injection → core/injection}/Container.js +0 -0
  149. /package/dist/src/{logger → core/logger}/Logger.js +0 -0
  150. /package/dist/src/{mindset → feature/mindset}/IMindset.js +0 -0
  151. /package/dist/src/{mindset → feature/mindset}/metadata/functions/decoratorNames.js +0 -0
  152. /package/dist/src/{mindset → feature/mindset}/metadata/mindsets/decoratorNames.js +0 -0
  153. /package/dist/src/{mindset → feature/mindset}/metadata/modules/decoratorNames.js +0 -0
  154. /package/dist/src/{mindset → feature/mindset}/metadata/params/decoratorNames.js +0 -0
@@ -0,0 +1,39 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { singleton } from '../injection/index.js';
3
+
4
+ let Env = class Env {
5
+ envType;
6
+ constructor() {
7
+ this.envType = process.env.WABOT_ENV ?? 'development';
8
+ }
9
+ isDevelopment() {
10
+ return this.envType === 'development';
11
+ }
12
+ isProduction() {
13
+ return this.envType === 'production';
14
+ }
15
+ isTesting() {
16
+ return this.envType === 'testing';
17
+ }
18
+ requireString(varName, options) {
19
+ const value = process.env[varName] ?? options?.default;
20
+ if (!value)
21
+ throw new Error(`Env Variable ${varName} is required`);
22
+ return value;
23
+ }
24
+ requireNumber(varName, options) {
25
+ const strValue = this.requireString(varName, {
26
+ default: options?.default != null ? String(options.default) : undefined,
27
+ });
28
+ const value = Number(strValue);
29
+ if (isNaN(value))
30
+ throw new Error(`Env Variable ${varName} should have number format`);
31
+ return value;
32
+ }
33
+ };
34
+ Env = __decorate([
35
+ singleton(),
36
+ __metadata("design:paramtypes", [])
37
+ ], Env);
38
+
39
+ export { Env };
@@ -0,0 +1,15 @@
1
+ class CustomError extends Error {
2
+ humanMessage;
3
+ code;
4
+ httpCode;
5
+ info;
6
+ constructor(data) {
7
+ super(data.message, { cause: data.cause });
8
+ this.humanMessage = data.humanMessage;
9
+ this.code = data.code;
10
+ this.httpCode = data.httpCode;
11
+ this.info = data.info;
12
+ }
13
+ }
14
+
15
+ export { CustomError };
@@ -0,0 +1,4 @@
1
+ await import('reflect-metadata');
2
+ const { injectable, container, singleton, inject, scoped, Lifecycle } = await import('tsyringe');
3
+
4
+ export { Lifecycle, container, inject, injectable, scoped, singleton };
@@ -0,0 +1,42 @@
1
+ import { Storable } from '../storable/Storable.js';
2
+ import { CustomError } from '../error/CustomError.js';
3
+ import '../injection/index.js';
4
+ import '../validation/metadata/ValidationMetadataStore.js';
5
+ import { validate } from '../validation/validate.js';
6
+
7
+ function deepCopyWithStorable(obj) {
8
+ if (obj === null || typeof obj !== 'object') {
9
+ return obj;
10
+ }
11
+ if (obj instanceof Date) {
12
+ return obj.getTime();
13
+ }
14
+ if (obj instanceof Storable) {
15
+ return deepCopyWithStorable(obj['data']);
16
+ }
17
+ if (Array.isArray(obj)) {
18
+ return obj.map((item) => deepCopyWithStorable(item));
19
+ }
20
+ const copy = {};
21
+ for (const key in obj) {
22
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
23
+ copy[key] = deepCopyWithStorable(obj[key]);
24
+ }
25
+ }
26
+ return copy;
27
+ }
28
+ class Mapper {
29
+ map(data, ctor) {
30
+ const validationResult = validate(deepCopyWithStorable(data), ctor);
31
+ if (validationResult.error) {
32
+ throw new CustomError({
33
+ httpCode: 500,
34
+ message: `Cant map value to ${ctor.name}`,
35
+ info: validationResult.error,
36
+ });
37
+ }
38
+ return validationResult.value;
39
+ }
40
+ }
41
+
42
+ export { Mapper };
@@ -0,0 +1,37 @@
1
+ import { randomBytes } from 'node:crypto';
2
+
3
+ const DIGITS = '0123456789';
4
+ const CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
5
+ class Random {
6
+ static slug(name, options) {
7
+ const base = name
8
+ .toLowerCase()
9
+ .trim()
10
+ .replace(/[\s\_]+/g, '-') // spaces/underscores to hyphens
11
+ .replace(/[^a-z0-9\-]/g, '') // remove non-alphanumeric except hyphens
12
+ .replace(/\-+/g, '-') // collapse multiple hyphens
13
+ .replace(/^\-+|\-+$/g, ''); // trim hyphens from ends
14
+ const random = this.string(options.randomLength);
15
+ return `${base}-${random}`;
16
+ }
17
+ static string(length) {
18
+ const bytes = randomBytes(length);
19
+ let result = '';
20
+ for (let i = 0; i < length; i++) {
21
+ const index = bytes[i] % CHARSET.length;
22
+ result += CHARSET[index];
23
+ }
24
+ return result;
25
+ }
26
+ static numberCode(length) {
27
+ const bytes = randomBytes(length);
28
+ let result = '';
29
+ for (let i = 0; i < length; i++) {
30
+ const index = bytes[i] % 10; // 0–9
31
+ result += DIGITS[index];
32
+ }
33
+ return result;
34
+ }
35
+ }
36
+
37
+ export { Random };
@@ -0,0 +1,8 @@
1
+ class Storable {
2
+ data;
3
+ constructor(data) {
4
+ this.data = data;
5
+ }
6
+ }
7
+
8
+ export { Storable };
@@ -0,0 +1,18 @@
1
+ import { container } from '../../injection/index.js';
2
+ import { validateArray } from '../validators/validateArray.js';
3
+ import { ValidationMetadataStore } from './ValidationMetadataStore.js';
4
+
5
+ function isArray(options) {
6
+ return function (target, propertyKey) {
7
+ const propertyName = propertyKey.toString();
8
+ const store = container.resolve(ValidationMetadataStore);
9
+ store.saveValidatorMetadata({
10
+ modelConstructor: target.constructor,
11
+ propertyName,
12
+ validator: validateArray,
13
+ validatorOptions: options,
14
+ });
15
+ };
16
+ }
17
+
18
+ export { isArray };
@@ -0,0 +1,18 @@
1
+ import { container } from '../../injection/index.js';
2
+ import { validateModel } from '../validators/validateModel.js';
3
+ import { ValidationMetadataStore } from './ValidationMetadataStore.js';
4
+
5
+ function isModel(model) {
6
+ return function (target, propertyKey) {
7
+ const propertyName = propertyKey.toString();
8
+ const store = container.resolve(ValidationMetadataStore);
9
+ store.saveValidatorMetadata({
10
+ modelConstructor: target.constructor,
11
+ propertyName,
12
+ validator: validateModel,
13
+ validatorOptions: store.getModelValidatorsInfo(model),
14
+ });
15
+ };
16
+ }
17
+
18
+ export { isModel };
@@ -0,0 +1,17 @@
1
+ import { container } from '../../injection/index.js';
2
+ import { ValidationMetadataStore } from './ValidationMetadataStore.js';
3
+ import { _IS_OPTIONAL_DUMMY_VALIDATOR_ } from '../validators/validateIsOptional.js';
4
+
5
+ function isOptional() {
6
+ return function (target, propertyKey) {
7
+ const propertyName = propertyKey.toString();
8
+ const store = container.resolve(ValidationMetadataStore);
9
+ store.saveValidatorMetadata({
10
+ modelConstructor: target.constructor,
11
+ propertyName,
12
+ validator: _IS_OPTIONAL_DUMMY_VALIDATOR_,
13
+ });
14
+ };
15
+ }
16
+
17
+ export { isOptional };
@@ -0,0 +1,98 @@
1
+ import { __decorate } from 'tslib';
2
+ import { singleton } from '../../injection/index.js';
3
+ import { _IS_OPTIONAL_DUMMY_VALIDATOR_ } from '../validators/validateIsOptional.js';
4
+ import { validateArray } from '../validators/validateArray.js';
5
+
6
+ function getClassHierarchy(cls) {
7
+ const classes = [];
8
+ let proto = Object.getPrototypeOf(cls.prototype);
9
+ while (proto && proto.constructor !== Object) {
10
+ classes.push(proto.constructor);
11
+ proto = Object.getPrototypeOf(proto);
12
+ }
13
+ return classes;
14
+ }
15
+ let ValidationMetadataStore = class ValidationMetadataStore {
16
+ validators = new Map();
17
+ saveValidatorMetadata(validatorMetadata) {
18
+ let modelValidators = this.validators.get(validatorMetadata.modelConstructor);
19
+ if (!modelValidators) {
20
+ this.validators.set(validatorMetadata.modelConstructor, (modelValidators = new Map()));
21
+ }
22
+ let propertyValidators = modelValidators.get(validatorMetadata.propertyName);
23
+ if (!propertyValidators) {
24
+ propertyValidators = [];
25
+ modelValidators.set(validatorMetadata.propertyName, propertyValidators);
26
+ }
27
+ propertyValidators.unshift(validatorMetadata);
28
+ const arrayValidatorMetadata = propertyValidators.find((x) => x.validator === validateArray);
29
+ if (!arrayValidatorMetadata) {
30
+ return;
31
+ }
32
+ if (!arrayValidatorMetadata.validatorOptions) {
33
+ arrayValidatorMetadata.validatorOptions = {};
34
+ }
35
+ const arrayValidatorOptions = arrayValidatorMetadata.validatorOptions;
36
+ if (!arrayValidatorOptions.itemsValidator) {
37
+ arrayValidatorOptions.itemsValidator = [];
38
+ }
39
+ const removeValidatorsMetadata = [];
40
+ for (const validatorMetadata of propertyValidators) {
41
+ if (validatorMetadata.validator === validateArray ||
42
+ validatorMetadata.validator === _IS_OPTIONAL_DUMMY_VALIDATOR_) {
43
+ continue;
44
+ }
45
+ arrayValidatorOptions.itemsValidator.push({
46
+ options: validatorMetadata.validatorOptions,
47
+ validator: validatorMetadata.validator,
48
+ });
49
+ removeValidatorsMetadata.push(validatorMetadata);
50
+ }
51
+ for (const toRemove of removeValidatorsMetadata) {
52
+ const indexToRemove = propertyValidators.indexOf(toRemove);
53
+ propertyValidators.splice(indexToRemove, 1);
54
+ }
55
+ }
56
+ getModelValidatorsInfo(modelConstructor) {
57
+ const constructors = getClassHierarchy(modelConstructor);
58
+ constructors.unshift(modelConstructor);
59
+ const modelValidators = {
60
+ modelConstructor: modelConstructor,
61
+ properties: Object.assign({}, ...constructors.map((x) => this.getConstructorPropertiesValidatorsInfo(x))),
62
+ };
63
+ return modelValidators;
64
+ }
65
+ getConstructorPropertiesValidatorsInfo(modelConstructor) {
66
+ const properties = {};
67
+ [...(this.validators.get(modelConstructor)?.values() ?? [])].forEach((propertyValidatorsMetadata) => {
68
+ const propertyName = propertyValidatorsMetadata.at(0)?.propertyName;
69
+ if (!propertyName) {
70
+ return;
71
+ }
72
+ let propertyInfo = properties[propertyName];
73
+ if (!propertyInfo) {
74
+ propertyInfo = {};
75
+ properties[propertyName] = propertyInfo;
76
+ }
77
+ let validators = propertyInfo.validators;
78
+ if (!validators) {
79
+ validators = [];
80
+ propertyInfo.validators = validators;
81
+ }
82
+ propertyValidatorsMetadata.forEach((propertyValidatorMetadata) => {
83
+ if (propertyValidatorMetadata.validator === _IS_OPTIONAL_DUMMY_VALIDATOR_) {
84
+ propertyInfo.isOptional = true;
85
+ }
86
+ else {
87
+ validators.push(propertyValidatorMetadata);
88
+ }
89
+ });
90
+ });
91
+ return properties;
92
+ }
93
+ };
94
+ ValidationMetadataStore = __decorate([
95
+ singleton()
96
+ ], ValidationMetadataStore);
97
+
98
+ export { ValidationMetadataStore };
@@ -0,0 +1,9 @@
1
+ import { container } from '../injection/index.js';
2
+ import { ValidationMetadataStore } from './metadata/ValidationMetadataStore.js';
3
+
4
+ function modelInfo(modelConstructor) {
5
+ const metadataStore = container.resolve(ValidationMetadataStore);
6
+ return metadataStore.getModelValidatorsInfo(modelConstructor);
7
+ }
8
+
9
+ export { modelInfo };
@@ -0,0 +1,11 @@
1
+ import { container } from '../injection/index.js';
2
+ import { ValidationMetadataStore } from './metadata/ValidationMetadataStore.js';
3
+ import { validateModel } from './validators/validateModel.js';
4
+
5
+ function validate(value, modelConstructor) {
6
+ const metadataStore = container.resolve(ValidationMetadataStore);
7
+ const info = metadataStore.getModelValidatorsInfo(modelConstructor);
8
+ return validateModel(value, info);
9
+ }
10
+
11
+ export { validate };
@@ -0,0 +1,51 @@
1
+ function validateArray(value, options) {
2
+ if (!Array.isArray(value)) {
3
+ return {
4
+ error: { description: 'Should be an array', items: [] },
5
+ };
6
+ }
7
+ if (options?.minLength != null && value.length < options.minLength) {
8
+ return {
9
+ error: { description: 'exceeds the established min length limit', items: [] },
10
+ };
11
+ }
12
+ if (options?.maxLength != null && value.length > options.maxLength) {
13
+ return {
14
+ error: { description: 'exceeds the established max length limit', items: [] },
15
+ };
16
+ }
17
+ const { itemsValidator } = options ?? {};
18
+ const valueOut = [];
19
+ const errorItems = [];
20
+ for (const item of value) {
21
+ let itemOut = item;
22
+ const itemErrors = [];
23
+ for (const itemValidator of itemsValidator ?? []) {
24
+ const { error, value } = itemValidator.validator(itemOut, itemValidator.options);
25
+ if (error) {
26
+ itemErrors.push(error);
27
+ }
28
+ else {
29
+ itemOut = value;
30
+ }
31
+ }
32
+ if (itemErrors.length == 0) {
33
+ valueOut.push(itemOut);
34
+ errorItems.push(null);
35
+ }
36
+ else {
37
+ valueOut.push(null);
38
+ errorItems.push(itemErrors);
39
+ }
40
+ }
41
+ if (errorItems.some((x) => x != null)) {
42
+ return {
43
+ error: { description: 'Error on some items', items: errorItems },
44
+ };
45
+ }
46
+ return {
47
+ value: valueOut,
48
+ };
49
+ }
50
+
51
+ export { validateArray };
@@ -0,0 +1,5 @@
1
+ const _IS_OPTIONAL_DUMMY_VALIDATOR_ = (value) => {
2
+ return { value, errors: [] };
3
+ };
4
+
5
+ export { _IS_OPTIONAL_DUMMY_VALIDATOR_ };
@@ -0,0 +1,36 @@
1
+ function validateModel(value, info) {
2
+ if (typeof value !== 'object' || value === null) {
3
+ return { error: { description: 'Invalid object', properties: {} } };
4
+ }
5
+ let propertiesErrors = {};
6
+ let resultValue = new info.modelConstructor();
7
+ for (const propertyName in info.properties) {
8
+ const propertyInfo = info.properties[propertyName];
9
+ const propertyValidators = propertyInfo.validators ?? [];
10
+ resultValue[propertyName] = propertyInfo.isOptional
11
+ ? (value[propertyName] ?? resultValue[propertyName])
12
+ : value[propertyName];
13
+ if (resultValue[propertyName] == null && propertyInfo.isOptional) {
14
+ resultValue[propertyName] = undefined;
15
+ continue;
16
+ }
17
+ for (let propertyValidatorInfo of propertyValidators) {
18
+ const propertyValidatorResult = propertyValidatorInfo.validator(resultValue[propertyName], propertyValidatorInfo.validatorOptions);
19
+ resultValue[propertyName] = propertyValidatorResult.value;
20
+ if (propertyValidatorResult.error) {
21
+ let propertyErrors = propertiesErrors[propertyName];
22
+ if (!propertyErrors) {
23
+ propertyErrors = [];
24
+ propertiesErrors[propertyName] = propertyErrors;
25
+ }
26
+ propertyErrors.push(propertyValidatorResult.error.description);
27
+ }
28
+ }
29
+ }
30
+ if (Object.keys(propertiesErrors).length > 0) {
31
+ return { error: { description: 'Invalid properties', properties: propertiesErrors } };
32
+ }
33
+ return { value: resultValue };
34
+ }
35
+
36
+ export { validateModel };
@@ -0,0 +1,11 @@
1
+ import { CommandMetadataStore } from './CommandMetadataStore.js';
2
+ import { container } from '../../core/injection/index.js';
3
+
4
+ function command(config) {
5
+ return function (target) {
6
+ const handlerContainer = container.resolve(CommandMetadataStore);
7
+ handlerContainer.registerCommand(target, config?.name ?? target.name);
8
+ };
9
+ }
10
+
11
+ export { command };
@@ -0,0 +1,12 @@
1
+ import { CommandMetadataStore } from './CommandMetadataStore.js';
2
+ import { container, injectable } from '../../core/injection/index.js';
3
+
4
+ function commandHandler(config) {
5
+ return function (target) {
6
+ const handlerContainer = container.resolve(CommandMetadataStore);
7
+ handlerContainer.registerHandler(config.command, target);
8
+ injectable()(target);
9
+ };
10
+ }
11
+
12
+ export { commandHandler };
@@ -0,0 +1,38 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { singleton } from '../../core/injection/index.js';
3
+ import { CommandMetadataStore } from './CommandMetadataStore.js';
4
+ import { Job } from './Job.js';
5
+ import { JobRepository } from './JobRepository.js';
6
+ import { JobsEventsHub } from './JobsEventsHub.js';
7
+
8
+ let Async = class Async {
9
+ jobRepository;
10
+ handlerContainer;
11
+ jobsEventsHub;
12
+ constructor(jobRepository, handlerContainer, jobsEventsHub) {
13
+ this.jobRepository = jobRepository;
14
+ this.handlerContainer = handlerContainer;
15
+ this.jobsEventsHub = jobsEventsHub;
16
+ }
17
+ async run(command) {
18
+ const commandName = this.handlerContainer.getCommandName(command.constructor);
19
+ if (!commandName) {
20
+ throw new Error(`${command.constructor.name} is not registered as command`);
21
+ }
22
+ const job = new Job({
23
+ commandName,
24
+ commandData: command['data'],
25
+ });
26
+ await this.jobRepository.create(job);
27
+ this.jobsEventsHub.notifyJobCreated(job);
28
+ return job;
29
+ }
30
+ };
31
+ Async = __decorate([
32
+ singleton(),
33
+ __metadata("design:paramtypes", [JobRepository,
34
+ CommandMetadataStore,
35
+ JobsEventsHub])
36
+ ], Async);
37
+
38
+ export { Async };
@@ -0,0 +1,9 @@
1
+ import { Storable } from '../../core/storable/Storable.js';
2
+
3
+ class Command extends Storable {
4
+ getData() {
5
+ return this.data;
6
+ }
7
+ }
8
+
9
+ export { Command };
@@ -0,0 +1,38 @@
1
+ import { __decorate } from 'tslib';
2
+ import { singleton } from '../../core/injection/index.js';
3
+
4
+ let CommandMetadataStore = class CommandMetadataStore {
5
+ handlersMap = new Map();
6
+ handlersInverseMap = new Map();
7
+ commandsMap = new Map();
8
+ commandsInverseMap = new Map();
9
+ registerCommand(command, commandName) {
10
+ this.commandsMap.set(commandName, command);
11
+ this.commandsInverseMap.set(command, commandName);
12
+ }
13
+ registerHandler(command, handlerConstructor) {
14
+ let commandName = this.commandsInverseMap.get(command);
15
+ if (!commandName) {
16
+ throw new Error(`Should use @command decorator on command class ${command.name}`);
17
+ }
18
+ this.handlersMap.set(commandName, handlerConstructor);
19
+ this.handlersInverseMap.set(handlerConstructor, commandName);
20
+ }
21
+ getHandlerForCommandName(commandName) {
22
+ return this.handlersMap.get(commandName) ?? null;
23
+ }
24
+ getCommandNameForHandler(handlerConstructor) {
25
+ return this.handlersInverseMap.get(handlerConstructor) ?? null;
26
+ }
27
+ getCommandName(command) {
28
+ return this.commandsInverseMap.get(command) ?? null;
29
+ }
30
+ getCommandForCommandName(commandName) {
31
+ return this.commandsMap.get(commandName) ?? null;
32
+ }
33
+ };
34
+ CommandMetadataStore = __decorate([
35
+ singleton()
36
+ ], CommandMetadataStore);
37
+
38
+ export { CommandMetadataStore };
@@ -0,0 +1,24 @@
1
+ import { Entity } from '../../core/entity/Entity.js';
2
+ import { CustomError } from '../../core/error/CustomError.js';
3
+
4
+ class Job extends Entity {
5
+ get commandName() {
6
+ return this.data.commandName;
7
+ }
8
+ setAsStarted() {
9
+ this.data.startedAt = new Date().getTime();
10
+ }
11
+ setAsSuccess() {
12
+ this.data.successAt = new Date().getTime();
13
+ }
14
+ setAsFailed(error) {
15
+ this.data.failedAt = new Date().getTime();
16
+ this.data.error = {
17
+ message: error.message,
18
+ stack: error.stack,
19
+ info: error instanceof CustomError ? error.info : undefined,
20
+ };
21
+ }
22
+ }
23
+
24
+ export { Job };
@@ -0,0 +1,31 @@
1
+ import { __decorate } from 'tslib';
2
+ import { singleton } from '../../core/injection/index.js';
3
+
4
+ let JobRepository = class JobRepository {
5
+ find(id) {
6
+ throw new Error('Method not implemented.');
7
+ }
8
+ findOrThrow(id) {
9
+ throw new Error('Method not implemented.');
10
+ }
11
+ findByIds(ids) {
12
+ throw new Error('Method not implemented.');
13
+ }
14
+ findAll(id) {
15
+ throw new Error('Method not implemented.');
16
+ }
17
+ create(item) {
18
+ throw new Error('Method not implemented.');
19
+ }
20
+ update(item) {
21
+ throw new Error('Method not implemented.');
22
+ }
23
+ discard(item) {
24
+ throw new Error('Method not implemented.');
25
+ }
26
+ };
27
+ JobRepository = __decorate([
28
+ singleton()
29
+ ], JobRepository);
30
+
31
+ export { JobRepository };
@@ -0,0 +1,45 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { CommandMetadataStore } from './CommandMetadataStore.js';
3
+ import { JobRepository } from './JobRepository.js';
4
+ import { singleton, container } from '../../core/injection/index.js';
5
+
6
+ let JobRunner = class JobRunner {
7
+ jobRepository;
8
+ handlerContainer;
9
+ constructor(jobRepository, handlerContainer) {
10
+ this.jobRepository = jobRepository;
11
+ this.handlerContainer = handlerContainer;
12
+ }
13
+ async run(job) {
14
+ try {
15
+ const { commandName, commandData } = job['data'];
16
+ const handlerConstructor = this.handlerContainer.getHandlerForCommandName(commandName);
17
+ if (!handlerConstructor) {
18
+ throw new Error(`Not found handler for command '${commandName}'`);
19
+ }
20
+ const handler = container.resolve(handlerConstructor);
21
+ const commandConstructor = this.handlerContainer.getCommandForCommandName(commandName);
22
+ if (!commandConstructor) {
23
+ throw new Error(`Not found class for command name '${commandName}'`);
24
+ }
25
+ job.setAsStarted();
26
+ await this.jobRepository.update(job);
27
+ const command = new commandConstructor(commandData);
28
+ await handler.handle(command);
29
+ job.setAsSuccess();
30
+ }
31
+ catch (e) {
32
+ job.setAsFailed(e instanceof Error ? e : new Error('Invalid Job error'));
33
+ }
34
+ finally {
35
+ await this.jobRepository.update(job);
36
+ }
37
+ }
38
+ };
39
+ JobRunner = __decorate([
40
+ singleton(),
41
+ __metadata("design:paramtypes", [JobRepository,
42
+ CommandMetadataStore])
43
+ ], JobRunner);
44
+
45
+ export { JobRunner };
@@ -0,0 +1,24 @@
1
+ import { __decorate } from 'tslib';
2
+ import { singleton } from '../../core/injection/index.js';
3
+
4
+ let JobsEventsHub = class JobsEventsHub {
5
+ jobsEventsListener = null;
6
+ notifyJobCreated(job) {
7
+ if (!this.jobsEventsListener) {
8
+ return;
9
+ }
10
+ this.jobsEventsListener({
11
+ jobId: job.id,
12
+ commandName: job.commandName,
13
+ type: 'created',
14
+ });
15
+ }
16
+ listenJobsEvents(listener) {
17
+ this.jobsEventsListener = listener;
18
+ }
19
+ };
20
+ JobsEventsHub = __decorate([
21
+ singleton()
22
+ ], JobsEventsHub);
23
+
24
+ export { JobsEventsHub };