@monixlite/grammy-scenes 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +74 -153
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,38 +1,39 @@
1
1
  # @monixlite/grammy-scenes
2
2
 
3
- A lightweight FSM (Finite State Machine) engine for Telegram bots built on grammY.
4
- The module implements step-based scenes with declarative step definitions, automatic transitions, session-based state management, and an extensible navigation system.
3
+ A lightweight Finite State Machine (FSM) engine for Telegram bots built on grammY.
4
+ The library provides step-based scenes with declarative definitions, session-backed state, deterministic transitions, and extensible navigation.
5
5
 
6
6
  ---
7
7
 
8
8
  ## Installation
9
9
 
10
- ```bash
10
+ ```
11
11
  npm install @monixlite/grammy-scenes
12
12
  ```
13
13
 
14
14
  ## Requirements
15
15
 
16
- Node.js >= 16
17
- grammY >= 1.19
16
+ * Node.js >= 16
17
+ * grammY >= 1.19
18
18
 
19
19
  ---
20
20
 
21
- ## Core Concept
21
+ ## Core Concepts
22
+
23
+ A scene is a sequence of ordered steps grouped under a shared title. Each step is defined declaratively and reacts to Telegram updates via callbacks.
22
24
 
23
- A scene is a sequence of steps united under a common title.
24
- Each step is described by an object containing:
25
+ The active scene state is stored in `ctx.session.scene`.
25
26
 
26
- scene and step identifiers
27
- • a set of callbacks reacting to Telegram events (enter, message, callbackQuery)
27
+ Each step definition contains:
28
28
 
29
- The current scene state is stored in `ctx.session.scene`.
29
+ * scene identifier (title + step)
30
+ * callbacks for lifecycle and update handling
30
31
 
31
32
  ---
32
33
 
33
34
  ## Basic Usage
34
35
 
35
- ```js
36
+ ```
36
37
  const { Bot, session } = require("grammy");
37
38
  const { Scenes } = require("@monixlite/grammy-scenes");
38
39
 
@@ -46,7 +47,7 @@ const bot = new Bot("..."); {
46
47
  };
47
48
 
48
49
 
49
- const scene = new Scenes([
50
+ const scenes = new Scenes([
50
51
  [
51
52
  {
52
53
  scene: {
@@ -76,21 +77,20 @@ const scene = new Scenes([
76
77
  const { phone } = ctx.session;
77
78
 
78
79
 
79
- await ctx.reply(([
80
+ await ctx.reply([
80
81
  `• Your phone number: ${phone}`,
81
- `• Is this correct?`
82
- ]).join("\n"), {
82
+ `• Is this correct?`,
83
+ ].join("\n"), {
83
84
  reply_markup: {
84
85
  inline_keyboard: [
85
86
  [
86
87
  {
87
88
  text: "• Yes",
88
- callback_data: "confirm:yes"
89
+ callback_data: "confirm:yes",
89
90
  },
90
-
91
91
  {
92
92
  text: "• No",
93
- callback_data: "confirm:no"
93
+ callback_data: "confirm:no",
94
94
  },
95
95
  ],
96
96
  ],
@@ -106,7 +106,7 @@ const scene = new Scenes([
106
106
 
107
107
 
108
108
  await ctx.answerCallbackQuery();
109
- await ctx.reply(`• Thank you! Your phone number ${phone} has been saved.`);
109
+ await ctx.reply(`• Thank you! ${phone} saved.`);
110
110
 
111
111
 
112
112
  return "stop";
@@ -126,7 +126,7 @@ const scene = new Scenes([
126
126
  },
127
127
  ],
128
128
  ], {
129
- ["callbacks:enter:buttons:cancel"]: {
129
+ "callbacks:enter:buttons:cancel": {
130
130
  enabled: true,
131
131
 
132
132
  component: {
@@ -144,19 +144,20 @@ bot.callbackQuery("scene:cancel", async (ctx) => {
144
144
  await ctx.editMessageReplyMarkup(null);
145
145
  await ctx.answerCallbackQuery();
146
146
 
147
- await ctx.reply("• Scene cancelled!");
147
+
148
+ await ctx.reply("• Scene cancelled");
148
149
  });
149
150
 
150
151
 
151
152
  bot.command("start", async (ctx) => {
152
- return await scene.enter(ctx, {
153
+ await scenes.enter(ctx, {
153
154
  title: "auth",
154
155
  step: "phone",
155
156
  });
156
157
  });
157
158
 
158
159
 
159
- bot.use(scene.middleware);
160
+ bot.use(scenes.middleware);
160
161
 
161
162
  bot.start();
162
163
  ```
