@wabot-dev/framework 0.9.1 → 0.9.5

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 (84) hide show
  1. package/dist/src/addon/async/in-memory/InMemoryCronJobRepository.js +45 -0
  2. package/dist/src/addon/async/in-memory/InMemoryJobRepository.js +75 -0
  3. package/dist/src/addon/async/in-memory/index.js +2 -0
  4. package/dist/src/addon/async/pg/PgCronJobRepository.js +7 -5
  5. package/dist/src/addon/async/pg/PgJobRepository.js +8 -5
  6. package/dist/src/addon/async/pg/PgTransactionAdapter.js +25 -0
  7. package/dist/src/addon/async/pg/index.js +3 -0
  8. package/dist/src/addon/auth/api-key/ApiKey.js +4 -4
  9. package/dist/src/addon/auth/api-key/PgApiKeyRepository.js +9 -8
  10. package/dist/src/addon/auth/jwt/JwtRefreshToken.js +4 -4
  11. package/dist/src/addon/auth/jwt/PgJwtRefreshTokenRepository.js +6 -5
  12. package/dist/src/addon/chat-bot/{ram/RamChatMemory.js → in-memory/InMemoryChatMemory.js} +2 -2
  13. package/dist/src/addon/chat-bot/{ram/RamChatRepository.js → in-memory/InMemoryChatRepository.js} +6 -6
  14. package/dist/src/addon/chat-bot/in-memory/index.js +2 -0
  15. package/dist/src/addon/chat-bot/pg/PgChatMemory.js +8 -7
  16. package/dist/src/addon/chat-bot/pg/PgChatRepository.js +7 -6
  17. package/dist/src/addon/chat-bot/pg/index.js +2 -0
  18. package/dist/src/addon/chat-controller/cmd/@cmd.js +7 -2
  19. package/dist/src/addon/chat-controller/cmd/CmdChannel.js +85 -61
  20. package/dist/src/addon/chat-controller/cmd/CmdChannelConfig.js +8 -0
  21. package/dist/src/addon/chat-controller/cmd/CmdChannelServer.js +169 -0
  22. package/dist/src/addon/chat-controller/cmd/cmdChannelSocketPath.js +16 -0
  23. package/dist/src/addon/chat-controller/cmd/runCmdClient.js +226 -0
  24. package/dist/src/addon/chat-controller/socket/@socket.js +3 -1
  25. package/dist/src/addon/chat-controller/socket/SocketChannelConfig.js +4 -4
  26. package/dist/src/addon/chat-controller/whatsapp/WhatsAppSender.js +2 -72
  27. package/dist/src/addon/chat-controller/whatsapp/{WhatsAppReceiver.js → cloud-api/WhatsAppApiReceiver.js} +2 -2
  28. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppApiSender.js +67 -0
  29. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js +5 -7
  30. package/dist/src/addon/chat-controller/whatsapp/wasender/@wasender.js +23 -0
  31. package/dist/src/addon/chat-controller/{wasender/WhatsAppByWasenderChannel.js → whatsapp/wasender/WasenderChannel.js} +20 -20
  32. package/dist/src/addon/chat-controller/{wasender/WhatsAppByWasenderChannelConfig.js → whatsapp/wasender/WasenderChannelConfig.js} +3 -3
  33. package/dist/src/addon/chat-controller/whatsapp/wasender/WasenderChannelName.js +3 -0
  34. package/dist/src/addon/chat-controller/{wasender/WhatsAppReceiverByWasender.js → whatsapp/wasender/WasenderReceiver.js} +7 -7
  35. package/dist/src/addon/chat-controller/{wasender/WhatsAppSenderByWasender.js → whatsapp/wasender/WasenderSender.js} +8 -5
  36. package/dist/src/addon/chat-controller/{wasender → whatsapp/wasender}/WasenderWebhookController.js +4 -4
  37. package/dist/src/addon/lock/InMemoryLockKey.js +45 -0
  38. package/dist/src/addon/lock/InMemoryLocker.js +15 -0
  39. package/dist/src/addon/lock/index.js +2 -0
  40. package/dist/src/core/repository/CrudRepository.js +25 -0
  41. package/dist/src/feature/async/{@cron.js → @cronHandler.js} +2 -2
  42. package/dist/src/feature/async/@transaction.js +22 -0
  43. package/dist/src/feature/async/AsyncMetadataStore.js +6 -0
  44. package/dist/src/feature/async/TransactionMetadataStore.js +28 -0
  45. package/dist/src/feature/chat-controller/metadata/ControllerMetadataStore.js +3 -0
  46. package/dist/src/feature/pg/@pgExtension.js +33 -0
  47. package/dist/src/feature/pg/PgJsonRepositoryAdapter.js +50 -0
  48. package/dist/src/feature/pg/index.js +10 -0
  49. package/dist/src/feature/project-runner/ProjectRunner.js +276 -0
  50. package/dist/src/feature/repository/@memoryExtension.js +29 -0
  51. package/dist/src/feature/repository/@query.js +22 -0
  52. package/dist/src/feature/repository/@queryExtension.js +21 -0
  53. package/dist/src/feature/repository/@repository.js +170 -0
  54. package/dist/src/feature/repository/MemoryRepositoryAdapter.js +110 -0
  55. package/dist/src/feature/repository/RepositoryAdapterRegistry.js +27 -0
  56. package/dist/src/feature/repository/RepositoryMetadataStore.js +102 -0
  57. package/dist/src/feature/repository/evaluateQueryAst.js +134 -0
  58. package/dist/src/feature/rest-controller/metadata/RestControllerMetadataStore.js +3 -0
  59. package/dist/src/feature/socket-controller/metadata/SocketControllerMetadataStore.js +3 -0
  60. package/dist/src/index.d.ts +377 -298
  61. package/dist/src/index.js +40 -34
  62. package/package.json +9 -7
  63. package/dist/src/addon/chat-controller/wasender/@whatsAppByWasender.js +0 -20
  64. package/dist/src/addon/chat-controller/wasender/whatsAppByWasenderChannelName.js +0 -3
  65. package/dist/src/addon/chat-controller/whatsapp/@whatsApp.js +0 -20
  66. package/dist/src/addon/chat-controller/whatsapp/EnvWhatsAppRepository.js +0 -49
  67. package/dist/src/addon/chat-controller/whatsapp/PgWhatsAppRepository.js +0 -48
  68. package/dist/src/addon/chat-controller/whatsapp/WhatsApp.js +0 -30
  69. package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannel.js +0 -58
  70. package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannelConfig.js +0 -8
  71. package/dist/src/addon/chat-controller/whatsapp/WhatsAppRepository.js +0 -10
  72. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppSenderByCloudApi.js +0 -133
  73. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppProxyContracts.js +0 -5
  74. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppReceiverByWabotProxy.js +0 -67
  75. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +0 -63
  76. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppWabotProxyConnection.js +0 -45
  77. package/dist/src/feature/pg/query/@pgJsonRepository.js +0 -73
  78. package/dist/src/feature/pg/query/@query.js +0 -14
  79. package/dist/src/feature/pg/query/PgJsonRepository.js +0 -23
  80. package/dist/src/feature/pg/query/PgRepositoryMetadataStore.js +0 -44
  81. /package/dist/src/addon/chat-controller/whatsapp/{whatsAppChannelName.js → cloud-api/whatsAppChannelName.js} +0 -0
  82. /package/dist/src/addon/chat-controller/{wasender → whatsapp/wasender}/extractNumberFromWasenderKey.js +0 -0
  83. /package/dist/src/feature/pg/{query/buildQuerySql.js → buildQuerySql.js} +0 -0
  84. /package/dist/src/feature/{pg/query → repository}/parseQueryMethodName.js +0 -0
