@wabot-dev/framework 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/src/addon/auth/api-key/@apiKeyGuard.js +1 -0
  2. package/dist/src/addon/auth/api-key/@apiKeyHandshakeGuard.js +2 -0
  3. package/dist/src/addon/auth/api-key/ApiKey.js +1 -0
  4. package/dist/src/addon/auth/api-key/ApiKeyGuardMiddleware.js +1 -0
  5. package/dist/src/addon/auth/api-key/ApiKeyHandshakeGuardMiddleware.js +10 -2
  6. package/dist/src/addon/auth/api-key/PgApiKeyRepository.js +1 -0
  7. package/dist/src/addon/auth/api-key/RemoteApiKeyRepository.js +1 -0
  8. package/dist/src/addon/auth/jwt/@jwtGuard.js +1 -0
  9. package/dist/src/addon/auth/jwt/@jwtHandshakeGuard.js +2 -0
  10. package/dist/src/addon/auth/jwt/JwtGuardMiddleware.js +7 -2
  11. package/dist/src/addon/auth/jwt/JwtHandshakeGuardMiddleware.js +1 -0
  12. package/dist/src/addon/auth/jwt/JwtRefreshToken.js +1 -0
  13. package/dist/src/addon/auth/jwt/PgJwtRefreshTokenRepository.js +1 -0
  14. package/dist/src/addon/chat-bot/anthropic/AnthropicChatAdapter.js +6 -2
  15. package/dist/src/addon/chat-bot/google/GoogleChatAdapter.js +5 -1
  16. package/dist/src/addon/chat-bot/pg/PgChatMemory.js +1 -0
  17. package/dist/src/addon/chat-bot/pg/PgChatRepository.js +1 -0
  18. package/dist/src/addon/chat-bot/wabot/WabotChatAdapter.js +1 -0
  19. package/dist/src/addon/chat-controller/cmd/@cmd.js +1 -6
  20. package/dist/src/addon/chat-controller/cmd/CmdChannel.js +8 -0
  21. package/dist/src/addon/chat-controller/socket/@socket.js +1 -6
  22. package/dist/src/addon/chat-controller/socket/SocketChannel.js +3 -0
  23. package/dist/src/addon/chat-controller/telegram/@telegram.js +1 -6
  24. package/dist/src/addon/chat-controller/telegram/TelegramChannel.js +3 -0
  25. package/dist/src/addon/chat-controller/whatsapp/@whatsApp.js +1 -6
  26. package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannel.js +3 -0
  27. package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiver.js +3 -0
  28. package/dist/src/addon/chat-controller/whatsapp/WhatsAppSender.js +1 -0
  29. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppSenderByCloudApi.js +2 -3
  30. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +2 -3
  31. package/dist/src/core/auth/Auth.js +1 -0
  32. package/dist/src/core/error/setupErrorHandlers.js +33 -0
  33. package/dist/src/core/logger/Logger.js +66 -9
  34. package/dist/src/core/mapper/Mapper.js +1 -0
  35. package/dist/src/feature/async/Job.js +1 -0
  36. package/dist/src/feature/async/JobExecutor.js +8 -1
  37. package/dist/src/feature/async/JobRunner.js +10 -6
  38. package/dist/src/feature/chat-bot/safeJsonParse.js +19 -0
  39. package/dist/src/feature/chat-controller/ChatResolver.js +36 -10
  40. package/dist/src/feature/chat-controller/runChatControllers.js +9 -1
  41. package/dist/src/feature/mindset/MindsetOperator.js +6 -1
  42. package/dist/src/feature/pg/PgCrudRepository.js +1 -0
  43. package/dist/src/feature/pg/PgRepositoryBase.js +2 -2
  44. package/dist/src/feature/rest-controller/runRestControllers.js +1 -0
  45. package/dist/src/feature/socket/SocketServerConfig.js +25 -0
  46. package/dist/src/feature/socket/SocketServerProvider.js +15 -3
  47. package/dist/src/feature/socket-controller/runSocketControllers.js +2 -0
  48. package/dist/src/index.d.ts +60 -17
  49. package/dist/src/index.js +3 -0
  50. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import '../../../core/injection/index.js';
2
2
  import '../../../feature/rest-controller/metadata/RestControllerMetadataStore.js';
3
3
  import { middleware } from '../../../feature/rest-controller/metadata/@middleware.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import 'debug';
5
6
  import '../../../core/validation/metadata/ValidationMetadataStore.js';
6
7
  import '../../../feature/express/ExpressProvider.js';
@@ -1,9 +1,11 @@
1
1
  import { handshakeMiddlewares } from '../../../feature/socket-controller/metadata/@handshakeMiddlewares.js';
2
2
  import '../../../feature/socket-controller/metadata/SocketControllerMetadataStore.js';
3
3
  import '../../../core/injection/index.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import 'debug';
5
6
  import '../../../core/validation/metadata/ValidationMetadataStore.js';
6
7
  import 'socket.io';
8
+ import '../../../feature/socket/SocketServerConfig.js';
7
9
  import '../../../feature/socket/SocketServerProvider.js';
8
10
  import { ApiKeyHandshakeGuardMiddleware } from './ApiKeyHandshakeGuardMiddleware.js';
9
11
 
@@ -1,5 +1,6 @@
1
1
  import { Entity } from '../../../core/entity/Entity.js';
2
2
  import { CustomError } from '../../../core/error/CustomError.js';
3
+ import '../../../core/error/setupErrorHandlers.js';
3
4
  import crypto from 'node:crypto';
4
5
 
