@wabot-dev/framework 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/README.md +9 -9
  2. package/dist/src/addon/auth/jwt/JwtGuardMiddleware.js +4 -1
  3. package/dist/src/addon/chat-bot/google/GoogleChatAdapter.js +5 -1
  4. package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannel.js +1 -1
  5. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js +3 -3
  6. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppSenderByCloudApi.js +1 -1
  7. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +1 -1
  8. package/dist/src/core/description/metadata/@description.js +1 -1
  9. package/dist/src/core/entity/Entity.js +3 -0
  10. package/dist/src/core/logger/Logger.js +30 -0
  11. package/dist/src/core/validation/metadata/@isArray.js +1 -1
  12. package/dist/src/core/validation/metadata/@isModel.js +1 -1
  13. package/dist/src/core/validation/validators/is-date/@isDate.js +1 -1
  14. package/dist/src/core/validation/validators/is-number/@isNumber.js +1 -1
  15. package/dist/src/core/validation/validators/is-string/@isString.js +1 -1
  16. package/dist/src/feature/async/Async.js +28 -4
  17. package/dist/src/feature/async/CronScheduler.js +3 -3
  18. package/dist/src/feature/async/JobRunner.js +1 -1
  19. package/dist/src/feature/async/JobScheduler.js +9 -6
  20. package/dist/src/feature/chat-bot/ChatMemory.js +2 -2
  21. package/dist/src/feature/http/HttpServerProvider.js +1 -1
  22. package/dist/src/feature/pg/PgLockKey.js +4 -4
  23. package/dist/src/feature/pg/PgLocker.js +1 -1
  24. package/dist/src/feature/rest-controller/runRestControllers.js +1 -1
  25. package/dist/src/feature/socket-controller/runSocketControllers.js +2 -2
  26. package/dist/src/index.d.ts +61 -15
  27. package/package.json +1 -1
package/README.md CHANGED
@@ -6,10 +6,9 @@
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
7
7
  [![Documentation](https://img.shields.io/badge/docs-wabot.dev-blue.svg?style=flat-square)](https://docs.wabot.dev)
8
8
 
9
-
10
9
  **Un framework moderno y flexible para crear bots con TypeScript e Inteligencia Artificial**
11
10
 
12
- [Documentación](https://docs.wabot.dev) • [Inicio Rápido](https://docs.wabot.dev/guides/start-new-project/)
11
+ [Documentación](https://docs.wabot.dev) • [Inicio Rápido](https://docs.wabot.dev/guides/start-new-project/)
13
12
 
14
13
  </div>
15
14
 
@@ -43,11 +42,11 @@ visita nuestra documentación 📘 **[Ver guía completa de inicio →](https://
43
42
 
44
43
  Wabot se integra nativamente con las principales plataformas de mensajería:
45
44
 
46
- | Plataforma | Estado |
47
- |------------|--------|
45
+ | Plataforma | Estado |
46
+ | --------------- | ------------ |
48
47
  | 📱 **WhatsApp** | ✅ Soportado |
49
48
  | ✈️ **Telegram** | ✅ Soportado |
50
- | 🔌 **Socket** | ✅ Soportado |
49
+ | 🔌 **Socket** | ✅ Soportado |
51
50
 
52
51
  ---
53
52
 
@@ -55,11 +54,12 @@ Wabot se integra nativamente con las principales plataformas de mensajería:
55
54
 
56
55
  Potencia tu bot con los principales proveedores de inteligencia artificial:
57
56
 
58
- | Proveedor | Soporte en Wabot |
59
- |-----------|------------------|
60
- | 🟢 **OpenAI** | ✅ Integración completa |
61
- | 🔵 **Google** | ✅ Integración completa |
57
+ | Proveedor | Soporte en Wabot |
58
+ | ---------------- | ----------------------- |
59
+ | 🟢 **OpenAI** | ✅ Integración completa |
60
+ | 🔵 **Google** | ✅ Integración completa |
62
61
  | 🟣 **Anthropic** | ✅ Integración completa |
62
+
63
63
  ---
64
64
 
65
65
  ## 📚 Documentación
@@ -20,7 +20,10 @@ let JwtGuardMiddleware = class JwtGuardMiddleware {
20
20
  }
21
21
  const parts = authorization.split(' ');
22
22
  if (parts.length !== 2) {
23
- throw new CustomError({ httpCode: 401, message: 'Authorization header must be: Bearer <token>' });
23
+ throw new CustomError({
24
+ httpCode: 401,
25
+ message: 'Authorization header must be: Bearer <token>',
26
+ });
24
27
  }
25
28
  const [bearer, token] = parts;
26
29
  if (bearer.toLowerCase() !== 'bearer') {
@@ -124,7 +124,11 @@ let GoogleChatAdapter = class GoogleChatAdapter {
124
124
  }
125
125
  nextItems.push({
126
126
  type: 'functionCall',
127
- functionCall: { id: id ?? Random.alphaNumericLowerCase(10), name, arguments: args && JSON.stringify(args) },
127
+ functionCall: {
128
+ id: id ?? Random.alphaNumericLowerCase(10),
129
+ name,
130
+ arguments: args && JSON.stringify(args),
131
+ },
128
132
  });
129
133
  }
130
134
  }
@@ -33,7 +33,7 @@ let WhatsAppChannel = class WhatsAppChannel {
33
33
  });
34
34
  }
35
35
  catch (err) {
36
- this.logger.error(err);
36
+ this.logger.error('Failed to handle WhatsApp message', err);
37
37
  }
38
38
  },
39
39
  });
