@wabot-dev/framework 0.9.16 → 0.9.18

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.
@@ -1,9 +1,29 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
2
4
  import { generate } from 'short-uuid';
3
5
  import { singleton } from '../../../core/injection/index.js';
6
+ import { Logger } from '../../../core/logger/Logger.js';
7
+ import '../../../feature/async/AsyncMetadataStore.js';
8
+ import '../../../feature/async/TransactionMetadataStore.js';
9
+ import '../../../feature/async/Async.js';
10
+ import { CronJob } from '../../../feature/async/CronJob.js';
11
+ import '../../../core/error/setupErrorHandlers.js';
12
+ import '../../../feature/async/JobRepository.js';
13
+ import '../../../feature/async/JobRunner.js';
14
+ import '../../../feature/async/JobScheduler.js';
15
+ import '../../../feature/async/JobWatchdog.js';
16
+ import '../../../feature/async/CronScheduler.js';
4
17
 
18
+ const CRON_JOBS_FILE = '.wabot/in-memory/cron-jobs.json';
19
+ const MAX_CRON_JOBS = 32;
20
+ const logger = new Logger('wabot:in-memory-cron-job-repository');
5
21
  let InMemoryCronJobRepository = class InMemoryCronJobRepository {
22
+ // Insertion order acts as LRU: most-recently-touched at the end.
6
23
  items = new Map();
24
+ constructor() {
25
+ this.load();
26
+ }
7
27
  async create(cronJob) {
8
28
  if (cronJob.wasCreated())
9
29
  throw new Error('CronJob already created');
@@ -11,6 +31,8 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
11
31
  cronJob['data'].createdAt = new Date().getTime();
12
32
  cronJob.validate();
13
33
  this.items.set(cronJob.id, cronJob);
34
+ this.enforceLimit();
35
+ this.persist();
14
36
  }
15
37
  async findDue(date) {
16
38
  const now = (date ?? new Date()).getTime();
@@ -28,7 +50,8 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
28
50
  if (!cronJob.wasCreated())
29
51
  throw new Error('CronJob was not created');
30
52
  cronJob.validate();
31
- this.items.set(cronJob.id, cronJob);
53
+ this.touch(cronJob);
54
+ this.persist();
32
55
  }
33
56
  async findByName(name) {
34
57
  for (const c of this.items.values()) {
@@ -37,9 +60,57 @@ let InMemoryCronJobRepository = class InMemoryCronJobRepository {
37
60
  }
38
61
  return null;
39
62
  }
63
+ touch(item) {
64
+ this.items.delete(item.id);
65
+ this.items.set(item.id, item);
66
+ }
67
+ enforceLimit() {
68
+ while (this.items.size > MAX_CRON_JOBS) {
69
+ const oldestKey = this.items.keys().next().value;
70
+ if (oldestKey === undefined)
71
+ break;
72
+ this.items.delete(oldestKey);
73
+ }
74
+ }
75
+ filePath() {
76
+ return path.resolve(process.cwd(), CRON_JOBS_FILE);
77
+ }
78
+ load() {
79
+ const file = this.filePath();
80
+ if (!fs.existsSync(file))
81
+ return;
82
+ try {
83
+ const raw = fs.readFileSync(file, 'utf-8');
84
+ const parsed = JSON.parse(raw);
85
+ if (!Array.isArray(parsed))
86
+ return;
87
+ for (const data of parsed) {
88
+ if (!data?.id)
89
+ continue;
90
+ const cronJob = new CronJob(data);
91
+ this.items.set(cronJob.id, cronJob);
92
+ }
93
+ this.enforceLimit();
94
+ }
95
+ catch (err) {
96
+ logger.warn(`Failed to load ${file}:`, err);
97
+ }
98
+ }
99
+ persist() {
100
+ const file = this.filePath();
101
+ try {
102
+ fs.mkdirSync(path.dirname(file), { recursive: true });
103
+ const data = [...this.items.values()].map((c) => c['data']);
104
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
105
+ }
106
+ catch (err) {
107
+ logger.warn(`Failed to persist ${file}:`, err);
108
+ }
109
+ }
40
110
  };
41
111
  InMemoryCronJobRepository = __decorate([
42
- singleton()
112
+ singleton(),
113
+ __metadata("design:paramtypes", [])
43
114
  ], InMemoryCronJobRepository);
44
115
 
45
116
  export { InMemoryCronJobRepository };
@@ -1,9 +1,29 @@
1
- import { __decorate } from 'tslib';
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
2
4
  import { generate } from 'short-uuid';
3
5
  import { singleton } from '../../../core/injection/index.js';
6
+ import { Logger } from '../../../core/logger/Logger.js';
7
+ import '../../../feature/async/AsyncMetadataStore.js';
8
+ import '../../../feature/async/TransactionMetadataStore.js';
9
+ import '../../../feature/async/Async.js';
10
+ import '../../../_virtual/index.js';
11
+ import { Job } from '../../../feature/async/Job.js';
12
+ import '../../../feature/async/JobRepository.js';
13
+ import '../../../feature/async/JobRunner.js';
14
+ import '../../../feature/async/JobScheduler.js';
15
+ import '../../../feature/async/JobWatchdog.js';
16
+ import '../../../feature/async/CronScheduler.js';
4
17
 
18
+ const JOBS_FILE = '.wabot/in-memory/jobs.json';
19
+ const MAX_JOBS = 32;
20
+ const logger = new Logger('wabot:in-memory-job-repository');
5
21
  let InMemoryJobRepository = class InMemoryJobRepository {
22
+ // Insertion order acts as LRU: most-recently-touched at the end.
6
23
  items = new Map();
24
+ constructor() {
25
+ this.load();
26
+ }
7
27
  async find(id) {
8
28
  return this.items.get(id) ?? null;
9
29
  }
@@ -26,15 +46,19 @@ let InMemoryJobRepository = class InMemoryJobRepository {
26
46
  item['data'].createdAt = new Date().getTime();
27
47
  item.validate();
28
48
  this.items.set(item.id, item);
49
+ this.enforceLimit();
50
+ this.persist();
29
51
  }
30
52
  async update(item) {
31
53
  if (!item.wasCreated())
32
54
  throw new Error('Job was not created');
33
55
  item.validate();
34
- this.items.set(item.id, item);
56
+ this.touch(item);
57
+ this.persist();
35
58
  }
36
59
  async delete(item) {
37
60
  this.items.delete(item.id);
61
+ this.persist();
38
62
  }
39
63
  async findPendingForRunFrom(date, limit) {
40
64
  const now = date.getTime();
@@ -67,9 +91,57 @@ let InMemoryJobRepository = class InMemoryJobRepository {
67
91
  }
68
92
  return count;
69
93
  }
94
+ touch(item) {
95
+ this.items.delete(item.id);
96
+ this.items.set(item.id, item);
97
+ }
98
+ enforceLimit() {
99
+ while (this.items.size > MAX_JOBS) {
100
+ const oldestKey = this.items.keys().next().value;
101
+ if (oldestKey === undefined)
102
+ break;
103
+ this.items.delete(oldestKey);
104
+ }
105
+ }
106
+ filePath() {
107
+ return path.resolve(process.cwd(), JOBS_FILE);
108
+ }
109
+ load() {
110
+ const file = this.filePath();
111
+ if (!fs.existsSync(file))
112
+ return;
113
+ try {
114
+ const raw = fs.readFileSync(file, 'utf-8');
115
+ const parsed = JSON.parse(raw);
116
+ if (!Array.isArray(parsed))
117
+ return;
118
+ for (const data of parsed) {
119
+ if (!data?.id)
120
+ continue;
121
+ const job = new Job(data);
122
+ this.items.set(job.id, job);
123
+ }
124
+ this.enforceLimit();
125
+ }
126
+ catch (err) {
127
+ logger.warn(`Failed to load ${file}:`, err);
128
+ }
129
+ }
130
+ persist() {
131
+ const file = this.filePath();
132
+ try {
133
+ fs.mkdirSync(path.dirname(file), { recursive: true });
134
+ const data = [...this.items.values()].map((j) => j['data']);
135
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
136
+ }
137
+ catch (err) {
138
+ logger.warn(`Failed to persist ${file}:`, err);
139
+ }
140
+ }
70
141
  };
71
142
  InMemoryJobRepository = __decorate([
72
- singleton()
143
+ singleton(),
144
+ __metadata("design:paramtypes", [])
73
145
  ], InMemoryJobRepository);
74
146
 
75
147
  export { InMemoryJobRepository };
@@ -1,8 +1,7 @@
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 'short-uuid';
5
- import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
5
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
6
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
7
  import '../../../feature/pg/withPgClient.js';
@@ -1,8 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
- import 'short-uuid';
5
- import '../../../core/error/setupErrorHandlers.js';
4
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
5
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
6
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
7
  import { withPgClient } from '../../../feature/pg/withPgClient.js';
@@ -1,11 +1,12 @@
1
1
  import '../../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../../core/error/setupErrorHandlers.js';
2
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
4
3
  import '../../../feature/repository/RepositoryMetadataStore.js';
5
4
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
5
  import { withPgClient } from '../../../feature/pg/withPgClient.js';
7
6
  import 'debug';
8
7
  import '../../../feature/pg/PgLocker.js';
8
+ import 'short-uuid';
9
+ import '../../../core/error/setupErrorHandlers.js';
9
10
  import 'node:crypto';
10
11
  import '../../../feature/pg/pgStorage.js';
11
12
  import { withPgTransaction } from '../../../feature/pg/withPgTransaction.js';
@@ -1,18 +1,18 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
- import 'short-uuid';
4
- import { CustomError } from '../../../core/error/CustomError.js';
5
- import '../../../core/error/setupErrorHandlers.js';
3
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
4
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
5
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
6
  import '../../../feature/pg/withPgClient.js';
9
7
  import 'debug';
8
+ import { CustomError } from '../../../core/error/CustomError.js';
10
9
  import '../../../feature/pg/PgLocker.js';
11
10
  import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
12
11
  import 'node:crypto';
13
12
  import '../../../feature/pg/pgStorage.js';
14
13
  import { Pool } from 'pg';
15
14
  import { ApiKey } from './ApiKey.js';
15
+ import '../../../core/error/setupErrorHandlers.js';
16
16
 
17
17
  let PgApiKeyRepository = class PgApiKeyRepository extends PgCrudRepository {
18
18
  constructor(pool) {
@@ -2,7 +2,7 @@ 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 'short-uuid';
5
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
6
6
  import '../../../feature/repository/RepositoryMetadataStore.js';
7
7
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
8
8
  import '../../../feature/pg/withPgClient.js';
@@ -16,7 +16,7 @@ import '../../../core/error/setupErrorHandlers.js';
16
16
 
17
17
  const CHATS_FILE = '.wabot/in-memory/chats.json';
18
18
  const MEMORY_DIR = '.wabot/in-memory';
19
- const MAX_CHATS = 10;
19
+ const MAX_CHATS = 32;
20
20
  const logger = new Logger('wabot:in-memory-chat-repository');
21
21
  let InMemoryChatRepository = class InMemoryChatRepository {
22
22
  // Ordered least-recently-active first, most-recent last.
@@ -1,6 +1,5 @@
1
1
  import '../../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../../core/error/setupErrorHandlers.js';
2
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
4
3
  import '../../../feature/repository/RepositoryMetadataStore.js';
5
4
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
6
5
  import '../../../feature/pg/withPgClient.js';
@@ -17,6 +16,7 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
17
16
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
18
17
  import 'uuid';
19
18
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
19
+ import '../../../core/error/setupErrorHandlers.js';
20
20
 
21
21
  class PgChatMemory extends PgCrudRepository {
22
22
  chatId;
@@ -2,8 +2,7 @@ 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 'short-uuid';
6
- import '../../../core/error/setupErrorHandlers.js';
5
+ import '../../../feature/repository/MemoryRepositoryAdapter.js';
7
6
  import '../../../feature/repository/RepositoryMetadataStore.js';
8
7
  import '../../../feature/repository/RepositoryAdapterRegistry.js';
9
8
  import '../../../feature/pg/withPgClient.js';
@@ -20,6 +19,7 @@ import '../../../feature/chat-bot/UnionChatAdapter.js';
20
19
  import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
21
20
  import 'uuid';
22
21
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
22
+ import '../../../core/error/setupErrorHandlers.js';
23
23
 
24
24
  let PgChatRepository = class PgChatRepository extends PgCrudRepository {
25
25
  constructor(pool) {
@@ -1,4 +1,5 @@
1
1
  import { container } from '../../../core/injection/index.js';
2
+ import { resolveConfigReferences } from '../../../core/config/resolver.js';
2
3
  import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
3
4
  import '../../../feature/chat-controller/ChatResolver.js';
4
5
  import '../../../feature/chat-controller/runChatControllers.js';
@@ -7,12 +8,13 @@ import { TelegramChannelConfig } from './TelegramChannelConfig.js';
7
8
 
8
9
  function telegram(config) {
9
10
  return function (target, propertyKey) {
11
+ const resolved = resolveConfigReferences(config);
10
12
  const store = container.resolve(ControllerMetadataStore);
11
13
  store.saveChannelMetadata({
12
14
  channelConstructor: TelegramChannel,
13
15
  functionName: propertyKey.toString(),
14
16
  controllerConstructor: target.constructor,
15
- channelConfig: new TelegramChannelConfig(config.botToken),
17
+ channelConfig: new TelegramChannelConfig(resolved.botToken),
16
18
  });
17
19
  };
18
20
  }
@@ -1,6 +1,5 @@
1
1
  import { container } from '../../core/injection/index.js';
2
- import 'short-uuid';
3
- import '../../core/error/setupErrorHandlers.js';
2
+ import '../repository/MemoryRepositoryAdapter.js';
4
3
  import { RepositoryMetadataStore } from '../repository/RepositoryMetadataStore.js';
5
4
  import '../repository/RepositoryAdapterRegistry.js';
6
5
  import { PgRepositoryBase } from './PgRepositoryBase.js';
@@ -11,7 +11,7 @@ function inheritsFrom(ctor, base) {
11
11
  }
12
12
  return false;
13
13
  }
14
- function memoryExtension(repositoryClass) {
14
+ function memExtension(repositoryClass) {
15
15
  if (typeof repositoryClass !== 'function') {
16
16
  throw new Error(`@memoryExtension: repository argument must be a class, ` +
17
17
  `got ${typeof repositoryClass}`);
@@ -26,4 +26,4 @@ function memoryExtension(repositoryClass) {
26
26
  };
27
27
  }
28
28
 
29
- export { memoryExtension };
29
+ export { memExtension };
@@ -1,12 +1,80 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
1
3
  import { generate } from 'short-uuid';
2
4
  import { CustomError } from '../../core/error/CustomError.js';
3
5
  import '../../core/error/setupErrorHandlers.js';
6
+ import { Logger } from '../../core/logger/Logger.js';
4
7
  import { evaluateQueryAst } from './evaluateQueryAst.js';
5
8
 
9
+ const DEFAULT_PERSIST_DIR = '.wabot/in-memory';
10
+ const DEFAULT_MAX_ITEMS = 32;
11
+ const logger = new Logger('wabot:memory-repository-adapter');
6
12
  function cloneEntity(config, item) {
7
13
  const data = JSON.parse(JSON.stringify(item['data']));
8
14
  return new config.constructor(data);
9
15
  }
16
+ class MemoryStore {
17
+ config;
18
+ persistOptions;
19
+ // Insertion order acts as LRU: most-recently-touched at the end.
20
+ items = new Map();
21
+ constructor(config, persistOptions) {
22
+ this.config = config;
23
+ this.persistOptions = persistOptions;
24
+ this.load();
25
+ }
26
+ touch(item) {
27
+ this.items.delete(item.id);
28
+ this.items.set(item.id, item);
29
+ }
30
+ enforceLimit() {
31
+ while (this.items.size > this.persistOptions.maxItems) {
32
+ const oldest = this.items.keys().next().value;
33
+ if (oldest === undefined)
34
+ break;
35
+ this.items.delete(oldest);
36
+ }
37
+ }
38
+ persist() {
39
+ if (!this.persistOptions.enabled)
40
+ return;
41
+ const file = this.filePath();
42
+ try {
43
+ fs.mkdirSync(path.dirname(file), { recursive: true });
44
+ const data = [...this.items.values()].map((i) => i['data']);
45
+ fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf-8');
46
+ }
47
+ catch (err) {
48
+ logger.warn(`Failed to persist ${file}:`, err);
49
+ }
50
+ }
51
+ load() {
52
+ if (!this.persistOptions.enabled)
53
+ return;
54
+ const file = this.filePath();
55
+ if (!fs.existsSync(file))
56
+ return;
57
+ try {
58
+ const raw = fs.readFileSync(file, 'utf-8');
59
+ const parsed = JSON.parse(raw);
60
+ if (!Array.isArray(parsed))
61
+ return;
62
+ for (const data of parsed) {
63
+ if (!data?.id)
64
+ continue;
65
+ const item = new this.config.constructor(data);
66
+ this.items.set(data.id, item);
67
+ }
68
+ this.enforceLimit();
69
+ }
70
+ catch (err) {
71
+ logger.warn(`Failed to load ${file}:`, err);
72
+ }
73
+ }
74
+ filePath() {
75
+ return path.resolve(process.cwd(), this.persistOptions.dir, `${this.config.table}.json`);
76
+ }
77
+ }
10
78
  class MemoryRepositoryExtension {
11
79
  items;
12
80
  config;
@@ -19,12 +87,15 @@ class MemoryRepositoryExtension {
19
87
  }
20
88
  }
21
89
  class MemoryRepositoryRuntime {
22
- items;
90
+ store;
23
91
  config;
24
- constructor(items, config) {
25
- this.items = items;
92
+ constructor(store, config) {
93
+ this.store = store;
26
94
  this.config = config;
27
95
  }
96
+ get items() {
97
+ return this.store.items;
98
+ }
28
99
  async find(id) {
29
100
  const item = this.items.get(id);
30
101
  return item ? cloneEntity(this.config, item) : null;
@@ -58,17 +129,22 @@ class MemoryRepositoryRuntime {
58
129
  item['data'].id = generate();
59
130
  item['data'].createdAt = new Date().getTime();
60
131
  item.validate();
61
- this.items.set(item.id, cloneEntity(this.config, item));
132
+ const stored = cloneEntity(this.config, item);
133
+ this.store.touch(stored);
134
+ this.store.enforceLimit();
135
+ this.store.persist();
62
136
  }
63
137
  async update(item) {
64
138
  item.validate();
65
139
  if (!this.items.has(item.id)) {
66
140
  throw new Error(`Update failed: no affected rows`);
67
141
  }
68
- this.items.set(item.id, cloneEntity(this.config, item));
142
+ this.store.touch(cloneEntity(this.config, item));
143
+ this.store.persist();
69
144
  }
70
145
  async delete(item) {
71
146
  this.items.delete(item.id);
147
+ this.store.persist();
72
148
  }
73
149
  async runQuery(ast, args) {
74
150
  const result = evaluateQueryAst(this.items.values(), ast, args);
@@ -85,16 +161,26 @@ class MemoryRepositoryRuntime {
85
161
  for (const item of matched) {
86
162
  this.items.delete(item.id);
87
163
  }
164
+ if (matched.length > 0)
165
+ this.store.persist();
88
166
  }
89
167
  }
90
168
  const MEMORY_ADAPTER_ID = Symbol('wabot:memory-adapter');
91
169
  class MemoryRepositoryAdapter {
92
170
  id = MEMORY_ADAPTER_ID;
93
171
  stores = new Map();
172
+ persistOptions;
173
+ constructor(options = {}) {
174
+ this.persistOptions = {
175
+ enabled: options.persist ?? true,
176
+ dir: options.dir ?? DEFAULT_PERSIST_DIR,
177
+ maxItems: options.maxItems ?? DEFAULT_MAX_ITEMS,
178
+ };
179
+ }
94
180
  getStore(config) {
95
181
  let store = this.stores.get(config);
96
182
  if (!store) {
97
- store = new Map();
183
+ store = new MemoryStore(config, this.persistOptions);
98
184
  this.stores.set(config, store);
99
185
  }
100
186
  return store;
@@ -103,7 +189,7 @@ class MemoryRepositoryAdapter {
103
189
  return new MemoryRepositoryRuntime(this.getStore(config), config);
104
190
  }
105
191
  buildExtension(config, ExtensionCtor) {
106
- return new ExtensionCtor(this.getStore(config), config);
192
+ return new ExtensionCtor(this.getStore(config).items, config);
107
193
  }
108
194
  }
109
195
 
@@ -1373,6 +1373,11 @@ interface IRepositoryAdapter {
1373
1373
  buildExtension?<E>(config: IRepositoryConfig<any>, ExtensionCtor: IConstructor<E>): E;
1374
1374
  }
1375
1375
 
1376
+ interface IMemoryRepositoryAdapterOptions {
1377
+ persist?: boolean;
1378
+ dir?: string;
1379
+ maxItems?: number;
1380
+ }
1376
1381
  declare class MemoryRepositoryExtension<P extends Entity<IEntityData>> {
1377
1382
  protected readonly items: Map<string, P>;
1378
1383
  protected readonly config: IRepositoryConfig<P>;
@@ -1383,13 +1388,15 @@ declare const MEMORY_ADAPTER_ID: unique symbol;
1383
1388
  declare class MemoryRepositoryAdapter implements IRepositoryAdapter {
1384
1389
  readonly id: symbol;
1385
1390
  private stores;
1391
+ private readonly persistOptions;
1392
+ constructor(options?: IMemoryRepositoryAdapterOptions);
1386
1393
  private getStore;
1387
1394
  build<P extends Entity<IEntityData>>(config: IRepositoryConfig<P>): IRepositoryRuntime<P>;
1388
1395
  buildExtension<E>(config: IRepositoryConfig<any>, ExtensionCtor: IConstructor<E>): E;
1389
1396
  }
1390
1397
 
1391
1398
  type ExtensionOf<R> = R extends CrudRepository<any, infer Ext> ? Ext : never;
1392
- declare function memoryExtension<R extends CrudRepository<any, any>>(repositoryClass: IConstructor<R>): <E extends MemoryRepositoryExtension<any> & ExtensionOf<R>>(target: IConstructor<E>) => void;
1399
+ declare function memExtension<R extends CrudRepository<any, any>>(repositoryClass: IConstructor<R>): <E extends MemoryRepositoryExtension<any> & ExtensionOf<R>>(target: IConstructor<E>) => void;
1393
1400
 
1394
1401
  declare function query(): (target: object, propertyKey: string | symbol, descriptor?: PropertyDescriptor) => void;
1395
1402
 
@@ -1645,6 +1652,7 @@ declare class PgTransactionAdapter implements ITransactionAdapter {
1645
1652
 
1646
1653
  declare class InMemoryJobRepository implements IJobRepository {
1647
1654
  private items;
1655
+ constructor();
1648
1656
  find(id: string): Promise<Job | null>;
1649
1657
  findOrThrow(id: string): Promise<Job>;
1650
1658
  findByIds(ids: string[]): Promise<Job[]>;
@@ -1655,15 +1663,26 @@ declare class InMemoryJobRepository implements IJobRepository {
1655
1663
  findPendingForRunFrom(date: Date, limit: number): Promise<Job[]>;
1656
1664
  findRunningJobs(): Promise<Job[]>;
1657
1665
  countRunningByCommand(commandName: string): Promise<number>;
1666
+ private touch;
1667
+ private enforceLimit;
1668
+ private filePath;
1669
+ private load;
1670
+ private persist;
1658
1671
  }
1659
1672
 
1660
1673
  declare class InMemoryCronJobRepository implements ICronJobRepository {
1661
1674
  private items;
1675
+ constructor();
1662
1676
  create(cronJob: CronJob): Promise<void>;
1663
1677
  findDue(date?: Date): Promise<CronJob[]>;
1664
1678
  findOrThrow(id: string): Promise<CronJob>;
1665
1679
  update(cronJob: CronJob): Promise<void>;
1666
1680
  findByName(name: string): Promise<CronJob | null>;
1681
+ private touch;
1682
+ private enforceLimit;
1683
+ private filePath;
1684
+ private load;
1685
+ private persist;
1667
1686
  }
1668
1687
 
1669
1688
  declare function apiKeyHandshakeGuard(): (target: IConstructor<any>) => void;
@@ -2138,9 +2157,9 @@ declare class SocketChannel implements IChatChannel {
2138
2157
  }
2139
2158
 
2140
2159
  interface ITelegramChannelConfig {
2141
- botToken: string;
2160
+ botToken: string | ConfigReference<string>;
2142
2161
  }
2143
- declare class TelegramChannelConfig implements ITelegramChannelConfig {
2162
+ declare class TelegramChannelConfig {
2144
2163
  botToken: string;
2145
2164
  constructor(botToken: string);
2146
2165
  }
@@ -2485,4 +2504,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
2485
2504
  new (): {};
2486
2505
  };
2487
2506
 
2488
- export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatAdapterMetadataStore, ChatAdapterRegistry, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatOperator, ChatRepository, ChatResolver, type ClientMap, CmdChannel, CmdChannelConfig, CmdChannelServer, type CmdClientMessage, type CmdServerMessage, type ConfigReference, type ConfigReferenceType, ConfigResolver, Container, ControllerMetadataStore, CronJob, CronJobRepository, CrudRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IBuiltQuery, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterDecoratorConfig, type IChatAdapterMetadata, 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 IChatMessageDocument, type IChatMessageFile, type IChatMessageImage, type IChatMessagesPrivateFile, type IChatMessagesPublicFile, type IChatRepository, type IChatType, type ICmdChannelEntry, type ICmdChannelHandlers, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronHandler, type ICronJobData, type ICronJobRepository, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IExtractChatMessageTextOptions, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type ILockKey, type ILocker, type ILockerKey, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModelKind, type IMindsetModelRef, type IMindsetModels, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IProjectRunnerConfig, type IPropertyValidatorInfo, type IQueryAst, type IQueryCondition, type IQueryMethodMetadata, type IQueryOrderBy, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRepositoryAdapter, type IRepositoryConfig, type IRepositoryRuntime, type IRestControllerConfig, type IRestControllerMetadata, type IScanProjectFilesOptions, type IScheduleAt, type IScheduleDelay, type ISendWhatsAppMessageReq, type ISendWhatsAppTemplateReq, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type ITransactionAdapter, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelConfig, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWasenderReceivedMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppSender, type IWhatsAppTemplateData, type IWhatsAppTemplateParameter, type IchatControllerConfig, InMemoryChatMemory, InMemoryChatRepository, InMemoryCronJobRepository, InMemoryJobRepository, InMemoryLockKey, InMemoryLocker, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, MEMORY_ADAPTER_ID, Mapper, MemoryRepositoryAdapter, MemoryRepositoryExtension, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenRouterChatAdapter, OpenaiChatAdapter, PG_ADAPTER_ID, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJsonRepositoryAdapter, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgRepositoryBase as PgRepositoryExtension, PgTransactionAdapter, ProjectRunner, type QueryConnector, type QueryOperator, type QueryPrefix, Random, RemoteApiKeyRepository, RepositoryAdapterRegistry, RepositoryMetadataStore, type ResolvedConfig, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelMessageFile, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, TransactionMetadataStore, UnionChatAdapter, ValidationMetadataStore, WabotChatAdapter, WasenderChannel, WasenderChannelConfig, WasenderReceiver, WasenderSender, WasenderWebhookController, WhatsAppApiSender, WhatsAppReceiverByCloudApi, WhatsAppSender, apiKeyGuard, apiKeyHandshakeGuard, bool, boolArr, buildQuerySql, chatAdapter, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, cmdChannelSocketPath, command, commandHandler, container, cronHandler, description, errorToPlainObject, evaluateQueryAst, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isChatMessageEmpty, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isRetryableError, isString, jwtGuard, jwtHandshakeGuard, max, memoryExtension, middleware, min, mindset, mindsetModule, modelInfo, num, numArr, obj, onDelete, onGet, onPost, onPut, onSocketEvent, parseQueryMethodName, pgExtension, pgStorage, query, queryExtension, readJsonFromFile, repository, resolveConfigReferences, restController, run, runChatAdapters, runChatControllers, runCmdClient, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scanProjectFiles, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, str, strArr, telegram, telegramChannelName, transaction, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, wasender, wasenderChannelName, withPgClient, withPgTransaction, writeJsonToFile };
2507
+ export { AnthropicChatAdapter, ApiKey, ApiKeyGuardMiddleware, ApiKeyHandshakeGuardMiddleware, ApiKeyRepository, Async, AsyncMetadataStore, Auth, Chat, ChatAdapter, ChatAdapterMetadataStore, ChatAdapterRegistry, ChatBot, ChatBotMetadataStore, ChatItem, ChatMemory, ChatOperator, ChatRepository, ChatResolver, type ClientMap, CmdChannel, CmdChannelConfig, CmdChannelServer, type CmdClientMessage, type CmdServerMessage, type ConfigReference, type ConfigReferenceType, ConfigResolver, Container, ControllerMetadataStore, CronJob, CronJobRepository, CrudRepository, CustomError, DeepSeekChatAdapter, DescriptionMetadataStore, EXPRESS_REQ, EXPRESS_RES, Entity, Env, type ErrorSeverity, ExpressProvider, GoogleChatAdapter, type GoogleChatAdapterV2Options, HtmlModule, HttpServerProvider, type IApiKeyData, type IApiKeyRepository, type IArrayValidationError, type IArrayValidationResult, type IBotMessageItem, type IBuiltQuery, type IChannelMessage, type IChannelMetadata, type IChatAdapter, type IChatAdapterDecoratorConfig, type IChatAdapterMetadata, 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 IChatMessageDocument, type IChatMessageFile, type IChatMessageImage, type IChatMessagesPrivateFile, type IChatMessagesPublicFile, type IChatRepository, type IChatType, type ICmdChannelEntry, type ICmdChannelHandlers, type ICmdChannelMessage, type ICmdReceivedMessage, type ICommandConfig, type ICommandHandler, type ICommandHandlerConfig, type IConstructor, type ICronConfig, type ICronHandler, type ICronJobData, type ICronJobRepository, type ICrudRepository, type ICustomErrorData, type IDescriptionMetadata, type IEndPointConfig, type IEndPointMetadata, type IEntityData, type IEnvType, type IErrorHandlersConfig, type IErrorMonitor, type IErrorMonitorContext, type IExtractChatMessageTextOptions, type IFunctionCall, type IFunctionCallItem, type IGenerateApiKeyReq, type IGenerateApiKeyRes, type IHandshakeMiddleware, type IHandshakeMiddlewareMetadata, type IHtmlModuleOptions, type IHumanMessageItem, type IJobData, type IJobRepository, type IJwtRefreshTokenData, type IJwtRefreshTokenRepository, type ILanguageModelUsage, type ILockKey, type ILocker, type ILockerKey, type IMemoryRepositoryAdapterOptions, type IMessageContext, type IMiddleware, type IMiddlewareMetadata, type IMindset, type IMindsetConfig, type IMindsetIdentity, type IMindsetLlm, type IMindsetMetadata, type IMindsetModelKind, type IMindsetModelRef, type IMindsetModels, type IMindsetModuleConfig, type IMindsetModuleMetadata, type IMindsetTool, type IMindsetToolParameter, type IModelValidationError, type IModelValidationResult, type IModelValidatorsInfo, type IMoneyData, type IPersistentData, type IPgRepositoryConfig, type IProjectRunnerConfig, type IPropertyValidatorInfo, type IQueryAst, type IQueryCondition, type IQueryMethodMetadata, type IQueryOrderBy, type IReceivedMessage, type IRemoteApiKeyFetcher, type IRepositoryAdapter, type IRepositoryConfig, type IRepositoryRuntime, type IRestControllerConfig, type IRestControllerMetadata, type IScanProjectFilesOptions, type IScheduleAt, type IScheduleDelay, type ISendWhatsAppMessageReq, type ISendWhatsAppTemplateReq, type ISocketChannelConfig, type ISocketChannelMessage, type ISocketChannelReceivedMessage, type ISocketControllerConfig, type ISocketControllerMetadata, type ISocketEventConfig, type ISocketEventMetadata, type ISocketReceivedMessage, type IStorableData, type ITelegramChannelConfig, type ITelegramChannelMessage, type ITelegramReceivedMessage, type ITransactionAdapter, type IValidateArrayOptions, type IValidateArrayOptionsWithItemsValidators, type IValidateInputShape, type IValidateIsInOptions, type IValidateIsRecordOptions, type IValidateMaxOptions, type IValidateMinOptions, type IValidationError, type IValidationResult, type IValidator, type IValidatorMetadata, type IWasenderChannelConfig, type IWasenderChannelMessageListener, type IWasenderDeviceListMetadata, type IWasenderEvent, type IWasenderMessageContent, type IWasenderMessageContextInfo, type IWasenderMessageKey, type IWasenderMessageReceivedData, type IWasenderMessageReceivedEvent, type IWasenderQrUpdatedEvent, type IWasenderReceivedMessage, type IWhatsAppCloudContact, type IWhatsAppCloudMessage, type IWhatsAppCloudMessageMetadata, type IWhatsAppCloudTemplate, type IWhatsAppCloudTemplateComponent, type IWhatsAppCloudTemplateResponse, type IWhatsAppCloudWebhookPayload, type IWhatsAppSender, type IWhatsAppTemplateData, type IWhatsAppTemplateParameter, type IchatControllerConfig, InMemoryChatMemory, InMemoryChatRepository, InMemoryCronJobRepository, InMemoryJobRepository, InMemoryLockKey, InMemoryLocker, Job, JobRepository, JobRunner, Jwt, JwtAccessAndRefreshTokenDto, JwtConfig, JwtGuardMiddleware, JwtHandshakeGuardMiddleware, JwtRefreshToken, JwtRefreshTokenRepository, JwtSigner, JwtTokenDto, Lifecycle, Locker, Logger, MEMORY_ADAPTER_ID, Mapper, MemoryRepositoryAdapter, MemoryRepositoryExtension, Mindset, MindsetMetadataStore, MindsetOperator, Money, MoneyDto, OpenRouterChatAdapter, OpenaiChatAdapter, PG_ADAPTER_ID, Password, type PasswordHashOptions, Persistent, PgApiKeyRepository, PgChatMemory, PgChatRepository, PgCronJobRepository, PgCrudRepository, PgJobRepository, PgJsonRepositoryAdapter, PgJwtRefreshTokenRepository, PgLockKey, PgLocker, PgRepositoryBase, PgRepositoryBase as PgRepositoryExtension, PgTransactionAdapter, ProjectRunner, type QueryConnector, type QueryOperator, type QueryPrefix, Random, RemoteApiKeyRepository, RepositoryAdapterRegistry, RepositoryMetadataStore, type ResolvedConfig, RestControllerMetadataStore, RestRequest, SocketChannel, SocketChannelConfig, SocketChannelMessageFile, SocketChannelReceivedMessage, SocketControllerMetadataStore, SocketServerConfig, SocketServerProvider, Storable, TelegramChannel, TelegramChannelConfig, TransactionMetadataStore, UnionChatAdapter, ValidationMetadataStore, WabotChatAdapter, WasenderChannel, WasenderChannelConfig, WasenderReceiver, WasenderSender, WasenderWebhookController, WhatsAppApiSender, WhatsAppReceiverByCloudApi, WhatsAppSender, apiKeyGuard, apiKeyHandshakeGuard, bool, boolArr, buildQuerySql, chatAdapter, chatBot, chatController, chatItemTypeOptions, cmd, cmdChannelName, cmdChannelSocketPath, command, commandHandler, container, cronHandler, description, errorToPlainObject, evaluateQueryAst, extractChatMessageText, extractNumberFromWasenderMessageKey, getClientMap, getPgClient, handshakeMiddlewares, inject, injectable, isArray, isBoolean, isChatMessageEmpty, isDate, isIn, isModel, isNotEmpty, isNumber, isOptional, isPresent, isRecord, isRetryableError, isString, jwtGuard, jwtHandshakeGuard, max, memExtension, middleware, min, mindset, mindsetModule, modelInfo, num, numArr, obj, onDelete, onGet, onPost, onPut, onSocketEvent, parseQueryMethodName, pgExtension, pgStorage, query, queryExtension, readJsonFromFile, repository, resolveConfigReferences, restController, run, runChatAdapters, runChatControllers, runCmdClient, runCommandHandlers, runCronHandlers, runRestControllers, runSocketControllers, safeJsonParse, scanProjectFiles, scoped, setupErrorHandlers, singleton, socket, socketChannelName, socketController, stopCommandHandlers, stopCronHandlers, str, strArr, telegram, telegramChannelName, transaction, validateAndTransform, validateArray, validateIsBoolean, validateIsDate, validateIsIn, validateIsNotEmpty, validateIsNumber, validateIsPresent, validateIsRecord, validateIsString, validateMax, validateMin, validateModel, wasender, wasenderChannelName, withPgClient, withPgTransaction, writeJsonToFile };
package/dist/src/index.js CHANGED
@@ -101,7 +101,7 @@ export { getClientMap, pgStorage } from './feature/pg/pgStorage.js';
101
101
  export { buildQuerySql } from './feature/pg/buildQuerySql.js';
102
102
  export { getPgClient, withPgClient } from './feature/pg/withPgClient.js';
103
103
  export { withPgTransaction } from './feature/pg/withPgTransaction.js';
104
- export { memoryExtension } from './feature/repository/@memoryExtension.js';
104
+ export { memExtension } from './feature/repository/@memExtension.js';
105
105
  export { query } from './feature/repository/@query.js';
106
106
  export { queryExtension } from './feature/repository/@queryExtension.js';
107
107
  export { repository } from './feature/repository/@repository.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wabot-dev/framework",
3
- "version": "0.9.16",
3
+ "version": "0.9.18",
4
4
  "description": "Framework for IA Chat Bots",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",