@@ -0,0 +1,45 @@
1
+ import { __decorate } from 'tslib';
2
+ import { generate } from 'short-uuid';
3
+ import { singleton } from '../../../core/injection/index.js';
4
+
5
+ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
6
+ items = new Map();
7
+ async create(cronJob) {
8
+ if (cronJob.wasCreated())
9
+ throw new Error('CronJob already created');
10
+ cronJob['data'].id = generate();
11
+ cronJob['data'].createdAt = new Date().getTime();
12
+ cronJob.validate();
13
+ this.items.set(cronJob.id, cronJob);
14
+ }
15
+ async findDue(date) {
16
+ const now = (date ?? new Date()).getTime();
17
+ return [...this.items.values()]
18
+ .filter((c) => c['data'].enabled && c['data'].nextRunAt != null && c['data'].nextRunAt <= now)
19
+ .sort((a, b) => (a['data'].nextRunAt ?? 0) - (b['data'].nextRunAt ?? 0));
20
+ }
21
+ async findOrThrow(id) {
22
+ const item = this.items.get(id);
23
+ if (!item)
24
+ throw new Error(`CronJob with id = '${id}' not found`);
25
+ return item;
26
+ }
27
+ async update(cronJob) {
28
+ if (!cronJob.wasCreated())
29
+ throw new Error('CronJob was not created');
30
+ cronJob.validate();
31
+ this.items.set(cronJob.id, cronJob);
32
+ }
33
+ async findByName(name) {
34
+ for (const c of this.items.values()) {
35
+ if (c['data'].name === name)
36
+ return c;
37
+ }
38
+ return null;
39
+ }
40
+ };
41
+ InMemoryCronJobRepository = __decorate([
42
+ singleton()
43
+ ], InMemoryCronJobRepository);
44
+
45
+ export { InMemoryCronJobRepository };
@@ -0,0 +1,75 @@
1
+ import { __decorate } from 'tslib';
2
+ import { generate } from 'short-uuid';
3
+ import { singleton } from '../../../core/injection/index.js';
4
+
5
+ let InMemoryJobRepository = class InMemoryJobRepository {
6
+ items = new Map();
7
+ async find(id) {
8
+ return this.items.get(id) ?? null;
9
+ }
10
+ async findOrThrow(id) {
11
+ const item = this.items.get(id);
12
+ if (!item)
13
+ throw new Error(`Job with id = '${id}' not found`);
14
+ return item;
15
+ }
16
+ async findByIds(ids) {
17
+ return ids.map((id) => this.items.get(id)).filter((j) => j != null);
18
+ }
19
+ async findAll() {
20
+ return [...this.items.values()];
21
+ }
22
+ async create(item) {
23
+ if (item.wasCreated())
24
+ throw new Error('Job already created');
25
+ item['data'].id = generate();
26
+ item['data'].createdAt = new Date().getTime();
27
+ item.validate();
28
+ this.items.set(item.id, item);
29
+ }
30
+ async update(item) {
31
+ if (!item.wasCreated())
32
+ throw new Error('Job was not created');
33
+ item.validate();
34
+ this.items.set(item.id, item);
35
+ }
36
+ async delete(item) {
37
+ this.items.delete(item.id);
38
+ }
39
+ async findPendingForRunFrom(date, limit) {
40
+ const now = date.getTime();
41
+ return [...this.items.values()]
42
+ .filter((j) => j['data'].scheduledAt != null &&
43
+ j['data'].scheduledAt <= now &&
44
+ j['data'].startedAt == null &&
45
+ j['data'].successAt == null &&
46
+ j['data'].failedAt == null)
47
+ .sort((a, b) => (a['data'].scheduledAt ?? 0) - (b['data'].scheduledAt ?? 0))
48
+ .slice(0, limit);
49
+ }
50
+ async findRunningJobs() {
51
+ return [...this.items.values()].filter((j) => {
52
+ if (j['data'].successAt != null || j['data'].failedAt != null)
53
+ return false;
54
+ return j['data'].scheduledAt != null && j['data'].startedAt != null;
55
+ });
56
+ }
57
+ async countRunningByCommand(commandName) {
58
+ let count = 0;
59
+ for (const j of this.items.values()) {
60
+ if (j['data'].commandName !== commandName)
61
+ continue;
62
+ if (j['data'].successAt != null || j['data'].failedAt != null)
63
+ continue;
64
+ if (j['data'].scheduledAt != null && j['data'].startedAt != null) {
65
+ count++;
66
+ }
67
+ }
68
+ return count;
69
+ }
70
+ };
71
+ InMemoryJobRepository = __decorate([
72
+ singleton()
73
+ ], InMemoryJobRepository);
74
+
75
+ export { InMemoryJobRepository };
@@ -0,0 +1,2 @@
1
+ export { InMemoryJobRepository } from './InMemoryJobRepository.js';
2
+ export { InMemoryCronJobRepository } from './InMemoryCronJobRepository.js';
@@ -1,14 +1,16 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
3
  import { CronJob } from '../../../feature/async/CronJob.js';