@@ -33,7 +33,7 @@ class WhatsAppReceiverByCloudApi extends WhatsAppReceiver {
33
33
  res.status(200).send(challenge);
34
34
  }
35
35
  catch (e) {
36
- this.logger.error(e);
36
+ this.logger.error('WhatsApp webhook verification failed', e);
37
37
  res.sendStatus(500);
38
38
  return;
39
39
  }
@@ -66,7 +66,7 @@ class WhatsAppReceiverByCloudApi extends WhatsAppReceiver {
66
66
  }
67
67
  }
68
68
  catch (err) {
69
- this.logger.error(err);
69
+ this.logger.error('Failed to handle WhatsApp webhook payload', err);
70
70
  }
71
71
  }
72
72
  async emmitMessage(metadata, message, contact) {
@@ -75,7 +75,7 @@ class WhatsAppReceiverByCloudApi extends WhatsAppReceiver {
75
75
  return;
76
76
  }
77
77
  if (message.type !== 'text') {
78
- this.logger.error(`message type ${message.type} is not supported yet`);
78
+ this.logger.warn(`Message type '${message.type}' is not supported yet`);
79
79
  return;
80
80
  }
81
81
  const channelName = 'WhatsAppChannel';
@@ -114,7 +114,7 @@ let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSe
114
114
  return template;
115
115
  }
116
116
  catch (error) {
117
- this.logger.error(error);
117
+ this.logger.error('Failed to fetch WhatsApp template', error);
118
118
  throw error;
119
119
  }
120
120
  }
@@ -43,7 +43,7 @@ let WhatsAppSenderByWabotProxy = class WhatsAppSenderByWabotProxy extends WhatsA
43
43
  }
44
44
  }
45
45
  catch (err) {
46
- this.logger.error(err);
46
+ this.logger.error(`Failed to send WhatsApp from '${request.from}' to '${request.to}'`, err);
47
47
  throw new Error(undefined, { cause: err });
48
48
  }
49
49
  }
@@ -13,7 +13,7 @@ function description(description) {
13
13
  propertyType,
14
14
  functionArgsTypes,
15
15
  functionReturnType: undefined,
16
- description
16
+ description,
17
17
  });
18
18
  };
19
19
  }
@@ -46,6 +46,9 @@ class Entity extends Storable {
46
46
  throw new Error('createdAt is required');
47
47
  }
