@wabot-dev/framework 0.5.0 → 0.5.2

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 (53) 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/entity/Entity.js +3 -0
  33. package/dist/src/core/error/setupErrorHandlers.js +33 -0
  34. package/dist/src/core/logger/Logger.js +66 -9
  35. package/dist/src/core/mapper/Mapper.js +1 -0
  36. package/dist/src/feature/async/Async.js +28 -4
  37. package/dist/src/feature/async/Job.js +1 -0
  38. package/dist/src/feature/async/JobExecutor.js +8 -1
  39. package/dist/src/feature/async/JobRunner.js +10 -6
  40. package/dist/src/feature/chat-bot/safeJsonParse.js +19 -0
  41. package/dist/src/feature/chat-controller/ChatResolver.js +36 -10
  42. package/dist/src/feature/chat-controller/runChatControllers.js +9 -1
  43. package/dist/src/feature/mindset/MindsetOperator.js +6 -1
  44. package/dist/src/feature/pg/PgCrudRepository.js +1 -0
  45. package/dist/src/feature/pg/PgLocker.js +1 -1
  46. package/dist/src/feature/pg/PgRepositoryBase.js +2 -2
  47. package/dist/src/feature/rest-controller/runRestControllers.js +1 -0
  48. package/dist/src/feature/socket/SocketServerConfig.js +25 -0
  49. package/dist/src/feature/socket/SocketServerProvider.js +15 -3
  50. package/dist/src/feature/socket-controller/runSocketControllers.js +2 -0
  51. package/dist/src/index.d.ts +90 -31
  52. package/dist/src/index.js +3 -0
  53. package/package.json +1 -1
@@ -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 {
@@ -9,7 +9,7 @@ let PgLocker = class PgLocker {
9
9
  this.pool = pool;
10
10
  }
11
11
  withKey(key) {
12
- return new PgLockKey(key, this.pool);
12
+ return new PgLockKey(typeof key === 'object' ? key.lockerKey() : key, this.pool);
13
13
  }
14
14
  };