4
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
5
- import '../../../feature/pg/PgLocker.js';
4
+ import 'short-uuid';
5
+ import '../../../core/error/setupErrorHandlers.js';
6
+ import '../../../feature/repository/RepositoryMetadataStore.js';
7
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
+ import '../../../feature/pg/withPgClient.js';
6
9
  import 'debug';
10
+ import '../../../feature/pg/PgLocker.js';
11
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
7
12
  import 'node:crypto';
8
- import '../../../feature/pg/withPgClient.js';
9
13
  import '../../../feature/pg/pgStorage.js';
10
- import '../../../feature/pg/query/PgJsonRepository.js';
11
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
12
14
  import { Pool } from 'pg';
13
15
 
14
16
  let PgCronJobRepository = class PgCronJobRepository extends PgCrudRepository {
@@ -1,15 +1,18 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
5
- import '../../../feature/pg/PgLocker.js';
4
+ import 'short-uuid';
5
+ import '../../../core/error/setupErrorHandlers.js';
6
+ import '../../../feature/repository/RepositoryMetadataStore.js';
7
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
+ import { withPgClient } from '../../../feature/pg/withPgClient.js';
6
9
  import 'debug';
10
+ import '../../../feature/pg/PgLocker.js';
11
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
7
12
  import 'node:crypto';
8
- import { withPgClient } from '../../../feature/pg/withPgClient.js';
9
13
  import '../../../feature/pg/pgStorage.js';
10
- import '../../../feature/pg/query/PgJsonRepository.js';
11
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
12
14
  import '../../../feature/async/AsyncMetadataStore.js';
15
+ import '../../../feature/async/TransactionMetadataStore.js';
13
16
  import '../../../feature/async/Async.js';
14
17
  import '../../../_virtual/index.js';
15
18
  import { Job } from '../../../feature/async/Job.js';
@@ -0,0 +1,25 @@
1
+ import '../../../core/injection/index.js';
2
+ import 'short-uuid';
3
+ import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/RepositoryMetadataStore.js';
5
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
+ import { withPgClient } from '../../../feature/pg/withPgClient.js';
7
+ import 'debug';
8
+ import '../../../feature/pg/PgLocker.js';
9
+ import 'node:crypto';
10
+ import '../../../feature/pg/pgStorage.js';
11
+ import { withPgTransaction } from '../../../feature/pg/withPgTransaction.js';
12
+
13
+ class PgTransactionAdapter {
14
+ pool;
15
+ constructor(pool) {
16
+ this.pool = pool;
17
+ }
18
+ async run(fn) {
19
+ return withPgClient(this.pool, () => withPgTransaction(this.pool, async () => {
20
+ return await fn();
21
+ }));
22
+ }
23
+ }
24
+
25
+ export { PgTransactionAdapter };
@@ -0,0 +1,3 @@
1
+ export { PgCronJobRepository } from './PgCronJobRepository.js';
2
+ export { PgJobRepository } from './PgJobRepository.js';
3
+ export { PgTransactionAdapter } from './PgTransactionAdapter.js';
@@ -1,12 +1,12 @@
1
1
  import { Entity } from '../../../core/entity/Entity.js';
2
2
  import { CustomError } from '../../../core/error/CustomError.js';
3
3
  import '../../../core/error/setupErrorHandlers.js';
4
- import crypto from 'node:crypto';
4
+ import crypto__default from 'node:crypto';
5
5
 
6
6
  class ApiKey extends Entity {
7
7
  static PREFIX = 'sk_';
8
8
  static hashSecret(secret) {
9
- return crypto.createHash('sha256').update(secret).digest('hex');
9
+ return crypto__default.createHash('sha256').update(secret).digest('hex');
10
10
  }
11
11
  get authInfo() {
12
12
  return this.data.authInfo;
@@ -24,7 +24,7 @@ class ApiKey extends Entity {
24
24
  if (this.data.secretHash) {
25
25
  throw new Error('This API key already has a secret');
26
26
  }
27
- const secret = `${ApiKey.PREFIX}${crypto.randomBytes(32).toString('hex')}`;
27
+ const secret = `${ApiKey.PREFIX}${crypto__default.randomBytes(32).toString('hex')}`;
28
28
  this.data.secretHash = ApiKey.hashSecret(secret);
29
29
  return secret;
30
30
  }
@@ -37,7 +37,7 @@ class ApiKey extends Entity {
37
37
  const stored = this.data.secretHash;
38
38
  const hashedBuf = Buffer.from(hashed, 'hex');
39
39
  const storedBuf = Buffer.from(stored, 'hex');
40
- return hashedBuf.length === storedBuf.length && crypto.timingSafeEqual(hashedBuf, storedBuf);
40
+ return hashedBuf.length === storedBuf.length && crypto__default.timingSafeEqual(hashedBuf, storedBuf);
41
41
  }
42
42
  validateSecret(secret) {
43
43
  if (!this.isValidSecret(secret)) {
@@ -1,17 +1,18 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
3
- import '../../../feature/pg/PgLocker.js';
4
- import 'debug';
2
+ import { singleton } from '../../../core/injection/index.js';
3
+ import 'short-uuid';
5
4
  import { CustomError } from '../../../core/error/CustomError.js';
6
- import 'node:crypto';
5
+ import '../../../core/error/setupErrorHandlers.js';
6
+ import '../../../feature/repository/RepositoryMetadataStore.js';
7
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
7
8
  import '../../../feature/pg/withPgClient.js';
9
+ import 'debug';
10
+ import '../../../feature/pg/PgLocker.js';
11
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
12
+ import 'node:crypto';
8
13
  import '../../../feature/pg/pgStorage.js';
9
- import { singleton } from '../../../core/injection/index.js';
10
- import '../../../feature/pg/query/PgJsonRepository.js';
11
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
12
14
  import { Pool } from 'pg';
13
15
  import { ApiKey } from './ApiKey.js';
14
- import '../../../core/error/setupErrorHandlers.js';
15
16
 
16
17
  let PgApiKeyRepository = class PgApiKeyRepository extends PgCrudRepository {
17
18
  constructor(pool) {
@@ -1,12 +1,12 @@
1
1
  import { Entity } from '../../../core/entity/Entity.js';
2
2
  import { CustomError } from '../../../core/error/CustomError.js';
3
3
  import '../../../core/error/setupErrorHandlers.js';
4
- import crypto from 'node:crypto';
4
+ import crypto__default from 'node:crypto';
5
5
 
6
6
  class JwtRefreshToken extends Entity {
7
7
  static PREFIX = 'rt_';
8
8
  static hashSecret(secret) {
9
- return crypto.createHash('sha256').update(secret).digest('hex');
9
+ return crypto__default.createHash('sha256').update(secret).digest('hex');
10
10
  }
11
11
  get authInfo() {
12
12
  return this.data.authInfo;
@@ -30,7 +30,7 @@ class JwtRefreshToken extends Entity {
30
30
  if (this.data.secretHash) {
31
31
  throw new Error('This Token key already has a secret');
32
32
  }
33
- const secret = `${JwtRefreshToken.PREFIX}${crypto.randomBytes(32).toString('hex')}`;
33
+ const secret = `${JwtRefreshToken.PREFIX}${crypto__default.randomBytes(32).toString('hex')}`;
34
34
  this.data.secretHash = JwtRefreshToken.hashSecret(secret);
35
35
  return secret;
36
36
  }
@@ -43,7 +43,7 @@ class JwtRefreshToken extends Entity {
43
43
  const stored = this.data.secretHash;
44
44
  const hashedBuf = Buffer.from(hashed, 'hex');
45
45
  const storedBuf = Buffer.from(stored, 'hex');
46
- return hashedBuf.length === storedBuf.length && crypto.timingSafeEqual(hashedBuf, storedBuf);
46
+ return hashedBuf.length === storedBuf.length && crypto__default.timingSafeEqual(hashedBuf, storedBuf);
47
47
  }
48
48
  isValidToken(secret) {
49
49
  if (this.isExpired())
@@ -2,14 +2,15 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
3
  import { CustomError } from '../../../core/error/CustomError.js';
4
4
  import '../../../core/error/setupErrorHandlers.js';
5
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
6
- import '../../../feature/pg/PgLocker.js';
5
+ import 'short-uuid';
6
+ import '../../../feature/repository/RepositoryMetadataStore.js';
7
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
+ import '../../../feature/pg/withPgClient.js';
7
9
  import 'debug';
10
+ import '../../../feature/pg/PgLocker.js';
11
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
8
12
  import 'node:crypto';
9
- import '../../../feature/pg/withPgClient.js';
10
13
  import '../../../feature/pg/pgStorage.js';
11
- import '../../../feature/pg/query/PgJsonRepository.js';
12
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
13
14
  import { Pool } from 'pg';
14
15
  import { JwtRefreshToken } from './JwtRefreshToken.js';
15
16
 
@@ -1,4 +1,4 @@
1
- class RamChatMemory {
1
+ class InMemoryChatMemory {
2
2
  memory = [];
3
3
  async findLastItems(count) {
4
4
  return this.memory.slice(-count);
@@ -11,4 +11,4 @@ class RamChatMemory {
11
11
  }
12
12
  }
13
13
 
14
- export { RamChatMemory };
14
+ export { InMemoryChatMemory };
@@ -1,6 +1,6 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { v4 } from 'uuid';
3
- import { RamChatMemory } from './RamChatMemory.js';
3
+ import { InMemoryChatMemory } from './InMemoryChatMemory.js';
4
4
  import { singleton } from '../../../core/injection/index.js';
5
5
  import '../../../feature/chat-bot/ChatAdapterRegistry.js';
6
6
  import '../../../feature/chat-bot/ChatBot.js';
@@ -10,7 +10,7 @@ import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
10
10
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
11
11
  import '../../../core/error/setupErrorHandlers.js';
12
12
 
13
- let RamChatRepository = class RamChatRepository {
13
+ let InMemoryChatRepository = class InMemoryChatRepository {
14
14
  items = [];
15
15
  memories = [];
16
16
  async update(chat) {
@@ -28,7 +28,7 @@ let RamChatRepository = class RamChatRepository {
28
28
  chat.validate();
29
29
  this.items.push(chat);
30
30
  const memory = {
31
- memory: new RamChatMemory(),
31
+ memory: new InMemoryChatMemory(),
32
32
  chatId: chat.id,
33
33
  };
34
34
  this.memories.push(memory);
@@ -56,8 +56,8 @@ let RamChatRepository = class RamChatRepository {
56
56
  return this.memories.find((r) => r.chatId === chatId) ?? null;
57
57
  }
58
58
  };
59
- RamChatRepository = __decorate([
59
+ InMemoryChatRepository = __decorate([
60
60
  singleton()
61
- ], RamChatRepository);
61
+ ], InMemoryChatRepository);
62
62
 
63
- export { RamChatRepository };
63
+ export { InMemoryChatRepository };
@@ -0,0 +1,2 @@
1
+ export { InMemoryChatMemory } from './InMemoryChatMemory.js';
2
+ export { InMemoryChatRepository } from './InMemoryChatRepository.js';
@@ -1,12 +1,14 @@
1
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
2
- import '../../../feature/pg/PgLocker.js';
1
+ import '../../../core/injection/index.js';
2
+ import 'short-uuid';
3
+ import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/RepositoryMetadataStore.js';
5
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
+ import '../../../feature/pg/withPgClient.js';
3
7
  import 'debug';
8
+ import '../../../feature/pg/PgLocker.js';
9
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
4
10
  import 'node:crypto';
5
- import '../../../feature/pg/withPgClient.js';
6
11
  import '../../../feature/pg/pgStorage.js';
7
- import '../../../core/injection/index.js';
8
- import '../../../feature/pg/query/PgJsonRepository.js';
9
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
10
12
  import '../../../feature/chat-bot/ChatAdapterRegistry.js';
11
13
  import '../../../feature/chat-bot/ChatBot.js';
12
14
  import { ChatItem } from '../../../feature/chat-bot/ChatItem.js';
@@ -15,7 +17,6 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
15
17
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
16
18
  import 'uuid';
17
19
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
18
- import '../../../core/error/setupErrorHandlers.js';
19
20
 
20
21
  class PgChatMemory extends PgCrudRepository {
21
22
  chatId;
@@ -2,14 +2,16 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { PgChatMemory } from './PgChatMemory.js';
4
4
  import { singleton } from '../../../core/injection/index.js';
5
- import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
6
- import '../../../feature/pg/PgLocker.js';
5
+ import 'short-uuid';
6
+ import '../../../core/error/setupErrorHandlers.js';
7
+ import '../../../feature/repository/RepositoryMetadataStore.js';
8
+ import '../../../feature/repository/RepositoryAdapterRegistry.js';
9
+ import '../../../feature/pg/withPgClient.js';
7
10
  import 'debug';
11
+ import '../../../feature/pg/PgLocker.js';
12
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
8
13
  import 'node:crypto';
9
- import '../../../feature/pg/withPgClient.js';
10
14
  import '../../../feature/pg/pgStorage.js';
11
- import '../../../feature/pg/query/PgJsonRepository.js';
12
- import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
13
15
  import { Chat } from '../../../feature/chat-bot/Chat.js';
14
16
  import '../../../feature/chat-bot/ChatAdapterRegistry.js';
15
17
  import '../../../feature/chat-bot/ChatBot.js';
@@ -18,7 +20,6 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
18
20
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
19
21
  import 'uuid';
20
22
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
21
- import '../../../core/error/setupErrorHandlers.js';
22
23
 
23
24
  let PgChatRepository = class PgChatRepository extends PgCrudRepository {
24
25
  constructor(pool) {
@@ -0,0 +1,2 @@
1
+ export { PgChatRepository } from './PgChatRepository.js';
2
+ export { PgChatMemory } from './PgChatMemory.js';
@@ -3,14 +3,19 @@ import { ControllerMetadataStore } from '../../../feature/chat-controller/metada
3
3
  import '../../../feature/chat-controller/ChatResolver.js';
4
4
  import '../../../feature/chat-controller/runChatControllers.js';
5
5
  import { CmdChannel } from './CmdChannel.js';
6
+ import { CmdChannelConfig } from './CmdChannelConfig.js';
6
7
 
7
8
  function cmd() {
8
9
  return function (target, propertyKey) {
9
10
  const store = container.resolve(ControllerMetadataStore);
11
+ const controllerConstructor = target.constructor;
12
+ const functionName = propertyKey.toString();
13
+ const route = `${controllerConstructor.name}.${functionName}`;
10
14
  store.saveChannelMetadata({
11
15
  channelConstructor: CmdChannel,
12
- functionName: propertyKey.toString(),
13
- controllerConstructor: target.constructor,
16
+ functionName,
17
+ controllerConstructor,
18
+ channelConfig: new CmdChannelConfig(route),
14
19
  });
15
20
  };
16
21
  }
@@ -1,97 +1,121 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
- import { injectable } from '../../../core/injection/index.js';
3
- import { Logger } from '../../../core/logger/Logger.js';
4
- import { cmdChannelName } from './cmdChannelName.js';
5
- import * as readline from 'node:readline';
6
2
  import * as fs from 'node:fs';
7
3
  import * as path from 'node:path';
4
+ import { injectable } from '../../../core/injection/index.js';
5
+ import { Logger } from '../../../core/logger/Logger.js';
8
6
  import { Random } from '../../../core/random/Random.js';
9
7
  import { Auth } from '../../../core/auth/Auth.js';
8
+ import { CmdChannelConfig } from './CmdChannelConfig.js';
9
+ import { CmdChannelServer } from './CmdChannelServer.js';
10
+ import { cmdChannelName } from './cmdChannelName.js';
10
11
 
11
12
  var CmdChannel_1;
12
- const chatIdPath = '.cmd-channel/id.json';
13
- const authInfoPath = '.cmd-channel/auth-info.json';
13
+ const fileLogger = new Logger('wabot:cmd-channel');
14
14
  let CmdChannel = class CmdChannel {
15
15
  static { CmdChannel_1 = this; }
16
16
  auth;
17
- chatId = undefined;
18
- rl = readline.createInterface({
19
- input: process.stdin,
20
- output: process.stdout,
21
- });
17
+ server;
18
+ config;
22
19
  static channelName = cmdChannelName;
20
+ chatId = undefined;
23
21
  callBack = null;
24
- constructor(auth) {
22
+ constructor(auth, server, config) {
25
23
  this.auth = auth;
24
+ this.server = server;
25
+ this.config = config;
26
26
  }
27
27
  listen(callback) {
28
28
  this.callBack = callback;
29
29
  }
30
30
  disconnect() {
31
- this.rl.removeAllListeners('line');
32
- this.rl.close();
31
+ this.server.unregister(this.config.route);
33
32
  this.callBack = null;
34
33
  }
35
34
  connect() {
36
- this.rl.on('line', async (input) => {
37
- const trimmedInput = input.trim();
38
- if (!trimmedInput) {
39
- this.rl.prompt();
40
- return;
41
- }
42
- if (trimmedInput.toLowerCase() === 'exit') {
43
- this.rl.close();
44
- return;
45
- }
46
- if (this.chatId === undefined) {
47
- this.chatId = readJsonFromFile(chatIdPath) ?? undefined;
48
- if (!this.chatId) {
49
- this.chatId = Random.alphaNumericLowerCase(10);
50
- writeJsonToFile(chatIdPath, this.chatId);
51
- }
52
- }
53
- const chatConnection = {
54
- id: this.chatId,
55
- chatType: 'PRIVATE',
56
- channelName: CmdChannel_1.channelName,
57
- };
58
- if (!this.callBack)
59
- return;
60
- if (!this.auth.isAssigned()) {
61
- const authInfo = readJsonFromFile(authInfoPath);
62
- if (authInfo) {
63
- this.auth.assign(authInfo);
64
- }
65
- }
66
- await this.callBack({
67
- channel: cmdChannelName,
68
- chatConnection,
69
- message: {
70
- text: trimmedInput,
71
- },
72
- reply: async (message) => {
73
- console.log(`\n[${message.senderName}]: ${message.text}\n`);
74
- this.rl.prompt();
75
- if (this.auth.isAssigned()) {
76
- writeJsonToFile(authInfoPath, this.auth.require());
77
- }
78
- },
79
- injectInstances: [[Auth, this.auth]],
80
- });
35
+ this.server.register(this.config.route, {
36
+ onMessage: async (text, reply) => {
37
+ if (!this.callBack)
38
+ return;
39
+ this.ensureChatId();
40
+ this.ensureAuthLoaded();
41
+ const chatConnection = {
42
+ id: this.chatId,
43
+ chatType: 'PRIVATE',
44
+ channelName: CmdChannel_1.channelName,
45
+ };
46
+ await this.callBack({
47
+ channel: cmdChannelName,
48
+ chatConnection,
49
+ message: { text },
50
+ reply: async (message) => {
51
+ reply({
52
+ senderName: message.senderName,
53
+ text: extractDisplayText(message),
54
+ });
55
+ if (this.auth.isAssigned()) {
56
+ writeJsonToFile(this.authInfoPath(), this.auth.require());
57
+ }
58
+ },
59
+ injectInstances: [[Auth, this.auth]],
60
+ });
61
+ },
81
62
  });
82
63
  }
64
+ routeSlug() {
65
+ return this.config.route.replace(/[^a-zA-Z0-9._-]/g, '_');
66
+ }
67
+ chatIdPath() {
68
+ return path.join('.cmd-channel', this.routeSlug(), 'id.json');
69
+ }
70
+ authInfoPath() {
71
+ return path.join('.cmd-channel', this.routeSlug(), 'auth-info.json');
72
+ }
73
+ ensureChatId() {
74
+ if (this.chatId !== undefined)
75
+ return;
76
+ this.chatId = readJsonFromFile(this.chatIdPath()) ?? undefined;
77
+ if (!this.chatId) {
78
+ this.chatId = Random.alphaNumericLowerCase(10);
79
+ writeJsonToFile(this.chatIdPath(), this.chatId);
80
+ }
81
+ }
82
+ ensureAuthLoaded() {
83
+ if (this.auth.isAssigned())
84
+ return;
85
+ const authInfo = readJsonFromFile(this.authInfoPath());
86
+ if (authInfo) {
87
+ this.auth.assign(authInfo);
88
+ }
89
+ }
83
90
  };
84
91
  CmdChannel = CmdChannel_1 = __decorate([
85
92
  injectable(),
86
- __metadata("design:paramtypes", [Auth])
93
+ __metadata("design:paramtypes", [Auth,
94
+ CmdChannelServer,
95
+ CmdChannelConfig])
87
96
  ], CmdChannel);
97
+ function extractDisplayText(message) {
98
+ const raw = message.text ?? '';
99
+ const trimmed = raw.trim();
100
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('['))
101
+ return raw;
102
+ try {
103
+ const parsed = JSON.parse(trimmed);
104
+ if (parsed && typeof parsed === 'object' && typeof parsed.text === 'string') {
105
+ return parsed.text;
106
+ }
107
+ }
108
+ catch {
109
+ // not JSON — fall through and return raw
110
+ }
111
+ return raw;
112
+ }
88
113
  function writeJsonToFile(filename, data) {
89
114
  const filePath = path.resolve(process.cwd(), filename);
90
115
  const dir = path.dirname(filePath);
91
116
  fs.mkdirSync(dir, { recursive: true });
92
117
  fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
93
118
  }
94
- const fileLogger = new Logger('wabot:cmd-channel');
95
119
  function readJsonFromFile(filename) {
96
120
  const filePath = path.resolve(process.cwd(), filename);
97
121
  if (!fs.existsSync(filePath)) {