48
48
  }
49
+ lockerKey() {
50
+ return this.id;
51
+ }
49
52
  }
50
53
  /**
51
54
  * @deprecated Should use Entity
@@ -13,6 +13,30 @@ const levelToSeverity = {
13
13
  error: 'error',
14
14
  fatal: 'fatal',
15
15
  };
16
+ /**
17
+ * Logger with 6 severity levels. Uses the `debug` library for output.
18
+ *
19
+ * ## Level verbosity contract
20
+ *
21
+ * - **fatal** — The process cannot continue. Something is critically broken
22
+ * (uncaught exceptions, unhandled rejections). Investigate immediately.
23
+ *
24
+ * - **error** — An operation failed unexpectedly. Always include: what failed,
25
+ * why (the Error), and enough context to locate the problem (IDs, names).
26
+ *
27
+ * - **warn** — Something unusual happened but the system handled it gracefully.
28
+ * Known limitations, safety guards triggered, recoverable issues.
29
+ *
30
+ * - **info** — Key lifecycle events the user cares about: systems starting or
31
+ * stopping, configuration applied, significant state changes. Should read
32
+ * like a high-level audit log.
33
+ *
34
+ * - **debug** — Internal operational details for developers troubleshooting.
35
+ * Step-by-step flow, lock acquisition, query execution, reconciliation steps.
36
+ *
37
+ * - **trace** — Very fine-grained: every HTTP request, every socket event,
38
+ * every message sent or received.
39
+ */
16
40
  class Logger {
17
41
  static monitor = null;
18
42
  debuggers;
@@ -32,21 +56,27 @@ class Logger {
32
56
  static getMonitor() {
33
57
  return Logger.monitor;
34
58
  }
59
+ /** Very fine-grained: every HTTP request, socket event, message sent/received. */
35
60
  trace(...args) {
36
61
  this.log('trace', args);
37
62
  }
63
+ /** Internal operational details for developers: step-by-step flow, lock acquisition, queries. */
38
64
  debug(...args) {
39
65
  this.log('debug', args);
40
66
  }
67
+ /** Key lifecycle events: systems start/stop, configuration applied, significant state changes. */
41
68
  info(...args) {
42
69
  this.log('info', args);
43
70
  }
71
+ /** Something unusual happened but the system recovered. Known limitations, safety guards. */
44
72
  warn(...args) {
45
73
  this.log('warn', args);
46
74
  }
75
+ /** Operation failed unexpectedly. Always include: what failed + why (Error) + identifiers. */
47
76
  error(...args) {
48
77
  this.log('error', args);
49
78
  }
79
+ /** Process cannot continue. Uncaught exceptions, unhandled rejections. Investigate immediately. */
50
80
  fatal(...args) {
51
81
  this.log('fatal', args);
52
82
  }
@@ -11,7 +11,7 @@ function isArray(options) {
11
11
  propertyName,
12
12
  validator: validateArray,
13
13
  validatorOptions: options,
14
- typeDescriptor: 'array'
14
+ typeDescriptor: 'array',
15
15
  });
16
16
  };
17
17
  }
@@ -11,7 +11,7 @@ function isModel(model) {
11
11
  propertyName,
12
12
  validator: validateModel,
13
13
  validatorOptions: store.getModelValidatorsInfo(model),
14
- typeDescriptor: 'object'
14
+ typeDescriptor: 'object',
15
15
  });
16
16
  };
17
17
  }
@@ -10,7 +10,7 @@ function isDate() {
10
10
  modelConstructor: target.constructor,
11
11
  propertyName,
12
12
  validator: validateIsDate,
13
- typeDescriptor: 'date'
13
+ typeDescriptor: 'date',
14
14
  });
15
15
  };
16
16
  }
@@ -10,7 +10,7 @@ function isNumber() {
10
10
  modelConstructor: target.constructor,
11
11
  propertyName,
12
12
  validator: validateIsNumber,
13
- typeDescriptor: 'number'
13
+ typeDescriptor: 'number',
14
14
  });