15
15
  PgLocker = __decorate([
@@ -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
 
@@ -30,6 +30,21 @@ declare class Auth<D> {
30
30
  wasOverrided(): boolean;
31
31
  }
32
32
 
33
+ interface ILockKey {
34
+ run<T>(fn: () => Promise<T>): Promise<T>;
35
+ tryRun<T>(fn: () => Promise<T>): Promise<T | undefined>;
36
+ }
37
+
38
+ interface ILockerKey {
39
+ lockerKey(): string | number;
40
+ }
41
+ interface ILocker {
42
+ withKey(key: string | number | ILockerKey): ILockKey;
43
+ }
44
+ declare class Locker implements ILocker {
45
+ withKey(key: string | number | ILockerKey): ILockKey;
46
+ }
47
+
33
48
  type IStorableData<O extends object> = {
34
49
  [K in keyof O]: IStorableType<O[K]>;
35
50
  };
@@ -44,7 +59,7 @@ interface IEntityData {
44
59
  createdAt?: number | null;
45
60
  discardedAt?: number | null;
46
61
  }
47
- declare class Entity<D extends IEntityData> extends Storable<D> {
62
+ declare class Entity<D extends IEntityData> extends Storable<D> implements ILockerKey {
48
63
  get id(): NonNullable<IStorableType<D["id"]>>;
49
64
  /**
50
65
  * @deprecated use id
@@ -58,6 +73,7 @@ declare class Entity<D extends IEntityData> extends Storable<D> {
58
73
  update(newData: Partial<Omit<D, 'id' | 'createdAt' | 'discardedAt'>>): void;
59
74
  wasCreated(): boolean;
60
75
  validate(): void;
76
+ lockerKey(): string | number;
61
77
  }
62
78
  /**
63
79
  * @deprecated Should use IEntityData
@@ -101,6 +117,44 @@ declare class CustomError extends Error {
101
117
  constructor(data: ICustomErrorData);
102
118
  }
103
119
 
120
+ type ErrorSeverity = 'warning' | 'error' | 'fatal';
121
+ interface IErrorMonitorContext {
122
+ logger: string;
123
+ level: ErrorSeverity;
124
+ timestamp: Date;
125
+ extra?: Record<string, unknown>;
126
+ }
127
+ interface IErrorMonitor {
128
+ captureError(error: Error, context: IErrorMonitorContext): void;
129
+ captureMessage(message: string, context: IErrorMonitorContext): void;
130
+ }
131
+
132
+ declare class Logger {
133
+ private static monitor;
134
+ private debuggers;
135
+ private name;
136
+ constructor(name: string);
137
+ static setMonitor(monitor: IErrorMonitor): void;
138
+ static getMonitor(): IErrorMonitor | null;
139
+ trace(...args: any[]): void;
140
+ debug(...args: any[]): void;
141
+ info(...args: any[]): void;
142
+ warn(...args: any[]): void;
143
+ error(...args: any[]): void;
144
+ fatal(...args: any[]): void;
145
+ private log;
146
+ private sendToMonitor;
147
+ private extractExtra;
148
+ private formatArgs;
149
+ }
150
+
151
+ interface IErrorHandlersConfig {
152
+ exitOnUncaughtException?: boolean;
153
+ exitOnUnhandledRejection?: boolean;
154
+ logger?: Logger;
155
+ }
156
+ declare function setupErrorHandlers(config?: IErrorHandlersConfig): void;
157
+
104
158
  type IConstructor<T> = new (...args: any[]) => T;
105
159
 
106
160
  declare class Container implements DependencyContainer {
@@ -126,18 +180,6 @@ declare const inject: typeof tsyringe.inject;
126
180
  declare const scoped: typeof tsyringe.scoped;
127
181
  declare const Lifecycle: typeof tsyringe.Lifecycle;
128
182
 
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
183
  declare function isModel(model: IConstructor<any>): (target: object, propertyKey: string | symbol) => void;
142
184
 
143
185
  declare function isOptional(): (target: object, propertyKey: string | symbol) => void;
@@ -341,18 +383,6 @@ declare class DescriptionMetadataStore {
341
383
  getModelDescriptions(model: IConstructor<any>): IDescriptionMetadata[];
342
384
  }
343
385
 
344
- interface ILockKey {
345
- run<T>(fn: () => Promise<T>): Promise<T>;
346
- tryRun<T>(fn: () => Promise<T>): Promise<T | undefined>;
347
- }
348
-
349
- interface ILocker {
350
- withKey(key: string | number): ILockKey;
351
- }
352
- declare class Locker implements ILocker {
353
- withKey(key: string | number): ILockKey;
354
- }
355
-
356
386
  interface ICommandConfig {
357
387
  name: string;
358
388
  }
@@ -471,9 +501,9 @@ declare class JobRepository implements IJobRepository {
471
501
 
472
502
  declare class JobRunner {
473
503
  private jobRepository;
474
- private handlerContainer;
504
+ private asyncMetadataStore;
475
505
  private logger;
476
- constructor(jobRepository: JobRepository, handlerContainer: AsyncMetadataStore);
506
+ constructor(jobRepository: JobRepository, asyncMetadataStore: AsyncMetadataStore);
477
507
  run(job: Job): Promise<void>;
478
508
  }
479
509
 
@@ -507,12 +537,24 @@ declare class JobScheduler {
507
537
  private tick;
508
538
  }
509
539
 
540
+ type IScheduleDelay = {
541
+ seconds: number;
542
+ } | {
543
+ minutes: number;
544
+ } | {
545
+ hours: number;
546
+ } | {
547
+ days: number;
548
+ };
549
+ type IScheduleAt = Date | IScheduleDelay;
510
550
  declare class Async {
511
551
  private jobRepository;
512
552
  private metadataStore;
513
553
  private jobScheduler;
514
554
  constructor(jobRepository: JobRepository, metadataStore: AsyncMetadataStore, jobScheduler: JobScheduler);
515
555
  runCommand<T>(ctor: IConstructor<T>, data: IValidateInputShape<T>): Promise<Job>;
556
+ scheduleCommand<T>(ctor: IConstructor<T>, data: IValidateInputShape<T>, scheduledAt: IScheduleAt): Promise<Job>;
557
+ private resolveScheduledDate;
516
558
  }
517
559
 
518
560
  interface ICronJobData extends IEntityData {
@@ -884,6 +926,8 @@ declare class ChatBotMetadataStore {
884
926
  getChatBotsMetadata(): IChatBotMetadata[];
885
927
  }
886
928
 
929
+ declare function safeJsonParse<T = unknown>(json: string | undefined | null, context?: string): T;
930
+
887
931
  interface IchatControllerConfig {
888
932
  }
889
933
 
@@ -906,6 +950,7 @@ interface IChannelMessage extends IReceivedMessage {
906
950
  interface IChatChannel {
907
951
  listen(callback: (received: IChannelMessage) => Promise<void>): void;
908
952
  connect(): void;
953
+ disconnect(): void;
909
954
  }
910
955
 
911
956
  interface IChannelMetadata {
@@ -928,10 +973,12 @@ declare class ControllerMetadataStore {
928
973
 
929
974
  declare class ChatResolver {
930
975
  private chatRepository;
931
- constructor(chatRepository: ChatRepository);
976
+ private locker;
977
+ constructor(chatRepository: ChatRepository, locker: Locker);
932
978
  resolve(connection: IChatConnection): Promise<Chat>;
933
979
  private resolveGroupChat;
934
980
  private resolvePrivateChat;
981
+ private buildLockKey;
935
982
  }
936
983
 
937
984
  interface IMessageContext extends IReceivedMessage {
@@ -1040,7 +1087,7 @@ declare class PgCrudRepository<P extends Entity<IEntityData>> extends PgReposito
1040
1087
  declare class PgLocker implements ILocker {
1041
1088
  private readonly pool;
1042
1089
  constructor(pool: Pool);
1043
- withKey(key: string | number): ILockKey;
1090
+ withKey(key: string | number | ILockerKey): ILockKey;
1044
1091
  }
1045
1092
 
1046
1093
  declare class PgLockKey implements ILockKey {
@@ -1147,13 +1194,20 @@ declare class RestRequest {
1147
1194
  headers?: Record<string, string>;
1148
1195
  }
1149
1196
 
1197
+ declare class SocketServerConfig {
1198
+ corsOrigin: string | string[];
1199
+ constructor(env: Env);
1200
+ }
1201
+
1150
1202
  declare class SocketServerProvider {
1151
1203
  private httpServerProvider;
1204
+ private config;
1152
1205
  private socketServer;
1153
1206
  private logger;
1154
- constructor(httpServerProvider: HttpServerProvider);
1207
+ constructor(httpServerProvider: HttpServerProvider, config: SocketServerConfig);
1155
1208
  getSocketServer(): Server$1;
1156
1209
  listen(): void;
1210
+ close(): void;
1157
1211
  private createSocketServer;
1158
1212
  }
1159
1213
 
@@ -1516,6 +1570,7 @@ declare class CmdChannel implements IChatChannel {
1516
1570
  private callBack;
1517
1571
  constructor(auth: Auth<any>);
1518
1572
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1573
+ disconnect(): void;
1519
1574
  connect(): void;
1520
1575
  }
1521
1576
  declare function writeJsonToFile<T>(filename: string, data: T): void;
@@ -1552,6 +1607,7 @@ declare class SocketChannel implements IChatChannel {
1552
1607
  private configController;
1553
1608
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1554
1609
  connect(): void;
1610
+ disconnect(): void;
1555
1611
  }
1556
1612
 
1557
1613
  interface ITelegramChannelConfig {
@@ -1570,6 +1626,7 @@ declare class TelegramChannel implements IChatChannel {
1570
1626
  constructor(config: TelegramChannelConfig);
1571
1627
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1572
1628
  connect(): void;
1629
+ disconnect(): void;
1573
1630
  }
1574
1631
 
1575
1632
  interface IWhatsappChannelConfig {
@@ -1638,6 +1695,7 @@ interface IListenWhatsAppMessageRequest {
1638
1695
  }
1639
1696
  declare class WhatsAppReceiver {
1640
1697
  connect(): Promise<void>;
1698
+ disconnect(): void;
1641
1699
  listenMessage(request: IListenWhatsAppMessageRequest): void;
1642
1700
  }
1643
1701
 
@@ -1735,6 +1793,7 @@ declare class WhatsAppChannel implements IChatChannel {
1735
1793
  constructor(config: WhatsappChannelConfig, sender: WhatsAppSender, receiver: WhatsAppReceiver);
1736
1794
  listen(callback: (message: IChannelMessage) => Promise<void>): void;
1737
1795
  connect(): void;
1796
+ disconnect(): void;
1738
1797
  }
1739
1798
 
1740
1799
  interface IWhatsAppCloudWebhookPayload {
@@ -1874,4 +1933,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
1874
1933
  new (): {};
1875
1934
  };
1876
1935
 
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 };
1936
+ 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 ILockerKey, 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 IScheduleAt, type IScheduleDelay, 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';