telemeister 0.1.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 +674 -0
- package/README.md +460 -0
- package/bin/telemeister.js +18 -0
- package/dist/bot/polling.d.ts +20 -0
- package/dist/bot/polling.d.ts.map +1 -0
- package/dist/bot/polling.js +115 -0
- package/dist/bot/polling.js.map +1 -0
- package/dist/bot/session.d.ts +50 -0
- package/dist/bot/session.d.ts.map +1 -0
- package/dist/bot/session.js +92 -0
- package/dist/bot/session.js.map +1 -0
- package/dist/bot/webhook.d.ts +36 -0
- package/dist/bot/webhook.d.ts.map +1 -0
- package/dist/bot/webhook.js +199 -0
- package/dist/bot/webhook.js.map +1 -0
- package/dist/bot-state-types.d.ts +10 -0
- package/dist/bot-state-types.d.ts.map +1 -0
- package/dist/bot-state-types.js +3 -0
- package/dist/bot-state-types.js.map +1 -0
- package/dist/cli/cli.d.ts +14 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +57 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/create-bot.d.ts +5 -0
- package/dist/cli/create-bot.d.ts.map +1 -0
- package/dist/cli/create-bot.js +275 -0
- package/dist/cli/create-bot.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +4 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/state-manager.d.ts +9 -0
- package/dist/cli/state-manager.d.ts.map +1 -0
- package/dist/cli/state-manager.js +381 -0
- package/dist/cli/state-manager.js.map +1 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +52 -0
- package/dist/config.js.map +1 -0
- package/dist/core/app-states.d.ts +8 -0
- package/dist/core/app-states.d.ts.map +1 -0
- package/dist/core/app-states.js +8 -0
- package/dist/core/app-states.js.map +1 -0
- package/dist/core/builder.d.ts +138 -0
- package/dist/core/builder.d.ts.map +1 -0
- package/dist/core/builder.js +195 -0
- package/dist/core/builder.js.map +1 -0
- package/dist/core/compact-machine.d.ts +57 -0
- package/dist/core/compact-machine.d.ts.map +1 -0
- package/dist/core/compact-machine.js +113 -0
- package/dist/core/compact-machine.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +47 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/database.d.ts +43 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +127 -0
- package/dist/database.js.map +1 -0
- package/dist/generated/prisma/browser.d.ts +15 -0
- package/dist/generated/prisma/browser.d.ts.map +1 -0
- package/dist/generated/prisma/browser.js +18 -0
- package/dist/generated/prisma/browser.js.map +1 -0
- package/dist/generated/prisma/client.d.ts +32 -0
- package/dist/generated/prisma/client.d.ts.map +1 -0
- package/dist/generated/prisma/client.js +33 -0
- package/dist/generated/prisma/client.js.map +1 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +166 -0
- package/dist/generated/prisma/commonInputTypes.d.ts.map +1 -0
- package/dist/generated/prisma/commonInputTypes.js +11 -0
- package/dist/generated/prisma/commonInputTypes.js.map +1 -0
- package/dist/generated/prisma/enums.d.ts +2 -0
- package/dist/generated/prisma/enums.d.ts.map +1 -0
- package/dist/generated/prisma/enums.js +11 -0
- package/dist/generated/prisma/enums.js.map +1 -0
- package/dist/generated/prisma/internal/class.d.ts +138 -0
- package/dist/generated/prisma/internal/class.d.ts.map +1 -0
- package/dist/generated/prisma/internal/class.js +50 -0
- package/dist/generated/prisma/internal/class.js.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +591 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +96 -0
- package/dist/generated/prisma/internal/prismaNamespace.js.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +56 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +67 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js.map +1 -0
- package/dist/generated/prisma/models/User.d.ts +1181 -0
- package/dist/generated/prisma/models/User.d.ts.map +1 -0
- package/dist/generated/prisma/models/User.js +2 -0
- package/dist/generated/prisma/models/User.js.map +1 -0
- package/dist/generated/prisma/models/UserInfo.d.ts +1101 -0
- package/dist/generated/prisma/models/UserInfo.d.ts.map +1 -0
- package/dist/generated/prisma/models/UserInfo.js +2 -0
- package/dist/generated/prisma/models/UserInfo.js.map +1 -0
- package/dist/generated/prisma/models.d.ts +4 -0
- package/dist/generated/prisma/models.d.ts.map +1 -0
- package/dist/generated/prisma/models.js +2 -0
- package/dist/generated/prisma/models.js.map +1 -0
- package/dist/handlers/idle/index.d.ts +2 -0
- package/dist/handlers/idle/index.d.ts.map +1 -0
- package/dist/handlers/idle/index.js +22 -0
- package/dist/handlers/idle/index.js.map +1 -0
- package/dist/handlers/index.d.ts +12 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +14 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/menu/index.d.ts +2 -0
- package/dist/handlers/menu/index.d.ts.map +1 -0
- package/dist/handlers/menu/index.js +35 -0
- package/dist/handlers/menu/index.js.map +1 -0
- package/dist/handlers/menu.d.ts +2 -0
- package/dist/handlers/menu.d.ts.map +1 -0
- package/dist/handlers/menu.js +37 -0
- package/dist/handlers/menu.js.map +1 -0
- package/dist/handlers/welcome/index.d.ts +2 -0
- package/dist/handlers/welcome/index.d.ts.map +1 -0
- package/dist/handlers/welcome/index.js +22 -0
- package/dist/handlers/welcome/index.js.map +1 -0
- package/dist/handlers/welcome.d.ts +2 -0
- package/dist/handlers/welcome.d.ts.map +1 -0
- package/dist/handlers/welcome.js +30 -0
- package/dist/handlers/welcome.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/package.json +111 -0
- package/templates/handler.ts.ejs +36 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Builder - Fluent API for configuring a single state
|
|
3
|
+
*
|
|
4
|
+
* @template TState - Union type of all valid states
|
|
5
|
+
*/
|
|
6
|
+
class StateBuilder {
|
|
7
|
+
state;
|
|
8
|
+
handlers;
|
|
9
|
+
constructor(state, handlers) {
|
|
10
|
+
this.state = state;
|
|
11
|
+
this.handlers = handlers;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Set the onEnter handler for this state
|
|
15
|
+
* Called when the user enters this state
|
|
16
|
+
* Can optionally return a state name to immediately transition to
|
|
17
|
+
*
|
|
18
|
+
* Example:
|
|
19
|
+
* .onEnter(async (ctx) => {
|
|
20
|
+
* await ctx.send('Welcome!');
|
|
21
|
+
* // Optionally transition immediately:
|
|
22
|
+
* return 'anotherState';
|
|
23
|
+
* })
|
|
24
|
+
*/
|
|
25
|
+
onEnter(handler) {
|
|
26
|
+
const existing = this.handlers.get(this.state) || {};
|
|
27
|
+
existing.onEnter = handler;
|
|
28
|
+
this.handlers.set(this.state, existing);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Set the onResponse handler for this state
|
|
33
|
+
* Called when the user sends a message while in this state
|
|
34
|
+
*
|
|
35
|
+
* Example:
|
|
36
|
+
* .onResponse(async (ctx, response) => {
|
|
37
|
+
* if (response === 'yes') {
|
|
38
|
+
* return 'confirmed';
|
|
39
|
+
* }
|
|
40
|
+
* return 'cancelled';
|
|
41
|
+
* })
|
|
42
|
+
*/
|
|
43
|
+
onResponse(handler) {
|
|
44
|
+
const existing = this.handlers.get(this.state) || {};
|
|
45
|
+
existing.onResponse = handler;
|
|
46
|
+
this.handlers.set(this.state, existing);
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Multi-State Builder - Registers handlers for multiple states at once
|
|
52
|
+
*
|
|
53
|
+
* @template TState - Union type of all valid states
|
|
54
|
+
*/
|
|
55
|
+
class MultiStateBuilder {
|
|
56
|
+
states;
|
|
57
|
+
handlers;
|
|
58
|
+
constructor(states, handlers) {
|
|
59
|
+
this.states = states;
|
|
60
|
+
this.handlers = handlers;
|
|
61
|
+
}
|
|
62
|
+
onEnter(handler) {
|
|
63
|
+
for (const state of this.states) {
|
|
64
|
+
const existing = this.handlers.get(state) || {};
|
|
65
|
+
existing.onEnter = handler;
|
|
66
|
+
this.handlers.set(state, existing);
|
|
67
|
+
}
|
|
68
|
+
return this;
|
|
69
|
+
}
|
|
70
|
+
onResponse(handler) {
|
|
71
|
+
for (const state of this.states) {
|
|
72
|
+
const existing = this.handlers.get(state) || {};
|
|
73
|
+
existing.onResponse = handler;
|
|
74
|
+
this.handlers.set(state, existing);
|
|
75
|
+
}
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Bot Builder - Main API for registering state handlers
|
|
81
|
+
*
|
|
82
|
+
* For type-safe state returns, define your states as a union type:
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // Define your states
|
|
87
|
+
* type MyStates = 'idle' | 'welcome' | 'menu' | 'collectName';
|
|
88
|
+
*
|
|
89
|
+
* // Create typed builder
|
|
90
|
+
* const typedBuilder = botBuilder as BotBuilder<MyStates>;
|
|
91
|
+
*
|
|
92
|
+
* typedBuilder
|
|
93
|
+
* .forState('welcome')
|
|
94
|
+
* .onEnter(async (ctx) => {
|
|
95
|
+
* await ctx.send('Welcome!');
|
|
96
|
+
* return 'menu'; // ✅ Type-safe: only 'idle' | 'welcome' | 'menu' | 'collectName' allowed
|
|
97
|
+
* })
|
|
98
|
+
* .onResponse(async (ctx, response) => {
|
|
99
|
+
* return 'collectName'; // ✅ Also type-safe
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @template TState - Union type of all valid states (defaults to string)
|
|
104
|
+
*/
|
|
105
|
+
export class BotBuilder {
|
|
106
|
+
handlers = new Map();
|
|
107
|
+
forState(state) {
|
|
108
|
+
if (Array.isArray(state)) {
|
|
109
|
+
return new MultiStateBuilder(state, this.handlers);
|
|
110
|
+
}
|
|
111
|
+
return new StateBuilder(state, this.handlers);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Register an onEnter handler for a state
|
|
115
|
+
* @param state - State name
|
|
116
|
+
* @param handler - Handler function
|
|
117
|
+
* @returns this for chaining
|
|
118
|
+
*/
|
|
119
|
+
onEnter(state, handler) {
|
|
120
|
+
const existing = this.handlers.get(state) || {};
|
|
121
|
+
existing.onEnter = handler;
|
|
122
|
+
this.handlers.set(state, existing);
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Register an onResponse handler for a state
|
|
127
|
+
* @param state - State name
|
|
128
|
+
* @param handler - Handler function
|
|
129
|
+
* @returns this for chaining
|
|
130
|
+
*/
|
|
131
|
+
onResponse(state, handler) {
|
|
132
|
+
const existing = this.handlers.get(state) || {};
|
|
133
|
+
existing.onResponse = handler;
|
|
134
|
+
this.handlers.set(state, existing);
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Execute the onEnter handler for a given state
|
|
139
|
+
* @internal Called by the bot handlers
|
|
140
|
+
* @returns The next state to transition to (if any), or void
|
|
141
|
+
*/
|
|
142
|
+
async executeOnEnter(state, context) {
|
|
143
|
+
const handlers = this.handlers.get(state);
|
|
144
|
+
const handler = handlers?.onEnter;
|
|
145
|
+
if (handler) {
|
|
146
|
+
return await handler(context);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Execute the onResponse handler for a given state
|
|
151
|
+
* @internal Called by the bot handlers
|
|
152
|
+
* @returns The next state to transition to, or void
|
|
153
|
+
*/
|
|
154
|
+
async executeOnResponse(state, context, response) {
|
|
155
|
+
const handlers = this.handlers.get(state);
|
|
156
|
+
const handler = handlers?.onResponse;
|
|
157
|
+
if (handler) {
|
|
158
|
+
return await handler(context, response);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if a state has an onEnter handler
|
|
163
|
+
*/
|
|
164
|
+
hasOnEnter(state) {
|
|
165
|
+
return !!this.handlers.get(state)?.onEnter;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Check if a state has an onResponse handler
|
|
169
|
+
*/
|
|
170
|
+
hasOnResponse(state) {
|
|
171
|
+
return !!this.handlers.get(state)?.onResponse;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Get all registered state names
|
|
175
|
+
*/
|
|
176
|
+
getRegisteredStates() {
|
|
177
|
+
return Array.from(this.handlers.keys());
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get handlers for a specific state
|
|
181
|
+
*/
|
|
182
|
+
getHandlers(state) {
|
|
183
|
+
return this.handlers.get(state);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Global bot builder instance (untyped - accepts any string state)
|
|
188
|
+
*
|
|
189
|
+
* For type safety, cast to BotBuilder<YourStateUnion>:
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const typedBuilder = botBuilder as BotBuilder<'idle' | 'welcome' | 'menu'>;
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export const botBuilder = new BotBuilder();
|
|
195
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/core/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { BotContext, BotMachineInput } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Compact XState Machine for Telemeister
|
|
4
|
+
*
|
|
5
|
+
* Uses the "states as data" pattern - a single state node handles
|
|
6
|
+
* all bot states. The actual state value is stored in context.currentState.
|
|
7
|
+
*
|
|
8
|
+
* Benefits:
|
|
9
|
+
* - No need to modify machine when adding new states
|
|
10
|
+
* - Compact, maintainable code
|
|
11
|
+
* - Builder pattern is the source of truth for valid states
|
|
12
|
+
* - Re-entry triggers onEnter handler for new states
|
|
13
|
+
*/
|
|
14
|
+
export declare const compactMachine: import("xstate").StateMachine<BotContext, {
|
|
15
|
+
type: "USER_MESSAGE";
|
|
16
|
+
message: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "TRANSITION";
|
|
19
|
+
toState: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: "REENTER";
|
|
22
|
+
}, {}, never, {
|
|
23
|
+
type: "updateState";
|
|
24
|
+
params: import("xstate").NonReducibleUnknown;
|
|
25
|
+
} | {
|
|
26
|
+
type: "persistState";
|
|
27
|
+
params: unknown;
|
|
28
|
+
}, never, never, "active", string, BotMachineInput, import("xstate").NonReducibleUnknown, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
29
|
+
id: "telemeister-bot";
|
|
30
|
+
states: {
|
|
31
|
+
readonly active: {};
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new machine instance with the given initial state
|
|
36
|
+
*/
|
|
37
|
+
export declare function createBotMachine(_input: BotMachineInput): import("xstate").StateMachine<BotContext, {
|
|
38
|
+
type: "USER_MESSAGE";
|
|
39
|
+
message: string;
|
|
40
|
+
} | {
|
|
41
|
+
type: "TRANSITION";
|
|
42
|
+
toState: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: "REENTER";
|
|
45
|
+
}, {}, never, {
|
|
46
|
+
type: "updateState";
|
|
47
|
+
params: import("xstate").NonReducibleUnknown;
|
|
48
|
+
} | {
|
|
49
|
+
type: "persistState";
|
|
50
|
+
params: unknown;
|
|
51
|
+
}, never, never, "active", string, BotMachineInput, import("xstate").NonReducibleUnknown, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
52
|
+
id: "telemeister-bot";
|
|
53
|
+
states: {
|
|
54
|
+
readonly active: {};
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
57
|
+
//# sourceMappingURL=compact-machine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-machine.d.ts","sourceRoot":"","sources":["../../src/core/compact-machine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAY,eAAe,EAAE,MAAM,YAAY,CAAC;AAExE;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;EAqDzB,CAAC;AAEH;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe;;;;;;;;;;;;;;;;;;;GA0CvD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { setup, assign } from 'xstate';
|
|
2
|
+
/**
|
|
3
|
+
* Compact XState Machine for Telemeister
|
|
4
|
+
*
|
|
5
|
+
* Uses the "states as data" pattern - a single state node handles
|
|
6
|
+
* all bot states. The actual state value is stored in context.currentState.
|
|
7
|
+
*
|
|
8
|
+
* Benefits:
|
|
9
|
+
* - No need to modify machine when adding new states
|
|
10
|
+
* - Compact, maintainable code
|
|
11
|
+
* - Builder pattern is the source of truth for valid states
|
|
12
|
+
* - Re-entry triggers onEnter handler for new states
|
|
13
|
+
*/
|
|
14
|
+
export const compactMachine = setup({
|
|
15
|
+
types: {
|
|
16
|
+
context: {},
|
|
17
|
+
events: {},
|
|
18
|
+
input: {},
|
|
19
|
+
},
|
|
20
|
+
actions: {
|
|
21
|
+
/**
|
|
22
|
+
* Update the current state in context
|
|
23
|
+
*/
|
|
24
|
+
updateState: assign({
|
|
25
|
+
currentState: ({ event }) => (event.type === 'TRANSITION' ? event.toState : ''),
|
|
26
|
+
}),
|
|
27
|
+
/**
|
|
28
|
+
* Persist state to database
|
|
29
|
+
* This is called as an action, but actual DB calls happen
|
|
30
|
+
* in the bot handlers to keep the machine pure.
|
|
31
|
+
*/
|
|
32
|
+
persistState: ({ context }) => {
|
|
33
|
+
// The actual persistence is handled by the bot layer
|
|
34
|
+
// This action serves as a hook for inspection/logging
|
|
35
|
+
console.log(`[XState] State changed to: ${context.currentState}`);
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}).createMachine({
|
|
39
|
+
id: 'telemeister-bot',
|
|
40
|
+
initial: 'active',
|
|
41
|
+
context: ({ input: _input }) => ({
|
|
42
|
+
userId: _input.userId,
|
|
43
|
+
telegramId: _input.telegramId,
|
|
44
|
+
chatId: _input.chatId,
|
|
45
|
+
currentState: _input.currentState,
|
|
46
|
+
stateData: _input.stateData,
|
|
47
|
+
}),
|
|
48
|
+
states: {
|
|
49
|
+
active: {
|
|
50
|
+
entry: ['persistState'],
|
|
51
|
+
on: {
|
|
52
|
+
TRANSITION: {
|
|
53
|
+
actions: ['updateState', 'persistState'],
|
|
54
|
+
// Self-transition with reentry to trigger onEnter
|
|
55
|
+
target: 'active',
|
|
56
|
+
reenter: true,
|
|
57
|
+
},
|
|
58
|
+
REENTER: {
|
|
59
|
+
// Re-enter current state (e.g., to re-trigger onEnter)
|
|
60
|
+
target: 'active',
|
|
61
|
+
reenter: true,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Create a new machine instance with the given initial state
|
|
69
|
+
*/
|
|
70
|
+
export function createBotMachine(_input) {
|
|
71
|
+
return setup({
|
|
72
|
+
types: {
|
|
73
|
+
context: {},
|
|
74
|
+
events: {},
|
|
75
|
+
input: {},
|
|
76
|
+
},
|
|
77
|
+
actions: {
|
|
78
|
+
updateState: assign({
|
|
79
|
+
currentState: ({ event }) => (event.type === 'TRANSITION' ? event.toState : ''),
|
|
80
|
+
}),
|
|
81
|
+
persistState: ({ context }) => {
|
|
82
|
+
console.log(`[XState] State changed to: ${context.currentState}`);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
}).createMachine({
|
|
86
|
+
id: 'telemeister-bot',
|
|
87
|
+
initial: 'active',
|
|
88
|
+
context: ({ input }) => ({
|
|
89
|
+
userId: input.userId,
|
|
90
|
+
telegramId: input.telegramId,
|
|
91
|
+
chatId: input.chatId,
|
|
92
|
+
currentState: input.currentState,
|
|
93
|
+
stateData: input.stateData,
|
|
94
|
+
}),
|
|
95
|
+
states: {
|
|
96
|
+
active: {
|
|
97
|
+
entry: ['persistState'],
|
|
98
|
+
on: {
|
|
99
|
+
TRANSITION: {
|
|
100
|
+
actions: ['updateState', 'persistState'],
|
|
101
|
+
target: 'active',
|
|
102
|
+
reenter: true,
|
|
103
|
+
},
|
|
104
|
+
REENTER: {
|
|
105
|
+
target: 'active',
|
|
106
|
+
reenter: true,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=compact-machine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compact-machine.js","sourceRoot":"","sources":["../../src/core/compact-machine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core module for Telemeister
|
|
3
|
+
*
|
|
4
|
+
* This module exports the centralized state types and typed builder.
|
|
5
|
+
* Import from here in your handlers for type safety.
|
|
6
|
+
*/
|
|
7
|
+
export { BotBuilder, botBuilder } from './builder.js';
|
|
8
|
+
export type { AppStates } from '../bot-state-types.js';
|
|
9
|
+
export type { StateTransitions } from '../bot-state-types.js';
|
|
10
|
+
export { appBuilder } from './types.js';
|
|
11
|
+
export type { AppContext } from './types.js';
|
|
12
|
+
export type { BotHandlerContext, BotState, EnterHandler, ResponseHandler, StateHandlers, } from './types.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEtD,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,YAAY,EACV,iBAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core module for Telemeister
|
|
3
|
+
*
|
|
4
|
+
* This module exports the centralized state types and typed builder.
|
|
5
|
+
* Import from here in your handlers for type safety.
|
|
6
|
+
*/
|
|
7
|
+
export { BotBuilder, botBuilder } from './builder.js';
|
|
8
|
+
export { appBuilder } from './types.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAKtD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { AppStates } from '../bot-state-types.js';
|
|
2
|
+
import { BotBuilder } from './builder.js';
|
|
3
|
+
export declare const appBuilder: BotBuilder<AppStates>;
|
|
4
|
+
export type AppContext = BotHandlerContext<AppStates>;
|
|
5
|
+
export type BotState = string;
|
|
6
|
+
export interface BotHandlerContext<TState extends BotState = BotState> {
|
|
7
|
+
userId: number;
|
|
8
|
+
telegramId: number;
|
|
9
|
+
chatId: number;
|
|
10
|
+
currentState: TState;
|
|
11
|
+
send: (text: string) => Promise<unknown>;
|
|
12
|
+
setData: <T>(key: string, value: T) => void;
|
|
13
|
+
getData: <T>(key: string) => T | undefined;
|
|
14
|
+
transition: (toState: TState) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export type EnterHandler<TState extends BotState = BotState> = (context: BotHandlerContext<TState>) => Promise<TState | void>;
|
|
17
|
+
export type ResponseHandler<TState extends BotState = BotState> = (context: BotHandlerContext<TState>, response: string) => Promise<TState | void>;
|
|
18
|
+
export interface StateHandlers<TState extends BotState = BotState> {
|
|
19
|
+
onEnter?: EnterHandler<TState>;
|
|
20
|
+
onResponse?: ResponseHandler<TState>;
|
|
21
|
+
}
|
|
22
|
+
export type ExtractStates<T> = T extends StateHandlers<infer S> ? S : never;
|
|
23
|
+
export interface BotContext {
|
|
24
|
+
userId: number;
|
|
25
|
+
telegramId: number;
|
|
26
|
+
chatId: number;
|
|
27
|
+
currentState: string;
|
|
28
|
+
stateData: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
export type BotEvent = {
|
|
31
|
+
type: 'USER_MESSAGE';
|
|
32
|
+
message: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'TRANSITION';
|
|
35
|
+
toState: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: 'REENTER';
|
|
38
|
+
};
|
|
39
|
+
export interface BotMachineInput {
|
|
40
|
+
userId: number;
|
|
41
|
+
telegramId: number;
|
|
42
|
+
chatId: number;
|
|
43
|
+
currentState: string;
|
|
44
|
+
stateData: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
export type { StateTransitions } from '../bot-state-types.js';
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,eAAO,MAAM,UAAU,uBAA8B,CAAC;AAEtD,MAAM,MAAM,UAAU,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAEtD,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,WAAW,iBAAiB,CAAC,MAAM,SAAS,QAAQ,GAAG,QAAQ;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,SAAS,CAAC;IAC3C,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAC7D,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,KAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,MAAM,eAAe,CAAC,MAAM,SAAS,QAAQ,GAAG,QAAQ,IAAI,CAChE,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAClC,QAAQ,EAAE,MAAM,KACb,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,WAAW,aAAa,CAAC,MAAM,SAAS,QAAQ,GAAG,QAAQ;IAC/D,OAAO,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE5E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAa,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Uses Prisma ORM 7.x with driver adapters for database operations.
|
|
5
|
+
*
|
|
6
|
+
* Switch between SQLite and MySQL by changing DATABASE_URL in .env:
|
|
7
|
+
* - SQLite: DATABASE_URL="file:./dev.db"
|
|
8
|
+
* - MySQL: DATABASE_URL="mysql://user:password@localhost:3306/dbname"
|
|
9
|
+
*
|
|
10
|
+
* Note: When switching providers, update the provider in prisma/schema.prisma:
|
|
11
|
+
* - SQLite: provider = "sqlite"
|
|
12
|
+
* - MySQL: provider = "mysql"
|
|
13
|
+
*/
|
|
14
|
+
import 'dotenv/config';
|
|
15
|
+
import { User, UserInfo } from './generated/prisma/client.js';
|
|
16
|
+
declare const prisma: import("./generated/prisma/internal/class.js").PrismaClient<never, import("./generated/prisma/internal/prismaNamespace.js").GlobalOmitConfig | undefined, import("@prisma/client/runtime/client").DefaultArgs>;
|
|
17
|
+
export type { User, UserInfo };
|
|
18
|
+
export type UserWithInfo = User & {
|
|
19
|
+
info: UserInfo | null;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Get user by Telegram ID with joined user info
|
|
23
|
+
*/
|
|
24
|
+
export declare function getUserByTelegramId(telegramId: number): Promise<UserWithInfo | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Create or update a user
|
|
27
|
+
*/
|
|
28
|
+
export declare function createOrUpdateUser(data: {
|
|
29
|
+
telegramId: number;
|
|
30
|
+
chatId: number;
|
|
31
|
+
currentState?: string;
|
|
32
|
+
stateData?: Record<string, unknown>;
|
|
33
|
+
}): Promise<UserWithInfo>;
|
|
34
|
+
/**
|
|
35
|
+
* Update user state and optional state data
|
|
36
|
+
*/
|
|
37
|
+
export declare function updateUserState(telegramId: number, currentState: string, stateData?: Record<string, unknown>): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Disconnect from database
|
|
40
|
+
*/
|
|
41
|
+
export declare function disconnectDB(): Promise<void>;
|
|
42
|
+
export { prisma };
|
|
43
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAgB,IAAI,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAmB5E,QAAA,MAAM,MAAM,gNAAgC,CAAC;AAG7C,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAG/B,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG;IAChC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAO1F;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,GAAG,OAAO,CAAC,YAAY,CAAC,CAkDxB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/dist/database.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Entry Point
|
|
3
|
+
*
|
|
4
|
+
* Uses Prisma ORM 7.x with driver adapters for database operations.
|
|
5
|
+
*
|
|
6
|
+
* Switch between SQLite and MySQL by changing DATABASE_URL in .env:
|
|
7
|
+
* - SQLite: DATABASE_URL="file:./dev.db"
|
|
8
|
+
* - MySQL: DATABASE_URL="mysql://user:password@localhost:3306/dbname"
|
|
9
|
+
*
|
|
10
|
+
* Note: When switching providers, update the provider in prisma/schema.prisma:
|
|
11
|
+
* - SQLite: provider = "sqlite"
|
|
12
|
+
* - MySQL: provider = "mysql"
|
|
13
|
+
*/
|
|
14
|
+
import 'dotenv/config';
|
|
15
|
+
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';
|
|
16
|
+
import { PrismaClient } from './generated/prisma/client.js';
|
|
17
|
+
// Determine database provider from URL
|
|
18
|
+
const databaseUrl = process.env.DATABASE_URL || 'file:./dev.db';
|
|
19
|
+
const isMysql = databaseUrl.startsWith('mysql:');
|
|
20
|
+
// Create adapter based on database type
|
|
21
|
+
// For now, SQLite is fully supported. MySQL adapter requires additional setup.
|
|
22
|
+
const adapter = isMysql
|
|
23
|
+
? (() => {
|
|
24
|
+
throw new Error('MySQL adapter not yet configured. Please configure @prisma/adapter-mariadb in src/database.ts');
|
|
25
|
+
})()
|
|
26
|
+
: new PrismaBetterSqlite3({
|
|
27
|
+
url: databaseUrl,
|
|
28
|
+
});
|
|
29
|
+
// Prisma client instance with adapter
|
|
30
|
+
const prisma = new PrismaClient({ adapter });
|
|
31
|
+
/**
|
|
32
|
+
* Get user by Telegram ID with joined user info
|
|
33
|
+
*/
|
|
34
|
+
export async function getUserByTelegramId(telegramId) {
|
|
35
|
+
const user = await prisma.user.findUnique({
|
|
36
|
+
where: { telegramId },
|
|
37
|
+
include: { info: true },
|
|
38
|
+
});
|
|
39
|
+
return user;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create or update a user
|
|
43
|
+
*/
|
|
44
|
+
export async function createOrUpdateUser(data) {
|
|
45
|
+
const existingUser = await getUserByTelegramId(data.telegramId);
|
|
46
|
+
if (existingUser) {
|
|
47
|
+
// Update existing user
|
|
48
|
+
const updatedUser = await prisma.user.update({
|
|
49
|
+
where: { telegramId: data.telegramId },
|
|
50
|
+
data: {
|
|
51
|
+
chatId: data.chatId,
|
|
52
|
+
...(data.currentState && { currentState: data.currentState }),
|
|
53
|
+
},
|
|
54
|
+
include: { info: true },
|
|
55
|
+
});
|
|
56
|
+
// Update or create user info if stateData provided
|
|
57
|
+
if (data.stateData) {
|
|
58
|
+
await prisma.userInfo.upsert({
|
|
59
|
+
where: { userId: updatedUser.id },
|
|
60
|
+
create: {
|
|
61
|
+
userId: updatedUser.id,
|
|
62
|
+
stateData: JSON.stringify(data.stateData),
|
|
63
|
+
},
|
|
64
|
+
update: {
|
|
65
|
+
stateData: JSON.stringify(data.stateData),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
// Return updated user with info
|
|
69
|
+
return (await getUserByTelegramId(data.telegramId));
|
|
70
|
+
}
|
|
71
|
+
return updatedUser;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Create new user with info
|
|
75
|
+
const newUser = await prisma.user.create({
|
|
76
|
+
data: {
|
|
77
|
+
telegramId: data.telegramId,
|
|
78
|
+
chatId: data.chatId,
|
|
79
|
+
currentState: data.currentState || 'idle',
|
|
80
|
+
info: {
|
|
81
|
+
create: {
|
|
82
|
+
stateData: JSON.stringify(data.stateData || {}),
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
include: { info: true },
|
|
87
|
+
});
|
|
88
|
+
return newUser;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Update user state and optional state data
|
|
93
|
+
*/
|
|
94
|
+
export async function updateUserState(telegramId, currentState, stateData) {
|
|
95
|
+
const user = await prisma.user.findUnique({
|
|
96
|
+
where: { telegramId },
|
|
97
|
+
});
|
|
98
|
+
if (!user) {
|
|
99
|
+
throw new Error(`User with telegramId ${telegramId} not found`);
|
|
100
|
+
}
|
|
101
|
+
// Update user state
|
|
102
|
+
await prisma.user.update({
|
|
103
|
+
where: { telegramId },
|
|
104
|
+
data: { currentState },
|
|
105
|
+
});
|
|
106
|
+
// Update state data if provided
|
|
107
|
+
if (stateData) {
|
|
108
|
+
await prisma.userInfo.upsert({
|
|
109
|
+
where: { userId: user.id },
|
|
110
|
+
create: {
|
|
111
|
+
userId: user.id,
|
|
112
|
+
stateData: JSON.stringify(stateData),
|
|
113
|
+
},
|
|
114
|
+
update: {
|
|
115
|
+
stateData: JSON.stringify(stateData),
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Disconnect from database
|
|
122
|
+
*/
|
|
123
|
+
export async function disconnectDB() {
|
|
124
|
+
await prisma.$disconnect();
|
|
125
|
+
}
|
|
126
|
+
export { prisma };
|
|
127
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"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"}
|