15
15
  };
16
16
  }
@@ -10,7 +10,7 @@ function isString() {
10
10
  modelConstructor: target.constructor,
11
11
  propertyName,
12
12
  validator: validateIsString,
13
- typeDescriptor: 'string'
13
+ typeDescriptor: 'string',
14
14
  });
15
15
  };
16
16
  }
@@ -17,23 +17,47 @@ let Async = class Async {
17
17
  this.jobScheduler = jobScheduler;
18
18
  }
19
19
  async runCommand(ctor, data) {
20
+ const job = await this.scheduleCommand(ctor, data, new Date());
21
+ this.jobScheduler.tryExecuteNow(job);
22
+ return job;
23
+ }
24
+ async scheduleCommand(ctor, data, scheduledAt) {
20
25
  const commandName = this.metadataStore.getCommandName(ctor);
21
26
  if (!commandName) {
22
27
  throw new Error(`${ctor.name} is not registered as command`);
23
28
  }
24
29
  const { error, value: commandData } = validateAndTransform(data, ctor);
25
- if (!commandData) {
26
- throw new Error('Invalid command data');
30
+ if (error) {
31
+ throw new Error(`Validation failed: ${error.description}`);
27
32
  }
33
+ const scheduledDate = this.resolveScheduledDate(scheduledAt);
28
34
  const job = new Job({
29
35
  commandName,
30
36
  commandData,
31
- scheduledAt: new Date().getTime(),
37
+ scheduledAt: scheduledDate.getTime(),
32
38
  });
33
39
  await this.jobRepository.create(job);
34
- this.jobScheduler.tryExecuteNow(job);
35
40
  return job;
36
41
  }
42
+ resolveScheduledDate(scheduledAt) {
43
+ if (scheduledAt instanceof Date) {
44
+ return scheduledAt;
45
+ }
46
+ const now = new Date();
47
+ if ('seconds' in scheduledAt) {
48
+ return new Date(now.getTime() + scheduledAt.seconds * 1000);
49
+ }
50
+ if ('minutes' in scheduledAt) {
51
+ return new Date(now.getTime() + scheduledAt.minutes * 60 * 1000);
52
+ }
53
+ if ('hours' in scheduledAt) {
54
+ return new Date(now.getTime() + scheduledAt.hours * 60 * 60 * 1000);
55
+ }
56
+ if ('days' in scheduledAt) {
57
+ return new Date(now.getTime() + scheduledAt.days * 24 * 60 * 60 * 1000);
58
+ }
59
+ throw new Error('Invalid schedule delay format');
60
+ }
37
61
  };
