@wabot-dev/framework 0.9.13 → 0.9.15

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.
package/README.md CHANGED
@@ -38,6 +38,71 @@ visita nuestra documentación 📘 **[Ver guía completa de inicio →](https://
38
38
 
39
39
  ---
40
40
 
41
+ ## 📦 Building for production
42
+
43
+ En modo dev, el framework descubre módulos escaneando el disco. Para producción, el framework incluye un script que empaqueta tu proyecto en un único `dist/entry.js` autocontenido usando `tsup`.
44
+
45
+ ### 1. Instala `tsup` como dev dependency del consumidor
46
+
47
+ ```bash
48
+ npm i -D tsup
49
+ ```
50
+
51
+ ### 2. Cambia `_run_.ts` para exportar la config
52
+
53
+ En vez de invocar `run()` directamente, exporta `config` para que tanto dev como build la puedan usar:
54
+
55
+ ```ts
56
+ // src/_run_.ts
57
+ import { run, IProjectRunnerConfig } from '@wabot-dev/framework'
58
+
59
+ export const config: IProjectRunnerConfig = {
60
+ directories: ['src'],
61
+ }
62
+
63
+ // Solo en dev: arrancar inmediatamente.
64
+ if (process.env.WABOT_BUNDLED !== '1') {
65
+ run(config)
66
+ }
67
+ ```
68
+
69
+ ### 3. Configura el build (opcional)
70
+
71
+ Crea `wabot.build.json` en la raíz del proyecto o agrega un campo `wabot` al `package.json`:
72
+
73
+ ```json
74
+ {
75
+ "entry": "./src/_run_.ts",
76
+ "directories": ["src"],
77
+ "exclude": ["_run_.ts", "_cmd_.ts"],
78
+ "outDir": "./dist",
79
+ "sourcemap": true,
80
+ "minify": false,
81
+ "external": ["pg"]
82
+ }
83
+ ```
84
+
85
+ ### 4. Agrega los scripts
86
+
87
+ ```json
88
+ "scripts": {
89
+ "dev": "node --import @yucacodes/ts ./src/_run_.ts",
90
+ "build": "node ./node_modules/@wabot-dev/framework/dist/build/build.js",
91
+ "start": "WABOT_BUNDLED=1 node ./dist/entry.js"
92
+ }
93
+ ```
94
+
95
+ El script de build:
96
+
97
+ 1. Escanea las `directories` configuradas (saltando tests y `_run_.ts`/`_cmd_.ts`).
98
+ 2. Genera un manifiesto temporal en `.wabot/` con imports estáticos a cada módulo.
99
+ 3. Empaqueta todo con `tsup` (ESM, single-file) en `dist/entry.js`.
100
+ 4. Arranca el runtime en modo `preloaded: true`, así que **no hay `readdir` ni imports dinámicos por template literal** en el bundle final.
101
+
102
+ Los addons opcionales (`pg`, SDKs de IA) se mantienen como `peerDependencies` y solo entran al bundle si tu proyecto los usa.
103
+
104
+ ---
105
+
41
106
  ## 💬 Plataformas Soportadas
42
107
 
43
108
  Wabot se integra nativamente con las principales plataformas de mensajería:
@@ -0,0 +1,200 @@
1
+ import { realpathSync, existsSync } from 'node:fs';
2
+ import { readdir, mkdir, writeFile, rm, readFile } from 'node:fs/promises';
3
+ import { resolve, join, relative, sep, isAbsolute } from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const TEST_FILE_PATTERNS = /\.(test|spec|unit|integration|e2e|multiprocess)\.(ts|js)$/;
7
+ const DEFAULT_DIRECTORIES = ['src'];
8
+ const DEFAULT_EXCLUDE = ['_run_.ts', '_cmd_.ts'];
9
+ async function scanProjectFiles(opts = {}) {
10
+ const directories = opts.directories ?? DEFAULT_DIRECTORIES;
11
+ const exclude = [...DEFAULT_EXCLUDE, ...(opts.exclude ?? [])];
12
+ const seen = new Set();
13
+ const roots = directories
14
+ .map((d) => resolve(d))
15
+ .filter((d) => {
16
+ if (seen.has(d))
17
+ return false;
18
+ seen.add(d);
19
+ return true;
20
+ });
21
+ const excludedNames = new Set();
22
+ const excludedPathsByRoot = new Map();
23
+ for (const entry of exclude) {
24
+ if (entry.includes('/') || entry.includes('\\')) {
25
+ for (const root of roots) {
26
+ let paths = excludedPathsByRoot.get(root);
27
+ if (!paths) {
28
+ paths = new Set();
29
+ excludedPathsByRoot.set(root, paths);
30
+ }
31
+ paths.add(resolve(root, entry));
32
+ }
33
+ }
34
+ else {
35
+ excludedNames.add(entry);
36
+ }
37
+ }
38
+ const results = await Promise.all(roots.map((dir) => {
39
+ const excludedPaths = excludedPathsByRoot.get(dir) ?? new Set();
40
+ return scanDir(dir, excludedNames, excludedPaths).catch(() => []);
41
+ }));
42
+ return results.flat();
43
+ }
44
+ async function scanDir(dir, excludedNames, excludedPaths) {
45
+ const entries = await readdir(dir, { withFileTypes: true });
46
+ const subResults = await Promise.all(entries.map(async (entry) => {
47
+ const name = entry.name;
48
+ const fullPath = join(dir, name);
49
+ if (excludedNames.has(name))
50
+ return [];
51
+ if (excludedPaths.has(fullPath))
52
+ return [];
53
+ if (entry.isDirectory()) {
54
+ if (name.startsWith('__'))
55
+ return [];
56
+ return scanDir(fullPath, excludedNames, excludedPaths);
57
+ }
58
+ if (!entry.isFile())
59
+ return [];
60
+ if (!(name.endsWith('.ts') || name.endsWith('.js')))
61
+ return [];
62
+ if (name.endsWith('.d.ts'))
63
+ return [];
64
+ if (TEST_FILE_PATTERNS.test(fullPath))
65
+ return [];
66
+ return [fullPath];
67
+ }));
68
+ return subResults.flat();
69
+ }
70
+
71
+ const MANIFEST_BANNER = '// auto-generated by @wabot-dev/framework build, do not edit';
72
+ /**
73
+ * Convert an absolute source path into an ESM import specifier relative to
74
+ * the manifest directory. Uses forward slashes on every OS and rewrites
75
+ * `.ts`/`.tsx` to `.js` so the bundler can resolve it statically.
76
+ */
77
+ function toManifestImport(absFile, manifestDir) {
78
+ let rel = relative(manifestDir, absFile);
79
+ if (sep !== '/')
80
+ rel = rel.split(sep).join('/');
81
+ if (!rel.startsWith('./') && !rel.startsWith('../'))
82
+ rel = './' + rel;
83
+ return rel.replace(/\.tsx?$/, '.js').replace(/\.jsx$/, '.js');
84
+ }
85
+ function generateManifest(absFiles, manifestDir) {
86
+ const imports = [...absFiles]
87
+ .sort()
88
+ .map((f) => `import '${toManifestImport(f, manifestDir)}'`);
89
+ return `${MANIFEST_BANNER}\n${imports.join('\n')}\n`;
90
+ }
91
+ function generateEntry(manifestDir, consumerEntry, frameworkPackageName) {
92
+ const lines = [MANIFEST_BANNER, "import './manifest.js'"];
93
+ if (consumerEntry) {
94
+ const spec = toManifestImport(consumerEntry, manifestDir);
95
+ lines.push(`import * as __wabot_user_entry from '${spec}'`);
96
+ lines.push(`import { run as __wabot_run } from '${frameworkPackageName}'`);
97
+ lines.push('const __wabot_cfg = ((__wabot_user_entry as any).config ?? (__wabot_user_entry as any).default ?? {})');
98
+ lines.push('await __wabot_run({ ...__wabot_cfg, preloaded: true })');
99
+ }
100
+ else {
101
+ lines.push(`import { run as __wabot_run } from '${frameworkPackageName}'`);
102
+ lines.push('await __wabot_run({ preloaded: true })');
103
+ }
104
+ return lines.join('\n') + '\n';
105
+ }
106
+
107
+ const FRAMEWORK_PACKAGE = '@wabot-dev/framework';
108
+ const MANIFEST_DIRNAME = '.wabot';
109
+ async function readJsonIfExists(path) {
110
+ if (!existsSync(path))
111
+ return null;
112
+ const raw = await readFile(path, 'utf-8');
113
+ return JSON.parse(raw);
114
+ }
115
+ async function loadBuildConfig(cwd) {
116
+ const fromFile = await readJsonIfExists(resolve(cwd, 'wabot.build.json'));
117
+ if (fromFile)
118
+ return fromFile;
119
+ const pkg = await readJsonIfExists(resolve(cwd, 'package.json'));
120
+ return pkg?.wabot ?? {};
121
+ }
122
+ function absolutize(cwd, p) {
123
+ return isAbsolute(p) ? p : resolve(cwd, p);
124
+ }
125
+ async function runBuild(options = {}) {
126
+ const cwd = options.cwd ?? process.cwd();
127
+ const config = await loadBuildConfig(cwd);
128
+ const entry = config.entry ? absolutize(cwd, config.entry) : absolutize(cwd, './src/_run_.ts');
129
+ const directories = config.directories ?? ['src'];
130
+ const exclude = config.exclude ?? [];
131
+ const outDir = absolutize(cwd, config.outDir ?? './dist');
132
+ const sourcemap = config.sourcemap ?? true;
133
+ const minify = config.minify ?? false;
134
+ const manifestDir = resolve(cwd, MANIFEST_DIRNAME);
135
+ await mkdir(manifestDir, { recursive: true });
136
+ const prevCwd = process.cwd();
137
+ let discovered;
138
+ try {
139
+ process.chdir(cwd);
140
+ discovered = await scanProjectFiles({ directories, exclude });
141
+ }
142
+ finally {
143
+ process.chdir(prevCwd);
144
+ }
145
+ const entryResolved = existsSync(entry) ? entry : null;
146
+ const filesForManifest = discovered.filter((f) => f !== entry);
147
+ const manifestSrc = generateManifest(filesForManifest, manifestDir);
148
+ const entrySrc = generateEntry(manifestDir, entryResolved, FRAMEWORK_PACKAGE);
149
+ await writeFile(resolve(manifestDir, 'manifest.ts'), manifestSrc, 'utf-8');
150
+ await writeFile(resolve(manifestDir, 'entry.ts'), entrySrc, 'utf-8');
151
+ let tsup;
152
+ try {
153
+ tsup = await import('tsup');
154
+ }
155
+ catch {
156
+ throw new Error(`tsup is not installed in the consumer project. Install it as a dev dependency: npm i -D tsup`);
157
+ }
158
+ try {
159
+ await tsup.build({
160
+ entry: [resolve(manifestDir, 'entry.ts')],
161
+ format: ['esm'],
162
+ outDir,
163
+ clean: true,
164
+ sourcemap,
165
+ minify,
166
+ splitting: false,
167
+ bundle: true,
168
+ target: 'node20',
169
+ tsconfig: existsSync(resolve(cwd, 'tsconfig.json'))
170
+ ? resolve(cwd, 'tsconfig.json')
171
+ : undefined,
172
+ external: config.external ?? ['pg'],
173
+ });
174
+ }
175
+ finally {
176
+ if (!options.keep) {
177
+ await rm(manifestDir, { recursive: true, force: true });
178
+ }
179
+ }
180
+ }
181
+ function isMainModule() {
182
+ const argvEntry = process.argv[1];
183
+ if (!argvEntry)
184
+ return false;
185
+ try {
186
+ return realpathSync(argvEntry) === realpathSync(fileURLToPath(import.meta.url));
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ }
192
+ if (isMainModule()) {
193
+ const keep = process.argv.includes('--keep');
194
+ runBuild({ keep }).catch((err) => {
195
+ console.error(err instanceof Error ? err.message : err);
196
+ process.exit(1);
197
+ });
198
+ }
199
+
200
+ export { loadBuildConfig, runBuild };
@@ -1,5 +1,3 @@
1
- import { readdir } from 'node:fs/promises';
2
- import { resolve, join } from 'node:path';
3
1
  import { pathToFileURL } from 'node:url';
4
2
  import { container } from '../../core/injection/index.js';
5
3
  import { Logger } from '../../core/logger/Logger.js';
@@ -33,53 +31,57 @@ import { runSocketControllers } from '../socket-controller/runSocketControllers.
33
31
  import { MemoryRepositoryAdapter } from '../repository/MemoryRepositoryAdapter.js';
34
32
  import { RepositoryMetadataStore } from '../repository/RepositoryMetadataStore.js';
35
33
  import { RepositoryAdapterRegistry } from '../repository/RepositoryAdapterRegistry.js';
34
+ import { scanProjectFiles } from './scanner.js';
36
35
 
37
36
  const logger = new Logger('wabot:project-runner');
38
- const TEST_FILE_PATTERNS = /\.(test|spec|unit|integration|e2e|multiprocess)\.(ts|js)$/;
39
- const DEFAULT_EXCLUDE = ['_run_.ts', '_cmd_.ts'];
40
- const MODULE_EXT = import.meta.url.endsWith('.ts') ? '.ts' : '.js';
41
- const DEFAULT_CHAT_ADAPTERS = [
42
- {
43
- path: `../../addon/chat-bot/openia/OpenaiChatAdapter${MODULE_EXT}`,
44
- name: 'OpenaiChatAdapter',
37
+ const DEFAULT_ADAPTER_LOADERS = {
38
+ openai: {
45
39
  apiKeyEnv: 'OPENAI_API_KEY',
40
+ load: async () => (await import('../../addon/chat-bot/openia/OpenaiChatAdapter.js')).OpenaiChatAdapter,
46
41
  },
47
- {
48
- path: `../../addon/chat-bot/openrouter/OpenRouterChatAdapter${MODULE_EXT}`,
49
- name: 'OpenRouterChatAdapter',
42
+ openrouter: {
50
43
  apiKeyEnv: 'OPENROUTER_API_KEY',
44
+ load: async () => (await import('../../addon/chat-bot/openrouter/OpenRouterChatAdapter.js'))
45
+ .OpenRouterChatAdapter,
51
46
  },
52
- {
53
- path: `../../addon/chat-bot/anthropic/AnthropicChatAdapter${MODULE_EXT}`,
54
- name: 'AnthropicChatAdapter',
47
+ anthropic: {
55
48
  apiKeyEnv: 'ANTHROPIC_API_KEY',
49
+ load: async () => (await import('../../addon/chat-bot/anthropic/AnthropicChatAdapter.js'))
50
+ .AnthropicChatAdapter,
56
51
  },
57
- {
58
- path: `../../addon/chat-bot/google/GoogleChatAdapter${MODULE_EXT}`,
59
- name: 'GoogleChatAdapter',
52
+ google: {
60
53
  apiKeyEnv: 'GOOGLE_API_KEY',
54
+ load: async () => (await import('../../addon/chat-bot/google/GoogleChatAdapter.js')).GoogleChatAdapter,
61
55
  },
62
- ];
56
+ };
63
57
  class ProjectRunner {
64
58
  directories;
65
59
  exclude;
66
60
  chatAdapters;
67
61
  connectionString;
68
62
  isPg;
63
+ preloaded;
69
64
  pool = null;
70
65
  constructor(config = {}) {
71
66
  this.directories = config.directories ?? ['src'];
72
- this.exclude = [...DEFAULT_EXCLUDE, ...(config.exclude ?? [])];
67
+ this.exclude = config.exclude ?? [];
73
68
  this.chatAdapters = config.chatAdapters;
74
69
  this.connectionString = this.resolveConnectionString(config.connectionString);
75
70
  this.isPg = this.connectionString != null && isPostgresUrl(this.connectionString);
71
+ this.preloaded = config.preloaded === true;
76
72
  }
77
73
  async run() {
78
- const [, files] = await Promise.all([
79
- this.isPg ? this.initPool() : Promise.resolve(),
80
- this.scanDirectories(),
81
- ]);
82
- await this.importFiles(files);
74
+ if (this.preloaded) {
75
+ if (this.isPg)
76
+ await this.initPool();
77
+ }
78
+ else {
79
+ const [, files] = await Promise.all([
80
+ this.isPg ? this.initPool() : Promise.resolve(),
81
+ scanProjectFiles({ directories: this.directories, exclude: this.exclude }),
82
+ ]);
83
+ await this.importFiles(files);
84
+ }
83
85
  const components = this.discoverComponents();
84
86
  await this.registerAdapters(components);
85
87
  await this.startComponents(components);
@@ -96,42 +98,6 @@ class ProjectRunner {
96
98
  this.pool = new Pool({ connectionString: this.connectionString });
97
99
  container.registerInstance(Pool, this.pool);
98
100
  }
99
- async scanDirectories() {
100
- const seen = new Set();
101
- const roots = this.directories
102
- .map((d) => resolve(d))
103
- .filter((d) => {
104
- if (seen.has(d))
105
- return false;
106
- seen.add(d);
107
- return true;
108
- });
109
- const excludedNames = new Set();
110
- const excludedPathsByRoot = new Map();
111
- for (const entry of this.exclude) {
112
- if (entry.includes('/') || entry.includes('\\')) {
113
- for (const root of roots) {
114
- let paths = excludedPathsByRoot.get(root);
115
- if (!paths) {
116
- paths = new Set();
117
- excludedPathsByRoot.set(root, paths);
118
- }
119
- paths.add(resolve(root, entry));
120
- }
121
- }
122
- else {
123
- excludedNames.add(entry);
124
- }
125
- }
126
- const results = await Promise.all(roots.map((dir) => {
127
- const excludedPaths = excludedPathsByRoot.get(dir) ?? new Set();
128
- return scanDir(dir, excludedNames, excludedPaths).catch((err) => {
129
- logger.warn(`Could not read directory ${dir}: ${err.message}`);
130
- return [];
131
- });
132
- }));
133
- return results.flat();
134
- }
135
101
  async importFiles(files) {
136
102
  if (files.length === 0) {
137
103
  logger.info('No files to import');
@@ -278,15 +244,16 @@ class ProjectRunner {
278
244
  }
279
245
  }
280
246
  async resolveDefaultChatAdapters() {
281
- const results = await Promise.all(DEFAULT_CHAT_ADAPTERS.map(async ({ path, name, apiKeyEnv }) => {
247
+ const keys = Object.keys(DEFAULT_ADAPTER_LOADERS);
248
+ const results = await Promise.all(keys.map(async (key) => {
249
+ const { apiKeyEnv, load } = DEFAULT_ADAPTER_LOADERS[key];
282
250
  if (!process.env[apiKeyEnv])
283
251
  return null;
284
252
  try {
285
- const mod = await import(path);
286
- const adapter = mod[name];
253
+ const adapter = await load();
287
254
  if (!adapter)
288
255
  return null;
289
- logger.info(`Using ${name}`);
256
+ logger.info(`Using ${adapter.name}`);
290
257
  return adapter;
291
258
  }
292
259
  catch {
@@ -302,31 +269,5 @@ function run(config) {
302
269
  function isPostgresUrl(cs) {
303
270
  return cs.startsWith('postgres://') || cs.startsWith('postgresql://');
304
271
  }
305
- async function scanDir(dir, excludedNames, excludedPaths) {
306
- const entries = await readdir(dir, { withFileTypes: true });
307
- const subResults = await Promise.all(entries.map(async (entry) => {
308
- const name = entry.name;
309
- const fullPath = join(dir, name);
310
- if (excludedNames.has(name))
311
- return [];
312
- if (excludedPaths.has(fullPath))
313
- return [];
314
- if (entry.isDirectory()) {
315
- if (name.startsWith('__'))
316
- return [];
317
- return scanDir(fullPath, excludedNames, excludedPaths);
318
- }
319
- if (!entry.isFile())
320
- return [];
321
- if (!(name.endsWith('.ts') || name.endsWith('.js')))
322
- return [];
323
- if (name.endsWith('.d.ts'))
324
- return [];
325
- if (TEST_FILE_PATTERNS.test(fullPath))
326
- return [];
327
- return [fullPath];
328
- }));
329
- return subResults.flat();
330
- }
331
272
 
332
273
  export { ProjectRunner, run };
@@ -0,0 +1,69 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { resolve, join } from 'node:path';
3
+
4
+ const TEST_FILE_PATTERNS = /\.(test|spec|unit|integration|e2e|multiprocess)\.(ts|js)$/;
5
+ const DEFAULT_DIRECTORIES = ['src'];
6
+ const DEFAULT_EXCLUDE = ['_run_.ts', '_cmd_.ts'];
7
+ async function scanProjectFiles(opts = {}) {
8
+ const directories = opts.directories ?? DEFAULT_DIRECTORIES;
9
+ const exclude = [...DEFAULT_EXCLUDE, ...(opts.exclude ?? [])];
10
+ const seen = new Set();
11
+ const roots = directories
12
+ .map((d) => resolve(d))
13
+ .filter((d) => {
14
+ if (seen.has(d))
15
+ return false;
16
+ seen.add(d);
17
+ return true;
18
+ });
19
+ const excludedNames = new Set();
20
+ const excludedPathsByRoot = new Map();
21
+ for (const entry of exclude) {
22
+ if (entry.includes('/') || entry.includes('\\')) {
23
+ for (const root of roots) {
24
+ let paths = excludedPathsByRoot.get(root);
25
+ if (!paths) {
26
+ paths = new Set();
27
+ excludedPathsByRoot.set(root, paths);
28
+ }
29
+ paths.add(resolve(root, entry));
30
+ }
31
+ }
32
+ else {
33
+ excludedNames.add(entry);
34
+ }
35
+ }
36
+ const results = await Promise.all(roots.map((dir) => {
37
+ const excludedPaths = excludedPathsByRoot.get(dir) ?? new Set();
38
+ return scanDir(dir, excludedNames, excludedPaths).catch(() => []);
39
+ }));
40
+ return results.flat();
41
+ }
42
+ async function scanDir(dir, excludedNames, excludedPaths) {
43
+ const entries = await readdir(dir, { withFileTypes: true });
44
+ const subResults = await Promise.all(entries.map(async (entry) => {
45
+ const name = entry.name;
46
+ const fullPath = join(dir, name);
47
+ if (excludedNames.has(name))
48
+ return [];
49
+ if (excludedPaths.has(fullPath))
50
+ return [];
51
+ if (entry.isDirectory()) {
52
+ if (name.startsWith('__'))
53
+ return [];
54
+ return scanDir(fullPath, excludedNames, excludedPaths);
55
+ }
56
+ if (!entry.isFile())
57
+ return [];
58
+ if (!(name.endsWith('.ts') || name.endsWith('.js')))
59
+ return [];
60
+ if (name.endsWith('.d.ts'))
61
+ return [];
62
+ if (TEST_FILE_PATTERNS.test(fullPath))
63
+ return [];
64
+ return [fullPath];
65
+ }));
66
+ return subResults.flat();
67
+ }
68
+
69
+ export { scanProjectFiles };
@@ -1128,6 +1128,16 @@ interface IProjectRunnerConfig {
1128
1128
  exclude?: string[];
1129
1129
  connectionString?: string;
1130
1130
  chatAdapters?: IConstructor<IChatAdapter>[];
1131
+ /**
1132
+ * When true, skip filesystem discovery (no readdir, no dynamic import of
1133
+ * source files) and start directly from the metadata that was registered
1134
+ * during the host module's import-time side effects.
1135
+ *
1136
+ * The caller is responsible for having imported every module that registers
1137
+ * controllers, handlers, adapters, etc. before invoking run(). This is the
1138
+ * mode used by the bundled output produced by src/build/build.ts.
1139
+ */
1140
+ preloaded?: boolean;
1131
1141
  }
1132
1142
  declare class ProjectRunner {
1133
1143
  private directories;
@@ -1135,12 +1145,12 @@ declare class ProjectRunner {
1135
1145
  private chatAdapters;
1136
1146
  private connectionString;
1137
1147
  private isPg;
1148
+ private preloaded;
1138
1149
  private pool;
1139
1150
  constructor(config?: IProjectRunnerConfig);
1140
1151
  run(): Promise<void>;
1141
1152
  private resolveConnectionString;
1142
1153
  private initPool;
1143
- private scanDirectories;
1144
1154
  private importFiles;
1145
1155
  private discoverComponents;
1146
1156
  private registerAdapters;
@@ -1151,6 +1161,12 @@ declare class ProjectRunner {
1151
1161
  }
1152
1162
  declare function run(config?: IProjectRunnerConfig): Promise<void>;
1153
1163
 
1164
+ interface IScanProjectFilesOptions {
1165
+ directories?: string[];
1166
+ exclude?: string[];
1167
+ }
1168
+ declare function scanProjectFiles(opts?: IScanProjectFilesOptions): Promise<string[]>;
1169
+
1154
1170
  interface IchatControllerConfig {
1155
1171
  }
1156
1172
 
@@ -2469,4 +2485,4 @@ declare function HtmlModule(options: IHtmlModuleOptions): {
2469
2485
  new (): {};
2470
2486
  };
2471
2487
 
2472
- 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 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, 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 };
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 };
package/dist/src/index.js CHANGED
@@ -58,6 +58,7 @@ export { runCommandHandlers, stopCommandHandlers } from './feature/async/runComm
58
58
  export { runCronHandlers, stopCronHandlers } from './feature/async/runCronHandlers.js';
59
59
  export { TransactionMetadataStore } from './feature/async/TransactionMetadataStore.js';
60
60
  export { ProjectRunner, run } from './feature/project-runner/ProjectRunner.js';
61
+ export { scanProjectFiles } from './feature/project-runner/scanner.js';
61
62
  export { Chat } from './feature/chat-bot/Chat.js';
62
63
  export { ChatAdapter } from './feature/chat-bot/ChatAdapter.js';
63
64
  export { ChatAdapterRegistry } from './feature/chat-bot/ChatAdapterRegistry.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wabot-dev/framework",
3
- "version": "0.9.13",
3
+ "version": "0.9.15",
4
4
  "description": "Framework for IA Chat Bots",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -39,6 +39,7 @@
39
39
  ],
40
40
  "files": [
41
41
  "dist/src",
42
+ "dist/build",
42
43
  "LICENSE.md"
43
44
  ],
44
45
  "scripts": {
@@ -49,9 +50,9 @@
49
50
  "fmt": "prettier --write .",
50
51
  "fmt:check": "prettier --check .",
51
52
  "types:check": "tsc --noEmit",
52
- "elia:dev": "node --import @yucacodes/ts --import ./env.mjs ./test/elia/run.ts",
53
- "elia:watch": "node --watch --import @yucacodes/ts --import ./env.mjs ./test/elia/run.ts",
54
- "cmd:channel": "node --import @yucacodes/ts ./test/cmd.ts"
53
+ "elia:dev": "node --import @yucacodes/ts --import ./env.mjs ./test/elia/_run_.ts",
54
+ "elia:watch": "node --watch --import @yucacodes/ts --import ./env.mjs ./test/elia/_run_.ts",
55
+ "elia:cmd:channel": "node --import @yucacodes/ts ./test/elia/_cmd_.ts"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@rollup/plugin-alias": "5.1.1",