@builderbot/manager 1.0.0

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/LICENSE.md ADDED
@@ -0,0 +1,16 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2024, Leifer Mendez
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @builderbot/manager
2
+
3
+ Multi-tenant bot manager for BuilderBot. Manage multiple WhatsApp bot instances, each with its own session, flows, and configuration.
4
+
5
+ ## Features
6
+
7
+ - **Multi-tenant Support**: Run multiple WhatsApp bots simultaneously
8
+ - **Isolated Sessions**: Each tenant gets its own session storage
9
+ - **REST API**: Built-in API for managing bots via HTTP
10
+ - **Dynamic Flows**: Create and manage flows via API
11
+ - **Event System**: Subscribe to bot lifecycle events
12
+ - **Swagger UI**: Auto-generated API documentation
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pnpm add @builderbot/manager
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import { BotManager, BotManagerApi } from '@builderbot/manager'
24
+ import { addKeyword } from '@builderbot/bot'
25
+
26
+ // Create the manager
27
+ const manager = new BotManager({
28
+ sessionsDir: './sessions'
29
+ })
30
+
31
+ // Create the API server
32
+ const api = new BotManagerApi(manager, {
33
+ port: 3000,
34
+ apiKey: 'your-secret-key' // optional
35
+ })
36
+
37
+ // Register a flow
38
+ const greetingFlow = addKeyword(['hola', 'hello'])
39
+ .addAnswer('¡Hola! Bienvenido')
40
+ .addAnswer('¿En qué puedo ayudarte?')
41
+
42
+ api.registerFlow('greeting', 'Greeting Flow', greetingFlow)
43
+
44
+ // Start the API
45
+ api.start()
46
+ ```
47
+
48
+ ## API Endpoints
49
+
50
+ ### Health
51
+ - `GET /api/health` - Health check
52
+
53
+ ### Flows
54
+ - `GET /api/flows` - List all flows
55
+ - `POST /api/flows` - Create a dynamic flow
56
+ - `GET /api/flows/:flowId` - Get flow by ID
57
+ - `PUT /api/flows/:flowId` - Update a dynamic flow
58
+ - `DELETE /api/flows/:flowId` - Delete a dynamic flow
59
+
60
+ ### Bots
61
+ - `GET /api/bots` - List all bots
62
+ - `POST /api/bots` - Create a new bot
63
+ - `GET /api/bots/:tenantId` - Get bot by tenant ID
64
+ - `PUT /api/bots/:tenantId` - Update bot
65
+ - `DELETE /api/bots/:tenantId` - Delete bot
66
+ - `GET /api/bots/:tenantId/qr` - Get QR code
67
+ - `POST /api/bots/:tenantId/restart` - Restart bot
68
+ - `POST /api/bots/:tenantId/stop` - Stop bot
69
+
70
+ ### Documentation
71
+ - `GET /docs` - Swagger UI
72
+
73
+ ## Creating Bots via API
74
+
75
+ ```bash
76
+ # Create a flow first
77
+ curl -X POST http://localhost:3000/api/flows \
78
+ -H "Content-Type: application/json" \
79
+ -H "X-API-Key: your-secret-key" \
80
+ -d '{
81
+ "id": "greeting",
82
+ "name": "Greeting Flow",
83
+ "keyword": ["hola", "hello"],
84
+ "steps": [
85
+ { "answer": "¡Hola! Bienvenido", "delay": 500 },
86
+ { "answer": "¿En qué puedo ayudarte?" }
87
+ ]
88
+ }'
89
+
90
+ # Create a bot using the flow
91
+ curl -X POST http://localhost:3000/api/bots \
92
+ -H "Content-Type: application/json" \
93
+ -H "X-API-Key: your-secret-key" \
94
+ -d '{
95
+ "tenantId": "my-bot",
96
+ "name": "My WhatsApp Bot",
97
+ "flowIds": ["greeting"],
98
+ "port": 3008
99
+ }'
100
+
101
+ # Get QR code to connect
102
+ curl http://localhost:3000/api/bots/my-bot/qr \
103
+ -H "X-API-Key: your-secret-key"
104
+ ```
105
+
106
+ ## Event Handling
107
+
108
+ ```typescript
109
+ manager.on('bot:created', (tenantId, data) => {
110
+ console.log(`Bot ${tenantId} created`)
111
+ })
112
+
113
+ manager.on('bot:connected', (tenantId) => {
114
+ console.log(`Bot ${tenantId} connected to WhatsApp`)
115
+ })
116
+
117
+ manager.on('bot:qr', (tenantId, data) => {
118
+ console.log(`QR for ${tenantId}:`, data.qr)
119
+ })
120
+
121
+ manager.on('bot:disconnected', (tenantId) => {
122
+ console.log(`Bot ${tenantId} disconnected`)
123
+ })
124
+
125
+ manager.on('bot:error', (tenantId, data) => {
126
+ console.error(`Error in bot ${tenantId}:`, data.error)
127
+ })
128
+ ```
129
+
130
+ ## Programmatic Usage
131
+
132
+ ```typescript
133
+ // Create a bot programmatically
134
+ const bot = await manager.createBot({
135
+ tenantId: 'tenant-1',
136
+ name: 'Tenant 1 Bot',
137
+ flows: [greetingFlow],
138
+ port: 3001
139
+ })
140
+
141
+ // Get bot info
142
+ const info = manager.getBot('tenant-1')
143
+
144
+ // Get all bots summary
145
+ const allBots = manager.getBotsInfo()
146
+
147
+ // Send a message
148
+ await manager.sendMessage('tenant-1', '1234567890', 'Hello!')
149
+
150
+ // Remove a bot
151
+ await manager.removeBot('tenant-1')
152
+
153
+ // Shutdown all bots
154
+ await manager.shutdown()
155
+ ```
156
+
157
+ ## License
158
+
159
+ ISC
160
+
package/dist/api.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ import type { BotManager } from './bot-manager';
2
+ import type { Flow } from './types';
3
+ import { FlowRegistry, type FlowDefinition } from './flow-registry';
4
+ import { type RateLimiterConfig } from './rate-limiter';
5
+ interface ApiConfig {
6
+ port: number;
7
+ apiKey?: string;
8
+ /** Rate limiter configuration */
9
+ rateLimit?: RateLimiterConfig | false;
10
+ }
11
+ /**
12
+ * REST API for managing bots via HTTP endpoints using Polka
13
+ */
14
+ export declare class BotManagerApi {
15
+ private manager;
16
+ private config;
17
+ private app;
18
+ private flowRegistry;
19
+ private qrCodes;
20
+ private rateLimiter;
21
+ constructor(manager: BotManager, config: ApiConfig);
22
+ /**
23
+ * Get the flow registry for external access
24
+ */
25
+ getFlowRegistry(): FlowRegistry;
26
+ /**
27
+ * Register a flow that can be used when creating bots via API
28
+ */
29
+ registerFlow(id: string, name: string, flow: Flow): FlowDefinition;
30
+ /**
31
+ * Get all registered flows
32
+ */
33
+ getRegisteredFlows(): FlowDefinition[];
34
+ /**
35
+ * Get a single flow by ID
36
+ */
37
+ getFlow(id: string): FlowDefinition | undefined;
38
+ /**
39
+ * Listen for QR codes to store them
40
+ */
41
+ private setupQrListener;
42
+ /**
43
+ * JSON body parser middleware
44
+ */
45
+ private jsonParser;
46
+ /**
47
+ * CORS middleware
48
+ */
49
+ private cors;
50
+ /**
51
+ * Auth middleware
52
+ */
53
+ private auth;
54
+ /**
55
+ * Send JSON response
56
+ */
57
+ private sendJson;
58
+ /**
59
+ * Start the API server
60
+ */
61
+ start(): void;
62
+ /**
63
+ * Stop the API server
64
+ */
65
+ stop(): void;
66
+ private handleCreateBot;
67
+ private handleUpdateBot;
68
+ private handleRestartBot;
69
+ private handleCreateFlow;
70
+ private handleUpdateFlow;
71
+ }
72
+ export {};
73
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAcnC,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAe,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAEpE,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,iCAAiC;IACjC,SAAS,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAA;CACtC;AAQD;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAY;IAC3B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,GAAG,CAAwC;IACnD,OAAO,CAAC,YAAY,CAAc;IAClC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,WAAW,CAA2B;gBAElC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS;IAYlD;;OAEG;IACH,eAAe,IAAI,YAAY;IAI/B;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,cAAc;IAIlE;;OAEG;IACH,kBAAkB,IAAI,cAAc,EAAE;IAItC;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI/C;;OAEG;IACH,OAAO,CAAC,eAAe;IAYvB;;OAEG;IACH,OAAO,CAAC,UAAU;IAkBlB;;OAEG;IACH,OAAO,CAAC,IAAI;IAeZ;;OAEG;IACH,OAAO,CAAC,IAAI;IAmBZ;;OAEG;IACH,OAAO,CAAC,QAAQ;IAKhB;;OAEG;IACH,KAAK,IAAI,IAAI;IAsNb;;OAEG;IACH,IAAI,IAAI,IAAI;YAYE,eAAe;YAiDf,eAAe;YA2Bf,gBAAgB;YAuChB,gBAAgB;YA+BhB,gBAAgB;CAyC/B"}
@@ -0,0 +1,125 @@
1
+ import type { TenantConfig, BotInstance, BotManagerConfig, BotStatus, BotManagerEvent, BotManagerEventHandler, ReconnectState } from './types';
2
+ /**
3
+ * Multi-tenant Bot Manager
4
+ * Manages multiple WhatsApp bot instances, each with its own session and flows
5
+ */
6
+ export declare class BotManager {
7
+ private bots;
8
+ private config;
9
+ private eventHandlers;
10
+ private reconnectStates;
11
+ private tenantConfigs;
12
+ constructor(config?: BotManagerConfig);
13
+ /**
14
+ * Create a new bot instance for a tenant
15
+ */
16
+ createBot(tenantConfig: TenantConfig): Promise<BotInstance>;
17
+ /**
18
+ * Setup event listeners on the provider for real-time status updates
19
+ */
20
+ private setupProviderEvents;
21
+ /**
22
+ * Attempt to reconnect a disconnected bot with exponential backoff
23
+ */
24
+ private attemptReconnect;
25
+ /**
26
+ * Helper delay function
27
+ */
28
+ private delay;
29
+ /**
30
+ * Get a bot instance by tenant ID
31
+ */
32
+ getBot(tenantId: string): BotInstance | undefined;
33
+ /**
34
+ * Remove a bot instance and clean up resources
35
+ */
36
+ removeBot(tenantId: string): Promise<boolean>;
37
+ /**
38
+ * List all active tenant IDs
39
+ */
40
+ listBots(): string[];
41
+ /**
42
+ * Get all bot instances
43
+ */
44
+ getAllBots(): BotInstance[];
45
+ /**
46
+ * Check if a tenant has an active bot
47
+ */
48
+ hasBot(tenantId: string): boolean;
49
+ /**
50
+ * Get the count of active bots
51
+ */
52
+ getBotCount(): number;
53
+ /**
54
+ * Shutdown all bots
55
+ */
56
+ shutdown(): Promise<void>;
57
+ /**
58
+ * Register an event handler
59
+ */
60
+ on(event: BotManagerEvent, handler: BotManagerEventHandler): void;
61
+ /**
62
+ * Remove an event handler
63
+ */
64
+ off(event: BotManagerEvent, handler: BotManagerEventHandler): void;
65
+ /**
66
+ * Emit an event
67
+ */
68
+ private emit;
69
+ /**
70
+ * Get bot status
71
+ */
72
+ getBotStatus(tenantId: string): BotStatus | undefined;
73
+ /**
74
+ * Update bot status
75
+ */
76
+ updateBotStatus(tenantId: string, status: BotStatus): void;
77
+ /**
78
+ * Get reconnection state for a bot
79
+ */
80
+ getReconnectState(tenantId: string): ReconnectState | undefined;
81
+ /**
82
+ * Manually trigger reconnection for a bot
83
+ */
84
+ reconnectBot(tenantId: string): Promise<boolean>;
85
+ /**
86
+ * Restart a bot by removing and recreating it
87
+ */
88
+ restartBot(tenantId: string, newConfig?: Partial<TenantConfig>): Promise<BotInstance | null>;
89
+ /**
90
+ * Get summary info of all bots (useful for dashboards)
91
+ */
92
+ getBotsInfo(): Array<{
93
+ tenantId: string;
94
+ name: string;
95
+ status: BotStatus;
96
+ port?: number;
97
+ createdAt: Date;
98
+ uptime: number;
99
+ providerType?: string;
100
+ databaseType?: string;
101
+ reconnectState?: ReconnectState;
102
+ }>;
103
+ /**
104
+ * Get detailed health information
105
+ */
106
+ getHealthInfo(): {
107
+ status: 'healthy' | 'degraded' | 'unhealthy';
108
+ bots: {
109
+ total: number;
110
+ connected: number;
111
+ disconnected: number;
112
+ error: number;
113
+ initializing: number;
114
+ };
115
+ memory: NodeJS.MemoryUsage;
116
+ uptime: number;
117
+ };
118
+ /**
119
+ * Send message through a specific bot
120
+ */
121
+ sendMessage(tenantId: string, number: string, message: string, options?: {
122
+ media?: string;
123
+ }): Promise<boolean>;
124
+ }
125
+ //# sourceMappingURL=bot-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot-manager.d.ts","sourceRoot":"","sources":["../src/bot-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ import type { Flow } from './types';
2
+ import type { CreateFlowInput, UpdateFlowInput } from './schemas';
3
+ /**
4
+ * Flow definition stored in registry
5
+ */
6
+ export interface FlowDefinition {
7
+ id: string;
8
+ name: string;
9
+ flow: Flow;
10
+ /** Whether this flow was created dynamically via API */
11
+ dynamic: boolean;
12
+ /** Original configuration for dynamic flows */
13
+ config?: CreateFlowInput;
14
+ /** Timestamp when flow was registered */
15
+ createdAt: Date;
16
+ /** Timestamp when flow was last updated */
17
+ updatedAt: Date;
18
+ }
19
+ /**
20
+ * FlowRegistry manages flow definitions that can be used when creating bots
21
+ */
22
+ export declare class FlowRegistry {
23
+ private flows;
24
+ /**
25
+ * Register a programmatic flow (created with addKeyword)
26
+ */
27
+ register(id: string, name: string, flow: Flow): FlowDefinition;
28
+ /**
29
+ * Register a dynamic flow from JSON configuration
30
+ */
31
+ registerDynamic(config: CreateFlowInput): FlowDefinition;
32
+ /**
33
+ * Update a dynamic flow
34
+ */
35
+ update(id: string, updates: UpdateFlowInput): FlowDefinition | null;
36
+ /**
37
+ * Remove a flow from registry
38
+ */
39
+ remove(id: string): boolean;
40
+ /**
41
+ * Get a flow by ID
42
+ */
43
+ get(id: string): FlowDefinition | undefined;
44
+ /**
45
+ * Get all registered flows
46
+ */
47
+ getAll(): FlowDefinition[];
48
+ /**
49
+ * Check if a flow exists
50
+ */
51
+ has(id: string): boolean;
52
+ /**
53
+ * Get all flow IDs
54
+ */
55
+ getIds(): string[];
56
+ /**
57
+ * Get count of registered flows
58
+ */
59
+ count(): number;
60
+ /**
61
+ * Clear all flows
62
+ */
63
+ clear(): void;
64
+ /**
65
+ * Get flows by type (dynamic or programmatic)
66
+ */
67
+ getByType(dynamic: boolean): FlowDefinition[];
68
+ /**
69
+ * Resolve multiple flow IDs to Flow objects
70
+ */
71
+ resolveFlows(flowIds: string[]): {
72
+ flows: Flow[];
73
+ missing: string[];
74
+ };
75
+ /**
76
+ * Build a flow from steps configuration
77
+ */
78
+ private buildFlowFromSteps;
79
+ /**
80
+ * Export all dynamic flows as serializable configs
81
+ */
82
+ exportDynamicFlows(): CreateFlowInput[];
83
+ /**
84
+ * Import dynamic flows from configs
85
+ */
86
+ importDynamicFlows(configs: CreateFlowInput[]): {
87
+ imported: number;
88
+ failed: string[];
89
+ };
90
+ }
91
+ //# sourceMappingURL=flow-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-registry.d.ts","sourceRoot":"","sources":["../src/flow-registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAY,MAAM,WAAW,CAAA;AAE3E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAA;IAChB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yCAAyC;IACzC,SAAS,EAAE,IAAI,CAAA;IACf,2CAA2C;IAC3C,SAAS,EAAE,IAAI,CAAA;CAChB;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAyC;IAEtD;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,cAAc;IAa9D;;OAEG;IACH,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc;IAmBxD;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,GAAG,IAAI;IA+BnE;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI3B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAI3C;;OAEG;IACH,MAAM,IAAI,cAAc,EAAE;IAI1B;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;OAEG;IACH,MAAM,IAAI,MAAM,EAAE;IAIlB;;OAEG;IACH,KAAK,IAAI,MAAM;IAIf;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,EAAE;IAI7C;;OAEG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG;QAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE;IAgBrE;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoB1B;;OAEG;IACH,kBAAkB,IAAI,eAAe,EAAE;IAMvC;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAiBvF"}