5
6
  class ApiKey extends Entity {
@@ -2,6 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { injectable } from '../../../core/injection/index.js';
3
3
  import { Auth } from '../../../core/auth/Auth.js';
4
4
  import { CustomError } from '../../../core/error/CustomError.js';
5
+ import '../../../core/error/setupErrorHandlers.js';
5
6
  import { ApiKeyRepository } from './ApiKeyRepository.js';
6
7
 
7
8
  let ApiKeyGuardMiddleware = class ApiKeyGuardMiddleware {
@@ -1,6 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Auth } from '../../../core/auth/Auth.js';
3
3
  import { CustomError } from '../../../core/error/CustomError.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import { injectable } from '../../../core/injection/index.js';
5
6
  import { ApiKeyRepository } from './ApiKeyRepository.js';
6
7
 
@@ -18,8 +19,15 @@ let ApiKeyHandshakeGuardMiddleware = class ApiKeyHandshakeGuardMiddleware {
18
19
  authorization = authorization[0];
19
20
  }
20
21
  if (authorization) {
21
- const [prefix, token] = authorization.split(' ');
22
- if (prefix.toLowerCase() !== 'api-key' || !token) {
22
+ const parts = authorization.split(' ');
23
+ if (parts.length !== 2) {
24
+ throw new CustomError({
25
+ httpCode: 401,
26
+ message: 'Authorization header must be: Api-Key <token>',
27
+ });
28
+ }
29
+ const [prefix, token] = parts;
30
+ if (prefix.toLowerCase() !== 'api-key') {
23
31
  throw new CustomError({
24
32
  httpCode: 401,
25
33
  message: 'Authorization should be an Api-Key',
@@ -8,6 +8,7 @@ import '../../../feature/pg/pgStorage.js';
8
8
  import { Pool } from 'pg';
9
9
  import { ApiKey } from './ApiKey.js';
10
10
  import { CustomError } from '../../../core/error/CustomError.js';
11
+ import '../../../core/error/setupErrorHandlers.js';
11
12
  import { singleton } from '../../../core/injection/index.js';
12
13
 
13
14
  let PgApiKeyRepository = class PgApiKeyRepository extends PgCrudRepository {
@@ -1,4 +1,5 @@
1
1
  import { CustomError } from '../../../core/error/CustomError.js';
2
+ import '../../../core/error/setupErrorHandlers.js';
2
3
 
3
4
  class RemoteApiKeyRepository {
4
5
  fetcher;
@@ -1,6 +1,7 @@
1
1
  import '../../../core/injection/index.js';
2
2
  import '../../../feature/rest-controller/metadata/RestControllerMetadataStore.js';
3
3
  import { middleware } from '../../../feature/rest-controller/metadata/@middleware.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import 'debug';
5
6
  import '../../../core/validation/metadata/ValidationMetadataStore.js';
6
7
  import '../../../feature/express/ExpressProvider.js';
@@ -1,9 +1,11 @@
1
1
  import { handshakeMiddlewares } from '../../../feature/socket-controller/metadata/@handshakeMiddlewares.js';
2
2
  import '../../../feature/socket-controller/metadata/SocketControllerMetadataStore.js';
3
3
  import '../../../core/injection/index.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import 'debug';
5
6
  import '../../../core/validation/metadata/ValidationMetadataStore.js';
6
7
  import 'socket.io';
8
+ import '../../../feature/socket/SocketServerConfig.js';
7
9
  import '../../../feature/socket/SocketServerProvider.js';
8
10
  import { JwtHandshakeGuardMiddleware } from './JwtHandshakeGuardMiddleware.js';
9
11
 
@@ -1,5 +1,6 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { CustomError } from '../../../core/error/CustomError.js';
3
+ import '../../../core/error/setupErrorHandlers.js';
3
4
  import { injectable } from '../../../core/injection/index.js';
4
5
  import jwt from 'jsonwebtoken';
5
6
  import { Auth } from '../../../core/auth/Auth.js';
@@ -17,8 +18,12 @@ let JwtGuardMiddleware = class JwtGuardMiddleware {
17
18
  if (!authorization) {
18
19
  throw new CustomError({ httpCode: 401, message: 'Authorization header not available' });
19
20
  }
20
- const [bearer, token] = authorization.split(' ');
21
- if (bearer.toLowerCase() !== 'bearer' || !token) {
21
+ const parts = authorization.split(' ');
22
+ if (parts.length !== 2) {
23
+ throw new CustomError({ httpCode: 401, message: 'Authorization header must be: Bearer <token>' });
24
+ }
25
+ const [bearer, token] = parts;
26
+ if (bearer.toLowerCase() !== 'bearer') {
22
27
  throw new CustomError({ httpCode: 401, message: 'Authorization should be a bearer token' });
23
28
  }
24
29
  try {
@@ -3,6 +3,7 @@ import jwt from 'jsonwebtoken';
3
3
  import { injectable } from '../../../core/injection/index.js';
4
4
  import { Auth } from '../../../core/auth/Auth.js';
5
5
  import { CustomError } from '../../../core/error/CustomError.js';
6
+ import '../../../core/error/setupErrorHandlers.js';
6
7
  import { JwtConfig } from './JwtConfig.js';
7
8
 
8
9
  let JwtHandshakeGuardMiddleware = class JwtHandshakeGuardMiddleware {
@@ -1,5 +1,6 @@
1
1
  import { Entity } from '../../../core/entity/Entity.js';
2
2
  import { CustomError } from '../../../core/error/CustomError.js';
3
+ import '../../../core/error/setupErrorHandlers.js';
3
4
  import crypto from 'node:crypto';
4
5
 
5
6
  class JwtRefreshToken extends Entity {
@@ -1,6 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
3
  import { CustomError } from '../../../core/error/CustomError.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
5
6
  import '../../../feature/pg/PgLocker.js';
6
7
  import 'debug';
@@ -2,6 +2,10 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Env } from '../../../core/env/Env.js';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
4
  import { Logger } from '../../../core/logger/Logger.js';
5
+ import '../../../feature/chat-bot/ChatBot.js';
6
+ import 'uuid';
7
+ import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
8
+ import { safeJsonParse } from '../../../feature/chat-bot/safeJsonParse.js';
5
9
  import { Anthropic } from '@anthropic-ai/sdk';
6
10
 
7
11
  let AnthropicChatAdapter = class AnthropicChatAdapter {
@@ -23,7 +27,7 @@ let AnthropicChatAdapter = class AnthropicChatAdapter {
23
27
  messages,
24
28
  tools: tools.length > 0 ? tools : undefined,
25
29
  };
26
- this.logger.debug(`Call Claude API with Request: ${JSON.stringify(request)}`);
30
+ this.logger.debug(`Call Claude API with model: ${request.model}, messages: ${request.messages.length}, tools: ${request.tools?.length ?? 0}`);
27
31
  const response = await this.anthropic.messages.create(request);
28
32
  return this.mapResponse(response);
29
33
  }
@@ -65,7 +69,7 @@ let AnthropicChatAdapter = class AnthropicChatAdapter {
65
69
  type: 'tool_use',
66
70
  id: item.id,
67
71
  name: item.name,
68
- input: JSON.parse(item.arguments || '{}'),
72
+ input: safeJsonParse(item.arguments, 'function call arguments'),
69
73
  },
70
74
  ],
71
75
  },
@@ -3,6 +3,10 @@ import { Env } from '../../../core/env/Env.js';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
4
  import { Logger } from '../../../core/logger/Logger.js';
5
5
  import { Random } from '../../../core/random/Random.js';
6
+ import '../../../feature/chat-bot/ChatBot.js';
7
+ import 'uuid';
8
+ import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
9
+ import { safeJsonParse } from '../../../feature/chat-bot/safeJsonParse.js';
6
10
  import { GoogleGenAI } from '@google/genai';
7
11
 
8
12
  let GoogleChatAdapter = class GoogleChatAdapter {
@@ -61,7 +65,7 @@ let GoogleChatAdapter = class GoogleChatAdapter {
61
65
  functionCall: {
62
66
  id: item.id,
63
67
  name: item.name,
64
- args: JSON.parse(item.arguments ?? '{}'),
68
+ args: safeJsonParse(item.arguments, 'function call arguments'),
65
69
  },
66
70
  },
67
71
  ],
@@ -9,6 +9,7 @@ import { ChatItem } from '../../../feature/chat-bot/ChatItem.js';
9
9
  import '../../../core/injection/index.js';
10
10
  import 'uuid';
11
11
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
12
+ import '../../../core/error/setupErrorHandlers.js';
12
13
 
13
14
  class PgChatMemory extends PgCrudRepository {
14
15
  chatId;
@@ -12,6 +12,7 @@ import { Chat } from '../../../feature/chat-bot/Chat.js';
12
12
  import '../../../feature/chat-bot/ChatBot.js';
13
13
  import 'uuid';
14
14
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
15
+ import '../../../core/error/setupErrorHandlers.js';
15
16
 
16
17
  let PgChatRepository = class PgChatRepository extends PgCrudRepository {
17
18
  constructor(pool) {
@@ -1,6 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Env } from '../../../core/env/Env.js';
3
3
  import { CustomError } from '../../../core/error/CustomError.js';
4
+ import '../../../core/error/setupErrorHandlers.js';
4
5
  import { singleton } from '../../../core/injection/index.js';
5
6
  import { Logger } from '../../../core/logger/Logger.js';
6
7
 
@@ -1,12 +1,7 @@
1
1
  import { container } from '../../../core/injection/index.js';
2
2
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
3
3
  import '../../../feature/chat-controller/ChatResolver.js';
4
- import '../../../core/auth/Auth.js';
5
- import '../../../feature/chat-bot/ChatBot.js';
6
- import 'uuid';
7
- import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
8
- import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
9
- import '../../../feature/mindset/MindsetOperator.js';
4
+ import '../../../feature/chat-controller/runChatControllers.js';
10
5
  import { CmdChannel } from './CmdChannel.js';
11
6
 
12
7
  function cmd() {
@@ -1,5 +1,6 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { injectable } from '../../../core/injection/index.js';
3
+ import { Logger } from '../../../core/logger/Logger.js';
3
4
  import * as readline from 'readline';
4
5
  import * as fs from 'fs';
5
6
  import * as path from 'path';
@@ -23,6 +24,11 @@ let CmdChannel = CmdChannel_1 = class CmdChannel {
23
24
  listen(callback) {
24
25
  this.callBack = callback;
25
26
  }
27
+ disconnect() {
28
+ this.rl.removeAllListeners('line');
29
+ this.rl.close();
30
+ this.callBack = null;
31
+ }
26
32
  connect() {
27
33
  this.rl.on('line', async (input) => {
28
34
  const trimmedInput = input.trim();
@@ -81,6 +87,7 @@ function writeJsonToFile(filename, data) {
81
87
  fs.mkdirSync(dir, { recursive: true });
82
88
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
83
89
  }
90
+ const fileLogger = new Logger('wabot:cmd-channel');
84
91
  function readJsonFromFile(filename) {
85
92
  const filePath = path.resolve(process.cwd(), filename);
86
93
  if (!fs.existsSync(filePath)) {
@@ -91,6 +98,7 @@ function readJsonFromFile(filename) {
91
98
  return JSON.parse(jsonData);
92
99
  }
93
100
  catch (err) {
101
+ fileLogger.warn(`Failed to parse JSON from ${filename}:`, err);
94
102
  return null;
95
103
  }
96
104
  }
@@ -1,12 +1,7 @@
1
1
  import { container } from '../../../core/injection/index.js';
2
2
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
3
3
  import '../../../feature/chat-controller/ChatResolver.js';
4
- import '../../../core/auth/Auth.js';
5
- import '../../../feature/chat-bot/ChatBot.js';
6
- import 'uuid';
7
- import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
8
- import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
9
- import '../../../feature/mindset/MindsetOperator.js';
4
+ import '../../../feature/chat-controller/runChatControllers.js';
10
5
  import { SocketChannel } from './SocketChannel.js';
11
6
  import { SocketChannelConfig } from './SocketChannelConfig.js';
12
7
 
@@ -97,6 +97,9 @@ let SocketChannel = SocketChannel_1 = class SocketChannel {
97
97
  return;
98
98
  runSocketControllers([this.controller]);
99
99
  }
100
+ disconnect() {
101
+ this.callBack = null;
102
+ }
100
103
  };
101
104
  SocketChannel = SocketChannel_1 = __decorate([
102
105
  injectable(),
@@ -1,12 +1,7 @@
1
1
  import { container } from '../../../core/injection/index.js';
2
2
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
3
3
  import '../../../feature/chat-controller/ChatResolver.js';
4
- import '../../../core/auth/Auth.js';
5
- import '../../../feature/chat-bot/ChatBot.js';
6
- import 'uuid';
7
- import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
8
- import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
9
- import '../../../feature/mindset/MindsetOperator.js';
4
+ import '../../../feature/chat-controller/runChatControllers.js';
10
5
  import { TelegramChannel } from './TelegramChannel.js';
11
6
  import { TelegramChannelConfig } from './TelegramChannelConfig.js';
12
7
 
@@ -38,6 +38,9 @@ let TelegramChannel = TelegramChannel_1 = class TelegramChannel {
38
38
  connect() {
39
39
  this.bot.start();
40
40
  }
41
+ disconnect() {
42
+ this.bot.stop();
43
+ }
41
44
  };
42
45
  TelegramChannel = TelegramChannel_1 = __decorate([
43
46
  injectable(),
@@ -2,12 +2,7 @@ import { container } from '../../../core/injection/index.js';
2
2
  import { WhatsappChannelConfig } from './WhatsAppChannelConfig.js';
3
3
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
4
4
  import '../../../feature/chat-controller/ChatResolver.js';
5
- import '../../../core/auth/Auth.js';
6
- import '../../../feature/chat-bot/ChatBot.js';
7
- import 'uuid';
8
- import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
9
- import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
10
- import '../../../feature/mindset/MindsetOperator.js';
5
+ import '../../../feature/chat-controller/runChatControllers.js';
11
6
  import { WhatsAppChannel } from './WhatsAppChannel.js';
12
7
 
13
8
  function whatsApp(config) {
@@ -41,6 +41,9 @@ let WhatsAppChannel = class WhatsAppChannel {
41
41
  connect() {
42
42
  this.receiver.connect();
43
43
  }
44
+ disconnect() {
45
+ this.receiver.disconnect();
46
+ }
44
47
  };
45
48
  WhatsAppChannel = __decorate([
46
49
  injectable(),
@@ -2,6 +2,9 @@ class WhatsAppReceiver {
2
2
  connect() {
3
3
  throw new Error('Not Implemented');
4
4
  }
5
+ disconnect() {
6
+ throw new Error('Not Implemented');
7
+ }
5
8
  listenMessage(request) {
6
9
  throw new Error('Not Implemented');
7
10
  }
@@ -3,6 +3,7 @@ import { ChatItem } from '../../../feature/chat-bot/ChatItem.js';
3
3
  import '../../../core/injection/index.js';
4
4
  import 'uuid';
5
5
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
6
+ import '../../../core/error/setupErrorHandlers.js';
6
7
 
7
8
  class WhatsAppSender {
8
9
  chatRepository;
@@ -4,13 +4,12 @@ import { WhatsAppSender } from '../WhatsAppSender.js';
4
4
  import { singleton } from '../../../../core/injection/index.js';
5
5
  import '../../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
6
6
  import { ChatResolver } from '../../../../feature/chat-controller/ChatResolver.js';
7
- import '../../../../core/auth/Auth.js';
7
+ import '../../../../feature/chat-controller/runChatControllers.js';
8
8
  import '../../../../feature/chat-bot/ChatBot.js';
9
9
  import { ChatRepository } from '../../../../feature/chat-bot/ChatRepository.js';
10
10
  import 'uuid';
11
11
  import '../../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
12
- import '../../../../feature/mindset/metadata/MindsetMetadataStore.js';
13
- import '../../../../feature/mindset/MindsetOperator.js';
12
+ import '../../../../core/error/setupErrorHandlers.js';
14
13
  import { WhatsAppRepository } from '../WhatsAppRepository.js';
15
14
 
16
15
  let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSender {
@@ -6,11 +6,10 @@ import '../../../../feature/chat-bot/ChatBot.js';
6
6
  import { ChatRepository } from '../../../../feature/chat-bot/ChatRepository.js';
7
7
  import 'uuid';
8
8
  import '../../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
9
+ import '../../../../core/error/setupErrorHandlers.js';
9
10
  import '../../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
10
11
  import { ChatResolver } from '../../../../feature/chat-controller/ChatResolver.js';
11
- import '../../../../core/auth/Auth.js';
12
- import '../../../../feature/mindset/metadata/MindsetMetadataStore.js';
13
- import '../../../../feature/mindset/MindsetOperator.js';
12
+ import '../../../../feature/chat-controller/runChatControllers.js';
14
13
  import { WhatsAppRepository } from '../WhatsAppRepository.js';
15
14
  import { WhatsAppWabotProxyConnection } from './WhatsAppWabotProxyConnection.js';
16
15
 
@@ -1,5 +1,6 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { CustomError } from '../error/CustomError.js';
3
+ import '../error/setupErrorHandlers.js';
3
4
  import { scoped, Lifecycle } from '../injection/index.js';
4
5
 
5
6
  let Auth = class Auth {
@@ -0,0 +1,33 @@
1
+ import { Logger } from '../logger/Logger.js';
2
+
3
+ const defaultConfig = {
4
+ exitOnUncaughtException: true,
5
+ exitOnUnhandledRejection: true,
6
+ logger: new Logger('wabot:error'),
7
+ };
8
+ function setupErrorHandlers(config) {
9
+ const { exitOnUncaughtException, exitOnUnhandledRejection, logger } = {
10
+ ...defaultConfig,
11
+ ...config,
12
+ };
13
+ process.on('uncaughtException', (error, origin) => {
14
+ logger.fatal(`Uncaught Exception [${origin}]:`, error);
15
+ if (exitOnUncaughtException) {
16
+ process.exit(1);
17
+ }
18
+ });
19
+ process.on('unhandledRejection', (reason, promise) => {
20
+ if (reason instanceof Error) {
21
+ logger.error('Unhandled Rejection:', reason);
22
+ }
23
+ else {
24
+ logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
25
+ }
26
+ if (exitOnUnhandledRejection) {
27
+ process.exit(1);
28
+ }
29
+ });
30
+ logger.info('Global error handlers configured');
31
+ }
32
+
33
+ export { setupErrorHandlers };
@@ -8,9 +8,17 @@ const levelColors = {
8
8
  error: 1,
9
9
  fatal: 1,
10
10
  };
11
+ const levelToSeverity = {
12
+ warn: 'warning',
13
+ error: 'error',
14
+ fatal: 'fatal',
15
+ };
11
16
  class Logger {
17
+ static monitor = null;
12
18
  debuggers;
19
+ name;
13
20
  constructor(name) {
21
+ this.name = name;
14
22
  this.debuggers = {};
15
23
  for (const level of Object.keys(levelColors)) {
16
24
  const dbg = debug(`${name}:${level}`);
@@ -18,26 +26,76 @@ class Logger {
18
26
  this.debuggers[level] = dbg;
19
27
  }
20
28
  }
29
+ static setMonitor(monitor) {
30
+ Logger.monitor = monitor;
31
+ }
32
+ static getMonitor() {
33
+ return Logger.monitor;
34
+ }
21
35
  trace(...args) {
22
- this.log(this.debuggers['trace'], args);
36
+ this.log('trace', args);
23
37
  }
24
38
  debug(...args) {
25
- this.log(this.debuggers['debug'], args);
39
+ this.log('debug', args);
26
40
  }
27
41
  info(...args) {
28
- this.log(this.debuggers['info'], args);
42
+ this.log('info', args);
29
43
  }
30
44
  warn(...args) {
31
- this.log(this.debuggers['warn'], args);
45
+ this.log('warn', args);
32
46
  }
33
47
  error(...args) {
34
- this.log(this.debuggers['error'], args);
48
+ this.log('error', args);
35
49
  }
36
50
  fatal(...args) {
37
- this.log(this.debuggers['fatal'], args);
51
+ this.log('fatal', args);
52
+ }
53
+ log(level, args) {
54
+ const debugg = this.debuggers[level];
55
+ const formattedArgs = this.formatArgs(args);
56
+ debugg(...formattedArgs);
57
+ this.sendToMonitor(level, args);
58
+ }
59
+ sendToMonitor(level, args) {
60
+ const severity = levelToSeverity[level];
61
+ if (!severity || !Logger.monitor)
62
+ return;
63
+ const context = {
64
+ logger: this.name,
65
+ level: severity,
66
+ timestamp: new Date(),
67
+ extra: this.extractExtra(args),
68
+ };
69
+ const error = args.find((arg) => arg instanceof Error);
70
+ if (error) {
71
+ Logger.monitor.captureError(error, context);
72
+ }
73
+ else {
74
+ const message = args
75
+ .filter((arg) => !(arg instanceof Error))
76
+ .map((arg) => (typeof arg === 'string' ? arg : JSON.stringify(arg)))
77
+ .join(' ');
78
+ Logger.monitor.captureMessage(message, context);
79
+ }
80
+ }
81
+ extractExtra(args) {
82
+ const extra = {};
83
+ let index = 0;
84
+ for (const arg of args) {
85
+ if (arg instanceof Error)
86
+ continue;
87
+ if (typeof arg === 'object' && arg !== null) {
88
+ Object.assign(extra, arg);
89
+ }
90
+ else if (typeof arg !== 'string') {
91
+ extra[`arg${index}`] = arg;
92
+ }
93
+ index++;
94
+ }
95
+ return Object.keys(extra).length > 0 ? extra : {};
38
96
  }
39
- log(debugg, args) {
40
- const _args = args.map((arg) => {
97
+ formatArgs(args) {
98
+ return args.map((arg) => {
41
99
  if (arg instanceof Error) {
42
100
  return JSON.stringify({
43
101
  name: arg.name,
@@ -58,7 +116,6 @@ class Logger {
58
116
  }
59
117
  return arg;
60
118
  });
61
- debugg(..._args);
62
119
  }
63
120
  }
64
121
 
@@ -1,5 +1,6 @@
1
1
  import { Storable } from '../storable/Storable.js';
2
2
  import { CustomError } from '../error/CustomError.js';
3
+ import '../error/setupErrorHandlers.js';
3
4
  import '../injection/index.js';
4
5
  import '../validation/metadata/ValidationMetadataStore.js';
5
6
  import { validateAndTransform } from '../validation/validateAndTransform.js';
@@ -1,5 +1,6 @@
1
1
  import { Entity } from '../../core/entity/Entity.js';
2
2
  import { CustomError } from '../../core/error/CustomError.js';
3
+ import '../../core/error/setupErrorHandlers.js';
3
4
 
4
5
  class Job extends Entity {
5
6
  get commandName() {
@@ -35,7 +35,14 @@ let JobExecutor = class JobExecutor {
35
35
  });
36
36
  }
37
37
  catch (e) {
38
- this.logger.error(e);
38
+ this.logger.error(`Job ${job.id} execution error:`, e);
39
+ try {
40
+ job.setAsFailed(e instanceof Error ? e : new Error('Job execution error'));
41
+ await this.repo.update(job);
42
+ }
43
+ catch (updateError) {
44
+ this.logger.error(`Failed to update job ${job.id} status:`, updateError);
45
+ }
39
46
  }
40
47
  finally {
41
48
  this.release();
@@ -1,6 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { AsyncMetadataStore } from './AsyncMetadataStore.js';
3
3
  import { JobRepository } from './JobRepository.js';
4
+ import { Job } from './Job.js';
4
5
  import { singleton, container } from '../../core/injection/index.js';
5
6
  import { Logger } from '../../core/logger/Logger.js';
6
7
  import '../../core/validation/metadata/ValidationMetadataStore.js';
@@ -8,21 +9,23 @@ import { validateAndTransform } from '../../core/validation/validateAndTransform
8
9
 
9
10
  let JobRunner = class JobRunner {
10
11
  jobRepository;
11
- handlerContainer;
12
+ asyncMetadataStore;
12
13
  logger = new Logger('wabot:job-runner');
13
- constructor(jobRepository, handlerContainer) {
14
+ constructor(jobRepository, asyncMetadataStore) {
14
15
  this.jobRepository = jobRepository;
15
- this.handlerContainer = handlerContainer;
16
+ this.asyncMetadataStore = asyncMetadataStore;
16
17
  }
17
18
  async run(job) {
19
+ const jobRunnerContainer = container.createChildContainer();
18
20
  try {
19
21
  const { commandName, commandData } = job;
20
- const handlerConstructor = this.handlerContainer.getHandlerForCommandName(commandName);
22
+ const handlerConstructor = this.asyncMetadataStore.getHandlerForCommandName(commandName);
21
23
  if (!handlerConstructor) {
22
24
  throw new Error(`Not found handler for command '${commandName}'`);
23
25
  }
24
- const handler = container.resolve(handlerConstructor);
25
- const commandConstructor = this.handlerContainer.getCommandForCommandName(commandName);
26
+ jobRunnerContainer.registerInstance(Job, job);
27
+ const handler = jobRunnerContainer.resolve(handlerConstructor);
28
+ const commandConstructor = this.asyncMetadataStore.getCommandForCommandName(commandName);
26
29
  if (commandConstructor === undefined && commandData != undefined) {
27
30
  throw new Error(`Not found class for validate data of command '${commandName}'`);
28
31
  }
@@ -47,6 +50,7 @@ let JobRunner = class JobRunner {
47
50
  }
48
51
  finally {
49
52
  await this.jobRepository.update(job);
53
+ await jobRunnerContainer.dispose();
50
54
  }
51
55
  }
52
56
  };
@@ -0,0 +1,19 @@
1
+ import { CustomError } from '../../core/error/CustomError.js';
2
+ import '../../core/error/setupErrorHandlers.js';
3
+
4
+ function safeJsonParse(json, context) {
5
+ const input = json || '{}';
6
+ try {
7
+ return JSON.parse(input);
8
+ }
9
+ catch (error) {
10
+ throw new CustomError({
11
+ message: `Failed to parse JSON${context ? ` in ${context}` : ''}: ${input}`,
12
+ code: 'JSON_PARSE_ERROR',
13
+ httpCode: 400,
14
+ cause: error instanceof Error ? error : undefined,
15
+ });
16
+ }
17
+ }
18
+
19
+ export { safeJsonParse };
@@ -5,11 +5,15 @@ import { ChatRepository } from '../chat-bot/ChatRepository.js';
5
5
  import { injectable } from '../../core/injection/index.js';
6
6
  import 'uuid';
7
7
  import '../chat-bot/metadata/ChatBotMetadataStore.js';
8
+ import '../../core/error/setupErrorHandlers.js';
9
+ import { Locker } from '../../core/lock/Locker.js';
8
10
 
9
11
  let ChatResolver = class ChatResolver {
10
12
  chatRepository;
11
- constructor(chatRepository) {
13
+ locker;
14
+ constructor(chatRepository, locker) {
12
15
  this.chatRepository = chatRepository;
16
+ this.locker = locker;
13
17
  }
14
18
  async resolve(connection) {
15
19
  if (connection.chatType === 'GROUP') {
@@ -18,25 +22,47 @@ let ChatResolver = class ChatResolver {
18
22
  return this.resolvePrivateChat(connection);
19
23
  }
20
24
  async resolveGroupChat(connection) {
25
+ // Fast path: check without lock
21
26
  let chat = await this.chatRepository.findByConnection(connection);
22
- if (!chat) {
23
- chat = new Chat({ type: 'GROUP', connections: [connection] });
24
- await this.chatRepository.create(chat);
27
+ if (chat) {
28
+ return chat;
25
29
  }
26
- return chat;
30
+ // Slow path: acquire lock and double-check
31
+ const lockKey = this.buildLockKey(connection);
32
+ return this.locker.withKey(lockKey).run(async () => {
33
+ chat = await this.chatRepository.findByConnection(connection);
34
+ if (!chat) {
35
+ chat = new Chat({ type: 'GROUP', connections: [connection] });
36
+ await this.chatRepository.create(chat);
37
+ }
38
+ return chat;
39
+ });
27
40
  }
28
41
  async resolvePrivateChat(connection) {
42
+ // Fast path: check without lock
29
43
  let chat = await this.chatRepository.findByConnection(connection);
30
- if (!chat) {
31
- chat = new Chat({ type: 'PRIVATE', connections: [connection] });
32
- await this.chatRepository.create(chat);
44
+ if (chat) {
45
+ return chat;
33
46
  }
34
- return chat;
47
+ // Slow path: acquire lock and double-check
48
+ const lockKey = this.buildLockKey(connection);
49
+ return this.locker.withKey(lockKey).run(async () => {
50
+ chat = await this.chatRepository.findByConnection(connection);
51
+ if (!chat) {
52
+ chat = new Chat({ type: 'PRIVATE', connections: [connection] });
53
+ await this.chatRepository.create(chat);
54
+ }
55
+ return chat;
56
+ });
57
+ }
58
+ buildLockKey(connection) {
59
+ return `chat-resolver:${connection.channelName}:${connection.id}`;
35
60
  }
36
61
  };
37
62
  ChatResolver = __decorate([
38
63
  injectable(),
39
- __metadata("design:paramtypes", [ChatRepository])
64
+ __metadata("design:paramtypes", [ChatRepository,
65
+ Locker])
40
66
  ], ChatResolver);
41
67
 
42
68
  export { ChatResolver };
@@ -1,11 +1,13 @@
1
1
  import { Auth } from '../../core/auth/Auth.js';
2
2
  import { container } from '../../core/injection/index.js';
3
+ import { Logger } from '../../core/logger/Logger.js';
3
4
  import { Chat } from '../chat-bot/Chat.js';
4
5
  import { ChatBot } from '../chat-bot/ChatBot.js';
5
6
  import { ChatMemory } from '../chat-bot/ChatMemory.js';
6
7
  import { ChatRepository } from '../chat-bot/ChatRepository.js';
7
8
  import 'uuid';
8
9
  import { ChatBotMetadataStore } from '../chat-bot/metadata/ChatBotMetadataStore.js';
10
+ import '../../core/error/setupErrorHandlers.js';
9
11
  import '../mindset/metadata/MindsetMetadataStore.js';
10
12
  import { Mindset } from '../mindset/IMindset.js';
11
13
  import '../mindset/MindsetOperator.js';
@@ -39,6 +41,7 @@ async function prepareChatContainer(container, messageContext, mindsetCtor) {
39
41
  }
40
42
  return chatContainer;
41
43
  }
44
+ const logger = new Logger('wabot:chat-controller');
42
45
  function runChatControllers(controllers) {
43
46
  const metadataStore = container.resolve(ControllerMetadataStore);
44
47
  const chatResolver = container.resolve(ChatResolver);
@@ -71,7 +74,12 @@ function runChatControllers(controllers) {
71
74
  message: channelMessage.message,
72
75
  reply: channelMessage.reply,
73
76
  };
74
- chatController[channelMetadata.functionName](receivedMessage);
77
+ try {
78
+ await chatController[channelMetadata.functionName](receivedMessage);
79
+ }
80
+ catch (error) {
81
+ logger.error(`Error in chat controller ${channelMetadata.controllerConstructor.name}.${channelMetadata.functionName}:`, error);
82
+ }
75
83
  });
76
84
  channel.connect();
77
85
  }
@@ -5,6 +5,7 @@ import { MindsetMetadataStore } from './metadata/MindsetMetadataStore.js';
5
5
  import { validateModel } from '../../core/validation/core/validateModel.js';
6
6
  import '../../core/validation/metadata/ValidationMetadataStore.js';
7
7
  import { CustomError } from '../../core/error/CustomError.js';
8
+ import '../../core/error/setupErrorHandlers.js';
8
9
  import { Container } from '../../core/injection/Container.js';
9
10
 
10
11
  let MindsetOperator = class MindsetOperator {
@@ -114,7 +115,11 @@ let MindsetOperator = class MindsetOperator {
114
115
  .flat()
115
116
  .find((fn) => fn.name === name);
116
117
  if (!fnMetadata) {
117
- throw new Error(`Function ${name} not found`);
118
+ throw new CustomError({
119
+ httpCode: 400,
120
+ code: 'FUNCTION_NOT_WHITELISTED',
121
+ message: `Function '${name}' is not registered in mindset tools`,
122
+ });
118
123
  }
119
124
  try {
120
125
  let paramsObj = JSON.parse(params);
@@ -1,6 +1,7 @@
1
1
  import * as shortUUID from 'short-uuid';
2
2
  import { PgRepositoryBase } from './PgRepositoryBase.js';
3
3
  import { CustomError } from '../../core/error/CustomError.js';
4
+ import '../../core/error/setupErrorHandlers.js';
4
5
  import { withPgClient } from './withPgClient.js';
5
6
 
6
7
  class PgCrudRepository extends PgRepositoryBase {
@@ -89,10 +89,10 @@ class PgRepositoryBase {
89
89
  const existingColumns = new Set(existing.map((col) => col.column_name));
90
90
  for (let i = 0; i < this.columnsList.length; i++) {
91
91
  const col = this.columnsList[i];
92
- const columnAndType = this.columnsAndTypes[0];
92
+ const columnAndType = this.columnsAndTypes[i];
93
93
  if (!existingColumns.has(col)) {
94
94
  const alterSql = `ALTER TABLE ${this.table} ADD COLUMN ${columnAndType}`;
95
- console.log(`[INFO] Adding column: ${alterSql}`);
95
+ this.logger.info(`Adding column: ${alterSql}`);
96
96
  await client.query(alterSql);
97
97
  }
98
98
  }
@@ -1,4 +1,5 @@
1
1
  import { CustomError } from '../../core/error/CustomError.js';
2
+ import '../../core/error/setupErrorHandlers.js';
2
3
  import { container } from '../../core/injection/index.js';
3
4
  import { Logger } from '../../core/logger/Logger.js';
4
5
  import { validateModel } from '../../core/validation/core/validateModel.js';
@@ -0,0 +1,25 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { Env } from '../../core/env/Env.js';
3
+ import { singleton } from '../../core/injection/index.js';
4
+
5
+ let SocketServerConfig = class SocketServerConfig {
6
+ corsOrigin;
7
+ constructor(env) {
8
+ const origin = env.requireString('SOCKET_CORS_ORIGIN', { default: '' });
9
+ if (!origin) {
10
+ this.corsOrigin = false;
11
+ }
12
+ else if (origin === '*') {
13
+ this.corsOrigin = '*';
14
+ }
15
+ else {
16
+ this.corsOrigin = origin.split(',').map((o) => o.trim());
17
+ }
18
+ }
19
+ };
20
+ SocketServerConfig = __decorate([
21
+ singleton(),
22
+ __metadata("design:paramtypes", [Env])
23
+ ], SocketServerConfig);
24
+
25
+ export { SocketServerConfig };
@@ -3,13 +3,16 @@ import { singleton } from '../../core/injection/index.js';
3
3
  import { Logger } from '../../core/logger/Logger.js';
4
4
  import { HttpServerProvider } from '../http/HttpServerProvider.js';
5
5
  import { Server } from 'socket.io';
6
+ import { SocketServerConfig } from './SocketServerConfig.js';
6
7
 
7
8
  let SocketServerProvider = class SocketServerProvider {
8
9
  httpServerProvider;
10
+ config;
9
11
  socketServer = null;
10
12
  logger = new Logger('wabot:socket');
11
- constructor(httpServerProvider) {
13
+ constructor(httpServerProvider, config) {
12
14
  this.httpServerProvider = httpServerProvider;
15
+ this.config = config;
13
16
  }
14
17
  getSocketServer() {
15
18
  if (!this.socketServer) {
@@ -20,11 +23,19 @@ let SocketServerProvider = class SocketServerProvider {
20
23
  listen() {
21
24
  this.httpServerProvider.listen();
22
25
  }
26
+ close() {
27
+ if (this.socketServer) {
28
+ this.socketServer.removeAllListeners();
29
+ this.socketServer.close();
30
+ this.socketServer = null;
31
+ this.logger.info('socket server closed');
32
+ }
33
+ }
23
34
  createSocketServer() {
24
35
  const httpServer = this.httpServerProvider.getHttpServer();
25
36
  const socketServer = new Server(httpServer, {
26
37
  cors: {
27
- origin: '*',
38
+ origin: this.config.corsOrigin,
28
39
  },
29
40
  });
30
41
  socketServer.on('connection', (socket) => {
@@ -44,7 +55,8 @@ let SocketServerProvider = class SocketServerProvider {
44
55
  };
45
56
  SocketServerProvider = __decorate([
46
57
  singleton(),
47
- __metadata("design:paramtypes", [HttpServerProvider])
58
+ __metadata("design:paramtypes", [HttpServerProvider,
59
+ SocketServerConfig])
48
60
  ], SocketServerProvider);
49
61
 
50
62
  export { SocketServerProvider };
@@ -1,9 +1,11 @@
1
1
  import { CustomError } from '../../core/error/CustomError.js';
2
+ import '../../core/error/setupErrorHandlers.js';
2
3
  import { container } from '../../core/injection/index.js';
3
4
  import { Logger } from '../../core/logger/Logger.js';
4
5
  import '../../core/validation/metadata/ValidationMetadataStore.js';
5
6
  import { validateAndTransform } from '../../core/validation/validateAndTransform.js';
6
7
  import { Socket } from 'socket.io';
8
+ import '../socket/SocketServerConfig.js';
7
9
  import { SocketServerProvider } from '../socket/SocketServerProvider.js';
8
10
  import { SocketControllerMetadataStore } from './metadata/SocketControllerMetadataStore.js';
9
11
 
@@ -101,6 +101,44 @@ declare class CustomError extends Error {
101
101
  constructor(data: ICustomErrorData);
102
102
  }
103
103
 
104
+ type ErrorSeverity = 'warning' | 'error' | 'fatal';
105
+ interface IErrorMonitorContext {
106
+ logger: string;
107
+ level: ErrorSeverity;
108
+ timestamp: Date;
109
+ extra?: Record<string, unknown>;
110
+ }
111
+ interface IErrorMonitor {
112
+ captureError(error: Error, context: IErrorMonitorContext): void;
113
+ captureMessage(message: string, context: IErrorMonitorContext): void;
114
+ }
115
+
116
+ declare class Logger {
117
+ private static monitor;
118
+ private debuggers;
119
+ private name;
120
+ constructor(name: string);
121
+ static setMonitor(monitor: IErrorMonitor): void;
122
+ static getMonitor(): IErrorMonitor | null;
123
+ trace(...args: any[]): void;
124
+ debug(...args: any[]): void;
125
+ info(...args: any[]): void;
126
+ warn(...args: any[]): void;
127
+ error(...args: any[]): void;
128
+ fatal(...args: any[]): void;
129
+ private log;
130
+ private sendToMonitor;
131
+ private extractExtra;
132
+ private formatArgs;
133
+ }
134
+
135
+ interface IErrorHandlersConfig {
136
+ exitOnUncaughtException?: boolean;
137
+ exitOnUnhandledRejection?: boolean;
138
+ logger?: Logger;
139
+ }
140
+ declare function setupErrorHandlers(config?: IErrorHandlersConfig): void;
141
+
104
142
  type IConstructor<T> = new (...args: any[]) => T;
105
143
 
106
144
  declare class Container implements DependencyContainer {
@@ -126,18 +164,6 @@ declare const inject: typeof tsyringe.inject;
126
164
  declare const scoped: typeof tsyringe.scoped;
127
165
  declare const Lifecycle: typeof tsyringe.Lifecycle;
128
166
 
129
- declare class Logger {
130
- private debuggers;
131
- constructor(name: string);
132
- trace(...args: any[]): void;
133
- debug(...args: any[]): void;
134
- info(...args: any[]): void;
135
- warn(...args: any[]): void;
136
- error(...args: any[]): void;
137
- fatal(...args: any[]): void;
138
- private log;
139
- }
140
-
141
167
  declare function isModel(model: IConstructor<any>): (target: object, propertyKey: string | symbol) => void;
142
168
 
143
169
  declare function isOptional(): (target: object, propertyKey: string | symbol) => void;
@@ -471,9 +497,9 @@ declare class JobRepository implements IJobRepository {
471
497
 
472
498
  declare class JobRunner {
473
499
  private jobRepository;
474
- private handlerContainer;
500
+ private asyncMetadataStore;
475
501
  private logger;
476
- constructor(jobRepository: JobRepository, handlerContainer: AsyncMetadataStore);
502
+ constructor(jobRepository: JobRepository, asyncMetadataStore: AsyncMetadataStore);
477
503
  run(job: Job): Promise<void>;
478
504
  }
479
505
 
@@ -884,6 +910,8 @@ declare class ChatBotMetadataStore {
884
910
  getChatBotsMetadata(): IChatBotMetadata[];
885
911
  }
886
912
 
913
+ declare function safeJsonParse<T = unknown>(json: string | undefined | null, context?: string): T;
914
+
887
915
  interface IchatControllerConfig {
888
916
  }
889
917
 
@@ -906,6 +934,7 @@ interface IChannelMessage extends IReceivedMessage {
906
934
  interface IChatChannel {
907
935
  listen(callback: (received: IChannelMessage) => Promise<void>): void;
908
936
  connect(): void;
937
+ disconnect(): void;
909
938
  }
910
939
 
911
940
  interface IChannelMetadata {
@@ -928,10 +957,12 @@ declare class ControllerMetadataStore {
928
957
 
929
958
  declare class ChatResolver {
930
959
  private chatRepository;
931
- constructor(chatRepository: ChatRepository);
960
+ private locker;
961
+ constructor(chatRepository: ChatRepository, locker: Locker);
932
962
  resolve(connection: IChatConnection): Promise<Chat>;
933
963
  private resolveGroupChat;
934
964
  private resolvePrivateChat;
965
+ private buildLockKey;
935
966
  }
936
967
 
937
968
  interface IMessageContext extends IReceivedMessage {
@@ -1147,13 +1178,20 @@ declare class RestRequest {
1147
1178
  headers?: Record<string, string>;
1148
1179
  }
1149
1180
 
1181
+ declare class SocketServerConfig {
1182
+ corsOrigin: string | string[];
1183
+ constructor(env: Env);
1184
+ }
1185
+
1150
1186
  declare class SocketServerProvider {
1151
1187
  private httpServerProvider;
1188
+ private config;
1152
1189
  private socketServer;
1153
1190
  private logger;
1154
- constructor(httpServerProvider: HttpServerProvider);
1191
+ constructor(httpServerProvider: HttpServerProvider, config: SocketServerConfig);
1155
1192
  getSocketServer(): Server$1;
1156
1193
  listen(): void;
1194
+ close(): void;
1157
1195
  private createSocketServer;
1158
1196
  }
1159
1197
 
@@ -1516,6 +1554,7 @@ declare class CmdChannel implements IChatChannel {
1516
1554
  private callBack;
1517
1555
  constructor(auth: Auth<any>);
1518
1556
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1557
+ disconnect(): void;
1519
1558
  connect(): void;
1520
1559
  }
1521
1560
  declare function writeJsonToFile<T>(filename: string, data: T): void;
@@ -1552,6 +1591,7 @@ declare class SocketChannel implements IChatChannel {
1552
1591
  private configController;
1553
1592
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1554
1593
  connect(): void;
1594
+ disconnect(): void;
1555
1595
  }
1556
1596
 
1557
1597
  interface ITelegramChannelConfig {
@@ -1570,6 +1610,7 @@ declare class TelegramChannel implements IChatChannel {
1570
1610
  constructor(config: TelegramChannelConfig);
1571
1611
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1572
1612
  connect(): void;
1613
+ disconnect(): void;
1573
1614
  }
1574
1615
 
1575
1616
  interface IWhatsappChannelConfig {
@@ -1638,6 +1679,7 @@ interface IListenWhatsAppMessageRequest {
1638
1679
  }
1639
1680
  declare class WhatsAppReceiver {
1640
1681
  connect(): Promise<void>;
1682
+ disconnect(): void;
1641
1683
  listenMessage(request: IListenWhatsAppMessageRequest): void;
1642
1684
  }
1643
1685
 
@@ -1735,6 +1777,7 @@ declare class WhatsAppChannel implements IChatChannel {
1735
1777
  constructor(config: WhatsappChannelConfig, sender: WhatsAppSender, receiver: WhatsAppReceiver);
1736
1778
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1737
1779
  connect(): void;
1780
+ disconnect(): void;
1738
1781
  }
1739
1782
 
1740
1783
  interface IWhatsAppCloudWebhookPayload {
@@ -1874,4 +1917,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
1874
1917
  new (): {};
1875
1918
  };
1876
1919
 
1877
- export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CronJob, CronJobRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronJobData, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type IStorableData, type ITelegramChannelConfig, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WhatsApp, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, command, commandHandler, container, cron, description, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, scoped, singleton, socket, socketController, stopCommandHandlers, stopCronHandlers, telegram, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, withPgClient, withPgTransaction, writeJsonToFile };
1920
+ export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatRepository, ChatResolver, type ClientMap, CmdChannel, Container, ControllerMetadataStore, CronJob, CronJobRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, EnvWhatsAppRepository, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterNextItemsReq, type IChatAdapterNextItemsRes, type IChatAssociation, type IChatBot, type IChatBotMetadata, type IChatChannel, type IChatConnection, type IChatControllerMetadata, type IChatData, type IChatItem, type IChatItemData, type IChatItemType, type IChatMemory, type IChatMessage, type IChatRepository, type IChatType, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronJobData, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IGetWhatsAppTemplateRequest, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type IListenWhatsAppMessageRequest, type ILockKey, type ILocker, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IPropertyValidatorInfo, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRestControllerConfig, type IRestControllerMetadata, type ISendWhatsAppRequest, type ISendWhatsAppTemplateRequest, type ISocketChannelConfig, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type IStorableData, type ITelegramChannelConfig, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWhatsAppBusinessAccount, type IWhatsAppBusinessNumber, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateMessage, type IWhatsAppCloudTemplateParameter, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppData, type IWhatsAppMessageListener, type IWhatsAppProxyListenMessageEventData, type IWhatsAppProxyListenMessageEventReq, type IWhatsAppProxyMessage, type IWhatsAppProxyMessageContent, type IWhatsAppProxyMessageEventReq, type IWhatsAppProxySendMessageEventReq, type IWhatsAppRepository, type IWhatsAppSenderOptions, type IWhatsappChannelConfig, type IchatControllerConfig, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, Mapper, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenaiChatAdapter, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgWhatsAppRepository, RamChatMemory, RamChatRepository, Random, RemoteApiKeyRepository, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, ValidationMetadataStore, WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT, WabotChatAdapter, WhatsApp, WhatsAppChannel, WhatsAppReceiver, WhatsAppReceiverByCloudApi, WhatsAppReceiverByWabotProxy, WhatsAppRepository, WhatsAppSender, WhatsAppSenderByCloudApi, WhatsAppSenderByWabotProxy, WhatsAppWabotProxyConnection, WhatsappChannelConfig, apiKeyGuard, apiKeyHandshakeGuard, chatBot, chatController, chatItemTypeOptions, cmd, command, commandHandler, container, cron, description, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isString, jwtGuard, jwtHandshakeGuard, max, middleware, min, mindset, mindsetModule, modelInfo, onDelete, onGet, onPost, onPut, onSocketEvent, pgStorage, readJsonFromFile, restController, runChatControllers, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scoped, setupErrorHandlers, singleton, socket, socketController, stopCommandHandlers, stopCronHandlers, telegram, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, whatsApp, withPgClient, withPgTransaction, writeJsonToFile };
package/dist/src/index.js CHANGED
@@ -2,6 +2,7 @@ export { Auth } from './core/auth/Auth.js';
2
2
  export { Entity, Persistent } from './core/entity/Entity.js';
3
3
  export { Env } from './core/env/Env.js';
4
4
  export { CustomError } from './core/error/CustomError.js';
5
+ export { setupErrorHandlers } from './core/error/setupErrorHandlers.js';
5
6
  export { Lifecycle, container, inject, injectable, scoped, singleton } from './core/injection/index.js';
6
7
  export { Logger } from './core/logger/Logger.js';
7
8
  export { Mapper } from './core/mapper/Mapper.js';
@@ -60,6 +61,7 @@ export { ChatRepository } from './feature/chat-bot/ChatRepository.js';
60
61
  export { chatItemTypeOptions } from './feature/chat-bot/IChatItem.js';
61
62
  export { chatBot } from './feature/chat-bot/metadata/@chatBot.js';
62
63
  export { ChatBotMetadataStore } from './feature/chat-bot/metadata/ChatBotMetadataStore.js';
64
+ export { safeJsonParse } from './feature/chat-bot/safeJsonParse.js';
63
65
  export { chatController } from './feature/chat-controller/metadata/controller/@chatController.js';
64
66
  export { ControllerMetadataStore } from './feature/chat-controller/metadata/ControllerMetadataStore.js';
65
67
  export { ChatResolver } from './feature/chat-controller/ChatResolver.js';
@@ -90,6 +92,7 @@ export { RestControllerMetadataStore } from './feature/rest-controller/metadata/
90
92
  export { runRestControllers } from './feature/rest-controller/runRestControllers.js';
91
93
  export { EXPRESS_REQ, EXPRESS_RES } from './feature/rest-controller/injection-tokens.js';
92
94
  export { RestRequest } from './feature/rest-controller/RestRequest.js';
95
+ export { SocketServerConfig } from './feature/socket/SocketServerConfig.js';
93
96
  export { SocketServerProvider } from './feature/socket/SocketServerProvider.js';
94
97
  export { handshakeMiddlewares } from './feature/socket-controller/metadata/@handshakeMiddlewares.js';
95
98
  export { socketController } from './feature/socket-controller/metadata/@socketController.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wabot-dev/framework",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Framework for IA Chat Bots",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",