38
62
  Async = __decorate([
39
63
  singleton(),
@@ -60,12 +60,12 @@ let CronScheduler = class CronScheduler {
60
60
  this.logger.debug(`start reconciliation of crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
61
61
  try {
62
62
  const cronJobs = await Promise.all(configToReconciliate.map((x) => this.reconciliateConfig(x)));
63
- this.logger.info(`success reconciliation of reconciliation of crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
63
+ this.logger.info(`Cron reconciliation succeeded for ${configToReconciliate.map((x) => x.name).join(', ')}`);
64
64
  this.jobScheduler.start(cronJobs.map((x) => x.commandName));
65
65
  this.jobWatchdog.start(cronJobs.map((x) => x.commandName));
66
66
  }
67
67
  catch (e) {
68
- this.logger.error(e);
68
+ this.logger.error('Cron reconciliation failed', e);
69
69
  this.stop(configToReconciliate);
70
70
  this.logger.error(`reconciliation fail - stopped crons ${configToReconciliate.map((x) => x.name).join(', ')}`);
71
71
  throw e;
@@ -88,7 +88,7 @@ let CronScheduler = class CronScheduler {
88
88
  });
89
89
  }
90
90
  catch (e) {
91
- this.logger.error(e);
91
+ this.logger.error('Cron tick failed', e);
92
92
  }
93
93
  finally {
94
94
  this.timeout = setTimeout(() => this.tick(), interval * 1000);
@@ -45,7 +45,7 @@ let JobRunner = class JobRunner {
45
45
  job.setAsSuccess();
46
46
  }
47
47
  catch (e) {
48
- this.logger.error(e);
48
+ this.logger.error(`Failed to run command '${job.commandName}'`, e);
49
49
  job.setAsFailed(e instanceof Error ? e : new Error('Invalid Job error'));
50
50
  }
51
51
  finally {
@@ -22,16 +22,15 @@ let JobScheduler = class JobScheduler {
22
22
  this.env = env;
23
23
  }
24
24
  start(commands) {
25
- this.logger.info(`starting handlers for commands ${commands}`);
26
25
  commands.forEach((x) => this.commands.add(x));
27
- this.logger.info(`starting job handlers for commands ${commands.join(', ')}`);
26
+ this.logger.info(`Starting job handlers for commands ${commands.join(', ')}`);
28
27
  if (this.commands.size > 0 && !this.running) {
29
28
  this.running = true;
30
29
  this.tick();
31
30
  }
32
31
  }
33
32
  stop(commands) {
34
- this.logger.info(`stoping handlers for commands ${commands}`);
33
+ this.logger.info(`Stopping job handlers for commands ${commands.join(', ')}`);
35
34
  commands.forEach((x) => this.commands.delete(x));
36
35
  if (this.commands.size === 0) {
37
36
  this.running = false;
@@ -42,7 +41,9 @@ let JobScheduler = class JobScheduler {
42
41
  }
43
42
  tryExecuteNow(job) {
44
43
  if (this.commands.has(job.commandName))
45
- this.executor.execute(job).catch((e) => this.logger.error(e));
44
+ this.executor
45
+ .execute(job)
46
+ .catch((e) => this.logger.error(`Failed to execute job ${job.id}`, e));
46
47
  }
47
48
  async tick() {
48
49
  if (!this.running)
@@ -57,12 +58,14 @@ let JobScheduler = class JobScheduler {
57
58
  await this.locker.withKey('wabot-job-scheduler-loop').run(async () => {
58
59
  const jobs = await this.repo.findPendingForRunFrom(new Date(), this.executor.remainingSlots());
59
60
  const readyToRunJobs = jobs.filter((job) => this.commands.has(job.commandName) && job.isScheduleReady());
60
- readyToRunJobs.forEach((j) => this.executor.execute(j).catch((e) => this.logger.error(e)));
61
+ readyToRunJobs.forEach((j) => this.executor
62
+ .execute(j)
63
+ .catch((e) => this.logger.error(`Failed to execute job ${j.id}`, e)));
61
64
  await new Promise((r) => setTimeout(r, 10));
62
65
  });
63
66
  }
64
67
  catch (e) {
65
- this.logger.error(e);
68
+ this.logger.error('Job scheduler tick failed', e);
66
69
  }
67
70
  finally {
68
71
  this.timeout = setTimeout(() => this.tick(), interval * 1000);
@@ -1,9 +1,9 @@
1
1
  class ChatMemory {
2
2
  findLastItems(count) {
3
- throw new Error("Method not implemented.");
3
+ throw new Error('Method not implemented.');
4
4
  }
5
5
  create(item) {
6
- throw new Error("Method not implemented.");
6
+ throw new Error('Method not implemented.');
7
7
  }
8
8
  }
9
9
 
@@ -20,7 +20,7 @@ let HttpServerProvider = class HttpServerProvider {
20
20
  this.listening = true;
21
21
  const PORT = process.env.PORT || 3000;
22
22
  this.server.listen(PORT, () => {
23
- this.logger.info(`server listenig on port ${PORT}`);
23
+ this.logger.info(`Server listening on port ${PORT}`);
24
24
  });
25
25
  }
26
26
  };
@@ -16,9 +16,9 @@ class PgLockKey {
16
16
  return withPgClient(this.pool, async (client) => {
17
17
  let locked = false;
18
18
  try {
19
- this.logger.debug(`try to adquire ${this.key}`);
19
+ this.logger.debug(`try to acquire ${this.key}`);
20
20
  await client.query('SELECT pg_advisory_lock($1)', [this.value]);
21
- this.logger.debug(`adquired ${this.key}`);
21
+ this.logger.debug(`acquired ${this.key}`);
22
22
  locked = true;
23
23
  return await fn();
24
24
  }
@@ -27,7 +27,7 @@ class PgLockKey {
27
27
  this.logger.debug(`try to release ${this.key}`);
28
28
  const res = await client.query('SELECT pg_advisory_unlock($1) AS unlocked', [this.value]);
29
29
  if (!res.rows[0]?.unlocked) {
30
- this.logger.error('error - no unlock');
30
+ this.logger.error(`Failed to release lock '${this.key}'`);
31
31
  }
32
32
  else {
33
33
  this.logger.debug(`released ${this.key}`);
@@ -50,7 +50,7 @@ class PgLockKey {
50
50
  if (locked) {
51
51
  const res = await client.query('SELECT pg_advisory_unlock($1) AS unlocked', [this.value]);
52
52
  if (!res.rows[0]?.unlocked) {
53
- this.logger.error('error - no unlock');
53
+ this.logger.error(`Failed to release lock '${this.key}'`);
54
54
  }
55
55
  }
56
56
  }
@@ -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([
@@ -68,7 +68,7 @@ function runRestControllers(controllers) {
68
68
  res.status(200).json(response ?? null);
69
69
  }
70
70
  catch (err) {
71
- logger.error(err);
71
+ logger.error(`${method.toUpperCase()} ${route} failed`, err);
72
72
  if (err instanceof Error) {
73
73
  const keys = Object.keys(err).filter((key) => !['message', 'stack'].includes(key));
74
74
  const { httpCode, ...info } = keys.reduce((acc, key) => {
@@ -70,7 +70,7 @@ function runSocketControllers(controllers) {
70
70
  }
71
71
  }
72
72
  catch (err) {
73
- logger.error(err);
73
+ logger.error(`Event '${event.config.event}' on '${namespace}' failed`, err);
74
74
  if (err instanceof Error) {
75
75
  const keys = Object.keys(err).filter((key) => !['message', 'stack'].includes(key));
76
76
  const { httpCode, ...info } = keys.reduce((acc, key) => {
@@ -108,7 +108,7 @@ function runSocketControllers(controllers) {
108
108
  }
109
109
  }
110
110
  catch (err) {
111
- logger.error(err);
111
+ logger.error(`Connection setup on '${namespace}' failed`, err);
112
112
  socket.disconnect();
113
113
  connectionContainer.dispose();
114
114
  }
@@ -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
@@ -113,6 +129,30 @@ interface IErrorMonitor {
113
129
  captureMessage(message: string, context: IErrorMonitorContext): void;
114
130
  }
115
131
 
132
+ /**
133
+ * Logger with 6 severity levels. Uses the `debug` library for output.
134
+ *
135
+ * ## Level verbosity contract
136
+ *
137
+ * - **fatal** — The process cannot continue. Something is critically broken
138
+ * (uncaught exceptions, unhandled rejections). Investigate immediately.
139
+ *
140
+ * - **error** — An operation failed unexpectedly. Always include: what failed,
141
+ * why (the Error), and enough context to locate the problem (IDs, names).
142
+ *
143
+ * - **warn** — Something unusual happened but the system handled it gracefully.
144
+ * Known limitations, safety guards triggered, recoverable issues.
145
+ *
146
+ * - **info** — Key lifecycle events the user cares about: systems starting or
147
+ * stopping, configuration applied, significant state changes. Should read
148
+ * like a high-level audit log.
149
+ *
150
+ * - **debug** — Internal operational details for developers troubleshooting.
151
+ * Step-by-step flow, lock acquisition, query execution, reconciliation steps.
152
+ *
153
+ * - **trace** — Very fine-grained: every HTTP request, every socket event,
154
+ * every message sent or received.
155
+ */
116
156
  declare class Logger {
117
157
  private static monitor;
118
158
  private debuggers;
@@ -120,11 +160,17 @@ declare class Logger {
120
160
  constructor(name: string);
121
161
  static setMonitor(monitor: IErrorMonitor): void;
122
162
  static getMonitor(): IErrorMonitor | null;
163
+ /** Very fine-grained: every HTTP request, socket event, message sent/received. */
123
164
  trace(...args: any[]): void;
165
+ /** Internal operational details for developers: step-by-step flow, lock acquisition, queries. */
124
166
  debug(...args: any[]): void;
167
+ /** Key lifecycle events: systems start/stop, configuration applied, significant state changes. */
125
168
  info(...args: any[]): void;
169
+ /** Something unusual happened but the system recovered. Known limitations, safety guards. */
126
170
  warn(...args: any[]): void;
171
+ /** Operation failed unexpectedly. Always include: what failed + why (Error) + identifiers. */
127
172
  error(...args: any[]): void;
173
+ /** Process cannot continue. Uncaught exceptions, unhandled rejections. Investigate immediately. */
128
174
  fatal(...args: any[]): void;
129
175
  private log;
130
176
  private sendToMonitor;
@@ -367,18 +413,6 @@ declare class DescriptionMetadataStore {
367
413
  getModelDescriptions(model: IConstructor<any>): IDescriptionMetadata[];
368
414
  }
369
415
 
370
- interface ILockKey {
371
- run<T>(fn: () => Promise<T>): Promise<T>;
372
- tryRun<T>(fn: () => Promise<T>): Promise<T | undefined>;
373
- }
374
-
375
- interface ILocker {
376
- withKey(key: string | number): ILockKey;
377
- }
378
- declare class Locker implements ILocker {
379
- withKey(key: string | number): ILockKey;
380
- }
381
-
382
416
  interface ICommandConfig {
383
417
  name: string;
384
418
  }
@@ -533,12 +567,24 @@ declare class JobScheduler {
533
567
  private tick;
534
568
  }
535
569
 
570
+ type IScheduleDelay = {
571
+ seconds: number;
572
+ } | {
573
+ minutes: number;
574
+ } | {
575
+ hours: number;
576
+ } | {
577
+ days: number;
578
+ };
579
+ type IScheduleAt = Date | IScheduleDelay;
536
580
  declare class Async {
537
581
  private jobRepository;
538
582
  private metadataStore;
539
583
  private jobScheduler;
540
584
  constructor(jobRepository: JobRepository, metadataStore: AsyncMetadataStore, jobScheduler: JobScheduler);
541
585
  runCommand<T>(ctor: IConstructor<T>, data: IValidateInputShape<T>): Promise<Job>;
586
+ scheduleCommand<T>(ctor: IConstructor<T>, data: IValidateInputShape<T>, scheduledAt: IScheduleAt): Promise<Job>;
587
+ private resolveScheduledDate;
542
588
  }
543
589
 
544
590
  interface ICronJobData extends IEntityData {
@@ -1071,7 +1117,7 @@ declare class PgCrudRepository<P extends Entity<IEntityData>> extends PgReposito
1071
1117
  declare class PgLocker implements ILocker {
1072
1118
  private readonly pool;
1073
1119
  constructor(pool: Pool);
1074
- withKey(key: string | number): ILockKey;
1120
+ withKey(key: string | number | ILockerKey): ILockKey;
1075
1121
  }
1076
1122
 
1077
1123
  declare class PgLockKey implements ILockKey {
@@ -1917,4 +1963,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
1917
1963
  new (): {};
1918
1964
  };
1919
1965
 
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 };
1966
+ 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wabot-dev/framework",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Framework for IA Chat Bots",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",