@@ -165,9 +166,7 @@ bot.start();
165
166
 
166
167
  ## Scene Definition
167
168
 
168
- Each scene step is described by the following structure:
169
-
170
- ```js
169
+ ```
171
170
  {
172
171
  scene: {
173
172
  title: string,
@@ -186,59 +185,35 @@ Each scene step is described by the following structure:
186
185
  }
187
186
  ```
188
187
 
189
- `SceneResult` is a value that determines the next transition (described below).
188
+ `SceneResult` determines the next transition.
190
189
 
191
190
  ---
192
191
 
193
192
  ## Callbacks
194
193
 
195
- ### callbacks.enter(ctx)
196
-
197
- Triggered when entering a scene step.
198
- Used to send messages, keyboards, or initialize data.
194
+ ### enter(ctx)
199
195
 
200
- Details:
196
+ Executed on step entry.
201
197
 
202
- Executed automatically on step entry
203
- Can freely use `ctx.reply`
204
- • If the cancel button option is enabled, it is automatically appended to the inline keyboard
198
+ * Used for messages and keyboards
199
+ * Cancel button can be injected automatically
205
200
 
206
- ---
201
+ ### update(ctx)
207
202
 
208
- ### callbacks.update(ctx)
203
+ Executed on any update while the step is active.
209
204
 
210
- Triggered on **any update** while the step is active.
205
+ * Runs before `message` and `query`
206
+ * Suitable for guards, timeouts, media
207
+ * Return value controls navigation
211
208
 
212
- Details:
209
+ ### message(ctx)
213
210
 
214
- Executed before `message` and `query`
215
- • Receives the raw grammY context
216
- • Can be used for global step logic (timeouts, guards, media handling)
217
- • Return value controls navigation using standard SceneResult rules
211
+ Triggered on text messages during the step.
218
212
 
219
- ---
213
+ ### query[]
220
214
 
221
- ### callbacks.message(ctx)
222
-
223
- Triggered when a text message is received while the step is active.
224
-
225
- ---
226
-
227
- ### callbacks.query
228
-
229
- An array of `callbackQuery` handlers.
230
-
231
- Each handler has the following shape:
232
-
233
- ```js
234
- {
235
- match: RegExp,
236
- handler: async (ctx) => SceneResult
237
- }
238
- ```
239
-
240
- When `match` matches `ctx.callbackQuery.data`, the corresponding handler is executed.
241
- Its return value is processed using the same transition logic as `callbacks.message`.
215
+ CallbackQuery handlers matched by regexp.
216
+ The handler return value follows standard transition rules.
242
217
 
243
218
  ---
244
219
 
@@ -246,122 +221,74 @@ Its return value is processed using the same transition logic as `callbacks.mess
246
221
 
247
222
  ### scenes.enter(ctx, scene)
248
223
 
249
- Forces entry into a scene and step.
250
-
251
- ```js
252
- await scenes.enter(ctx, {
253
- title: "auth",
254
- step: "phone",
255
- });
256
- ```
224
+ Forces entering a scene step.
257
225
 
258
226
  Behavior:
259
227
 
260
- Writes the scene into `ctx.session.scene`
261
- Locates the step definition
262
- Executes `callbacks.enter` if present
263
- Temporarily overrides `ctx.reply` to append the cancel button
264
-
265
- ---
266
-
267
- ### Cancel a Scene Manually
228
+ * Writes to `ctx.session.scene`
229
+ * Resolves step
230
+ * Executes `enter`
231
+ * Temporarily patches `ctx.reply` for cancel button injection
268
232
 
269
- A scene can be terminated manually:
233
+ ### Manual Termination
270
234
 
271
- ```js
235
+ ```
272
236
  ctx.session.scene = null;
273
237
  ```
274
238
 
275
- After this, the middleware stops processing scene events.
276
-
277
239
  ---
278
240
 
279
241
  ## Middleware
280
242
 
281
- ```js
243
+ ```
282
244
  bot.use(session(...));
283
245
  bot.use(scenes.middleware);
284
246
  ```
285
247
 
286
248
  The middleware:
287
249
 
288
- Checks for an active scene in the session
289
- Resolves the current step
290
- Delegates updates to the appropriate callbacks
291
- • Executes step transitions
250
+ * Resolves the active step
251
+ * Dispatches updates to callbacks
252
+ * Applies transitions
292
253
 
293
- The middleware **must** be registered after the session middleware.
254
+ Must be registered after session middleware.
294
255
 
295
256
  ---
296
257
 
297
258
  ## Step Navigation
298
259
 
299
- Transitions are determined by the value returned from callbacks.
300
-
301
- ### Terminating a Scene
260
+ Transitions are driven by callback return values.
302
261
 
303
- `"stop"`, `"exit"`, `"!"`
304
- → `ctx.session.scene = null`
262
+ ### Transitions
305
263
 
306
- ---
307
-
308
- ### All Transitions
264
+ * `undefined`, `"next"`, `">"` → next step
265
+ * `"prev"`, `"<"` → previous step
266
+ * `"stop"`, `"exit"`, `"!"` → terminate scene
267
+ * `"^step"` → jump within current scene
268
+ * `"^scene:step"` → jump to another scene
269
+ * `{ step }` → absolute step
270
+ * `{ scene: { title, step } }` → absolute scene
309
271
 
310
- `undefined` or `"next"` → move to the next step
311
- • `"stop" | "exit" | "!"` → terminate the scene
312
- • `"<" | "prev"` → move to the previous step
313
- • `">" | "next"` → move to the next step
314
- • `"^step"` → jump to a step within the current scene
315
- • `"^scene:step"` → jump to another scene
316
- • `{ step: "..." }` → jump to a specific step
317
- • `{ scene: { title, step } }` → jump to another scene
318
-
319
- ---
272
+ ### Termination
320
273
 
321
- ### Relative Transitions
322
-
323
- • `undefined` / `"next"` / `">"` → next step
324
- • `"prev"` / `"<"` → previous step
325
-
326
- ---
327
-
328
- ### Absolute Transitions
329
-
330
- • `"^step"` → step within the current scene
331
- • `"^scene:step"` → jump to another scene
332
-
333
- ---
274
+ Scene termination sets:
334
275
 
335
- ### Object-Based Transitions
336
-
337
- ```js
338
- return { step: "confirm" };
339
276
  ```
340
-
341
- ```js
342
- return {
343
- scene: {
344
- title: "auth",
345
- step: "phone",
346
- },
347
- };
277
+ ctx.session.scene = null;
348
278
  ```
349
279
 
350
280
  ---
351
281
 
352
282
  ## Options
353
283
 
354
- Options are passed as the second argument to `new Scenes()`.
355
-
356
284
  ### callbacks:enter:buttons:cancel
357
285
 
358
- Adds a cancel button to all messages sent inside `callbacks.enter`.
286
+ Injects a cancel button into all `enter` replies.
359
287
 
360
- ```js
288
+ ```
361
289
  {
362
290
  "callbacks:enter:buttons:cancel": {
363
291
  enabled: true,
364
-
365
292
  component: {
366
293
  text: "Cancel",
367
294
  callback_data: "scene:cancel",
@@ -370,29 +297,23 @@ Adds a cancel button to all messages sent inside `callbacks.enter`.
370
297
  }
371
298
  ```
372
299
 
373
- Behavior:
300
+ Notes:
374
301
 
375
- Works only inside `callbacks.enter`
376
- The button is appended automatically
377
- • Scene cancellation logic must be implemented by the user
302
+ * Only affects `enter`
303
+ * Cancellation logic is user-defined
378
304
 
379
305
  ---
380
306
 
381
- ## Scenes Class
307
+ ## API
382
308
 
383
309
  ### new Scenes(scenes, options)
384
310
 
385
- Creates a scene manager instance.
386
-
387
- Parameters:
388
-
389
- • `scenes` — an array of grouped scene steps
390
- • `options` — configuration object
311
+ Creates a scene manager.
391
312
 
392
313
  Exports:
393
314
 
394
- `scenes.middleware` — grammY middleware
395
- `scenes.enter(ctx, scene)` — method to enter a scene
315
+ * `scenes.middleware`
316
+ * `scenes.enter(ctx, scene)`
396
317
 
397
318
  ---
398
319
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monixlite/grammy-scenes",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Scene middleware for grammY with step-based navigation",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",