@mtcute/dispatcher 0.16.7 → 0.16.13

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 (237) hide show
  1. package/{cjs/callback-data-builder.d.ts → callback-data-builder.d.ts} +2 -2
  2. package/callback-data-builder.test.d.ts +1 -0
  3. package/{esm/context → context}/base.d.ts +2 -2
  4. package/{esm/context → context}/business-message.d.ts +5 -6
  5. package/{esm/context → context}/callback-query.d.ts +6 -7
  6. package/{cjs/context → context}/chat-join-request.d.ts +3 -3
  7. package/{esm/context → context}/chosen-inline-result.d.ts +3 -3
  8. package/{esm/context → context}/inline-query.d.ts +4 -5
  9. package/{cjs/context → context}/message.d.ts +11 -6
  10. package/{cjs/context → context}/parse.d.ts +3 -3
  11. package/{esm/context → context}/pre-checkout-query.d.ts +3 -3
  12. package/{esm/context → context}/scene-transition.d.ts +1 -1
  13. package/{cjs/dispatcher.d.ts → dispatcher.d.ts} +9 -10
  14. package/{cjs/filters → filters}/bots.d.ts +4 -4
  15. package/filters/bots.test.d.ts +1 -0
  16. package/{cjs/filters → filters}/chat.d.ts +3 -3
  17. package/{esm/filters → filters}/group.d.ts +4 -4
  18. package/{cjs/filters → filters}/logic.d.ts +1 -1
  19. package/filters/logic.test.d.ts +1 -0
  20. package/{esm/filters → filters}/message.d.ts +9 -5
  21. package/{cjs/filters → filters}/state.d.ts +2 -2
  22. package/{esm/filters → filters}/text.d.ts +3 -3
  23. package/{cjs/filters → filters}/types.d.ts +2 -2
  24. package/{cjs/filters → filters}/updates.d.ts +2 -2
  25. package/{cjs/filters → filters}/user.d.ts +3 -4
  26. package/{cjs/handler.d.ts → handler.d.ts} +5 -5
  27. package/index.cjs +2534 -0
  28. package/index.d.ts +8 -1
  29. package/index.js +2529 -1
  30. package/package.json +28 -24
  31. package/{cjs/state → state}/key.d.ts +3 -3
  32. package/state/provider.d.ts +5 -0
  33. package/{cjs/state → state}/providers/memory.d.ts +3 -4
  34. package/{esm/state → state}/providers/sqlite.d.ts +3 -3
  35. package/{cjs/state → state}/repository.d.ts +1 -1
  36. package/{esm/state → state}/service.d.ts +2 -2
  37. package/{cjs/state → state}/update-state.d.ts +2 -2
  38. package/{esm/wizard.d.ts → wizard.d.ts} +5 -6
  39. package/cjs/callback-data-builder.js +0 -141
  40. package/cjs/callback-data-builder.js.map +0 -1
  41. package/cjs/context/base.d.ts +0 -9
  42. package/cjs/context/base.js +0 -3
  43. package/cjs/context/base.js.map +0 -1
  44. package/cjs/context/business-message.d.ts +0 -61
  45. package/cjs/context/business-message.js +0 -146
  46. package/cjs/context/business-message.js.map +0 -1
  47. package/cjs/context/callback-query.d.ts +0 -63
  48. package/cjs/context/callback-query.js +0 -109
  49. package/cjs/context/callback-query.js.map +0 -1
  50. package/cjs/context/chat-join-request.js +0 -35
  51. package/cjs/context/chat-join-request.js.map +0 -1
  52. package/cjs/context/chosen-inline-result.d.ts +0 -22
  53. package/cjs/context/chosen-inline-result.js +0 -36
  54. package/cjs/context/chosen-inline-result.js.map +0 -1
  55. package/cjs/context/index.js +0 -25
  56. package/cjs/context/index.js.map +0 -1
  57. package/cjs/context/inline-query.d.ts +0 -16
  58. package/cjs/context/inline-query.js +0 -23
  59. package/cjs/context/inline-query.js.map +0 -1
  60. package/cjs/context/message.js +0 -171
  61. package/cjs/context/message.js.map +0 -1
  62. package/cjs/context/parse.js +0 -42
  63. package/cjs/context/parse.js.map +0 -1
  64. package/cjs/context/pre-checkout-query.d.ts +0 -17
  65. package/cjs/context/pre-checkout-query.js +0 -27
  66. package/cjs/context/pre-checkout-query.js.map +0 -1
  67. package/cjs/context/scene-transition.d.ts +0 -24
  68. package/cjs/context/scene-transition.js +0 -52
  69. package/cjs/context/scene-transition.js.map +0 -1
  70. package/cjs/dispatcher.js +0 -908
  71. package/cjs/dispatcher.js.map +0 -1
  72. package/cjs/filters/bots.js +0 -135
  73. package/cjs/filters/bots.js.map +0 -1
  74. package/cjs/filters/bundle.js +0 -27
  75. package/cjs/filters/bundle.js.map +0 -1
  76. package/cjs/filters/chat.js +0 -56
  77. package/cjs/filters/chat.js.map +0 -1
  78. package/cjs/filters/group.d.ts +0 -26
  79. package/cjs/filters/group.js +0 -69
  80. package/cjs/filters/group.js.map +0 -1
  81. package/cjs/filters/index.js +0 -29
  82. package/cjs/filters/index.js.map +0 -1
  83. package/cjs/filters/logic.js +0 -112
  84. package/cjs/filters/logic.js.map +0 -1
  85. package/cjs/filters/message.d.ts +0 -215
  86. package/cjs/filters/message.js +0 -191
  87. package/cjs/filters/message.js.map +0 -1
  88. package/cjs/filters/state.js +0 -33
  89. package/cjs/filters/state.js.map +0 -1
  90. package/cjs/filters/text.d.ts +0 -64
  91. package/cjs/filters/text.js +0 -136
  92. package/cjs/filters/text.js.map +0 -1
  93. package/cjs/filters/types.js +0 -3
  94. package/cjs/filters/types.js.map +0 -1
  95. package/cjs/filters/updates.js +0 -40
  96. package/cjs/filters/updates.js.map +0 -1
  97. package/cjs/filters/user.js +0 -77
  98. package/cjs/filters/user.js.map +0 -1
  99. package/cjs/handler.js +0 -4
  100. package/cjs/handler.js.map +0 -1
  101. package/cjs/index.js +0 -31
  102. package/cjs/index.js.map +0 -1
  103. package/cjs/package.json +0 -3
  104. package/cjs/propagation.js +0 -27
  105. package/cjs/propagation.js.map +0 -1
  106. package/cjs/state/index.js +0 -22
  107. package/cjs/state/index.js.map +0 -1
  108. package/cjs/state/key.js +0 -43
  109. package/cjs/state/key.js.map +0 -1
  110. package/cjs/state/provider.d.ts +0 -5
  111. package/cjs/state/provider.js +0 -3
  112. package/cjs/state/provider.js.map +0 -1
  113. package/cjs/state/providers/index.js +0 -19
  114. package/cjs/state/providers/index.js.map +0 -1
  115. package/cjs/state/providers/memory.js +0 -81
  116. package/cjs/state/providers/memory.js.map +0 -1
  117. package/cjs/state/providers/sqlite.d.ts +0 -28
  118. package/cjs/state/providers/sqlite.js +0 -100
  119. package/cjs/state/providers/sqlite.js.map +0 -1
  120. package/cjs/state/repository.js +0 -3
  121. package/cjs/state/repository.js.map +0 -1
  122. package/cjs/state/service.d.ts +0 -20
  123. package/cjs/state/service.js +0 -70
  124. package/cjs/state/service.js.map +0 -1
  125. package/cjs/state/update-state.js +0 -219
  126. package/cjs/state/update-state.js.map +0 -1
  127. package/cjs/wizard.d.ts +0 -65
  128. package/cjs/wizard.js +0 -105
  129. package/cjs/wizard.js.map +0 -1
  130. package/esm/callback-data-builder.d.ts +0 -49
  131. package/esm/callback-data-builder.js +0 -137
  132. package/esm/callback-data-builder.js.map +0 -1
  133. package/esm/context/base.js +0 -2
  134. package/esm/context/base.js.map +0 -1
  135. package/esm/context/business-message.js +0 -142
  136. package/esm/context/business-message.js.map +0 -1
  137. package/esm/context/callback-query.js +0 -103
  138. package/esm/context/callback-query.js.map +0 -1
  139. package/esm/context/chat-join-request.d.ts +0 -17
  140. package/esm/context/chat-join-request.js +0 -31
  141. package/esm/context/chat-join-request.js.map +0 -1
  142. package/esm/context/chosen-inline-result.js +0 -32
  143. package/esm/context/chosen-inline-result.js.map +0 -1
  144. package/esm/context/index.d.ts +0 -9
  145. package/esm/context/index.js +0 -9
  146. package/esm/context/index.js.map +0 -1
  147. package/esm/context/inline-query.js +0 -19
  148. package/esm/context/inline-query.js.map +0 -1
  149. package/esm/context/message.d.ts +0 -77
  150. package/esm/context/message.js +0 -167
  151. package/esm/context/message.js.map +0 -1
  152. package/esm/context/parse.d.ts +0 -13
  153. package/esm/context/parse.js +0 -39
  154. package/esm/context/parse.js.map +0 -1
  155. package/esm/context/pre-checkout-query.js +0 -23
  156. package/esm/context/pre-checkout-query.js.map +0 -1
  157. package/esm/context/scene-transition.js +0 -48
  158. package/esm/context/scene-transition.js.map +0 -1
  159. package/esm/dispatcher.d.ts +0 -881
  160. package/esm/dispatcher.js +0 -904
  161. package/esm/dispatcher.js.map +0 -1
  162. package/esm/filters/bots.d.ts +0 -64
  163. package/esm/filters/bots.js +0 -131
  164. package/esm/filters/bots.js.map +0 -1
  165. package/esm/filters/bundle.d.ts +0 -10
  166. package/esm/filters/bundle.js +0 -11
  167. package/esm/filters/bundle.js.map +0 -1
  168. package/esm/filters/chat.d.ts +0 -27
  169. package/esm/filters/chat.js +0 -51
  170. package/esm/filters/chat.js.map +0 -1
  171. package/esm/filters/group.js +0 -65
  172. package/esm/filters/group.js.map +0 -1
  173. package/esm/filters/index.d.ts +0 -4
  174. package/esm/filters/index.js +0 -3
  175. package/esm/filters/index.js.map +0 -1
  176. package/esm/filters/logic.d.ts +0 -29
  177. package/esm/filters/logic.js +0 -105
  178. package/esm/filters/logic.js.map +0 -1
  179. package/esm/filters/message.js +0 -168
  180. package/esm/filters/message.js.map +0 -1
  181. package/esm/filters/state.d.ts +0 -15
  182. package/esm/filters/state.js +0 -28
  183. package/esm/filters/state.js.map +0 -1
  184. package/esm/filters/text.js +0 -129
  185. package/esm/filters/text.js.map +0 -1
  186. package/esm/filters/types.d.ts +0 -91
  187. package/esm/filters/types.js +0 -2
  188. package/esm/filters/types.js.map +0 -1
  189. package/esm/filters/updates.d.ts +0 -39
  190. package/esm/filters/updates.js +0 -34
  191. package/esm/filters/updates.js.map +0 -1
  192. package/esm/filters/user.d.ts +0 -25
  193. package/esm/filters/user.js +0 -71
  194. package/esm/filters/user.js.map +0 -1
  195. package/esm/handler.d.ts +0 -41
  196. package/esm/handler.js +0 -3
  197. package/esm/handler.js.map +0 -1
  198. package/esm/index.d.ts +0 -8
  199. package/esm/index.js +0 -9
  200. package/esm/index.js.map +0 -1
  201. package/esm/propagation.d.ts +0 -22
  202. package/esm/propagation.js +0 -24
  203. package/esm/propagation.js.map +0 -1
  204. package/esm/state/index.d.ts +0 -5
  205. package/esm/state/index.js +0 -6
  206. package/esm/state/index.js.map +0 -1
  207. package/esm/state/key.d.ts +0 -24
  208. package/esm/state/key.js +0 -39
  209. package/esm/state/key.js.map +0 -1
  210. package/esm/state/provider.d.ts +0 -5
  211. package/esm/state/provider.js +0 -2
  212. package/esm/state/provider.js.map +0 -1
  213. package/esm/state/providers/index.d.ts +0 -2
  214. package/esm/state/providers/index.js +0 -3
  215. package/esm/state/providers/index.js.map +0 -1
  216. package/esm/state/providers/memory.d.ts +0 -30
  217. package/esm/state/providers/memory.js +0 -77
  218. package/esm/state/providers/memory.js.map +0 -1
  219. package/esm/state/providers/sqlite.js +0 -96
  220. package/esm/state/providers/sqlite.js.map +0 -1
  221. package/esm/state/repository.d.ts +0 -62
  222. package/esm/state/repository.js +0 -2
  223. package/esm/state/repository.js.map +0 -1
  224. package/esm/state/service.js +0 -66
  225. package/esm/state/service.js.map +0 -1
  226. package/esm/state/update-state.d.ts +0 -151
  227. package/esm/state/update-state.js +0 -214
  228. package/esm/state/update-state.js.map +0 -1
  229. package/esm/wizard.js +0 -101
  230. package/esm/wizard.js.map +0 -1
  231. /package/{cjs/context → context}/index.d.ts +0 -0
  232. /package/{cjs/filters → filters}/bundle.d.ts +0 -0
  233. /package/{cjs/filters → filters}/index.d.ts +0 -0
  234. /package/{cjs/index.d.ts → index.d.cts} +0 -0
  235. /package/{cjs/propagation.d.ts → propagation.d.ts} +0 -0
  236. /package/{cjs/state → state}/index.d.ts +0 -0
  237. /package/{cjs/state → state}/providers/index.d.ts +0 -0
@@ -1,214 +0,0 @@
1
- import { MtArgumentError, MtcuteError } from '@mtcute/core';
2
- import { sleep } from '@mtcute/core/utils.js';
3
- /**
4
- * Error thrown by `.rateLimit()`
5
- */
6
- export class RateLimitError extends MtcuteError {
7
- reset;
8
- constructor(reset) {
9
- super('You are being rate limited.');
10
- this.reset = reset;
11
- }
12
- }
13
- /**
14
- * State of the current update.
15
- *
16
- * @template State Type that represents the state
17
- * @template SceneName Possible scene names
18
- */
19
- export class UpdateState {
20
- _key;
21
- _localKey;
22
- _storage;
23
- _scene;
24
- _scoped;
25
- _cached;
26
- _localStorage;
27
- _localKeyBase;
28
- constructor(storage, key, scene, scoped, customStorage, customKey) {
29
- this._storage = storage;
30
- this._key = key;
31
- this._scene = scene;
32
- this._scoped = scoped;
33
- this._localStorage = customStorage ?? storage;
34
- this._localKeyBase = customKey ?? key;
35
- this._updateLocalKey();
36
- }
37
- /** Name of the current scene */
38
- get scene() {
39
- return this._scene;
40
- }
41
- _updateLocalKey() {
42
- if (!this._scoped) {
43
- this._localKey = this._localKeyBase;
44
- }
45
- else {
46
- this._localKey = this._scene ? `${this._scene}_${this._localKeyBase}` : this._localKeyBase;
47
- }
48
- }
49
- async get(fallback, force) {
50
- if (typeof fallback === 'boolean') {
51
- force = fallback;
52
- fallback = undefined;
53
- }
54
- if (!force && this._cached !== undefined) {
55
- if (!this._cached && fallback) {
56
- return typeof fallback === 'function' ? fallback() : fallback;
57
- }
58
- return this._cached;
59
- }
60
- let res = (await this._localStorage.getState(this._localKey));
61
- if (!res && fallback) {
62
- res = typeof fallback === 'function' ? fallback() : fallback;
63
- }
64
- this._cached = res;
65
- return res;
66
- }
67
- /**
68
- * Set new state to the storage
69
- *
70
- * @param state New state
71
- * @param ttl TTL for the new state (in seconds)
72
- */
73
- async set(state, ttl) {
74
- this._cached = state;
75
- await this._localStorage.setState(this._localKey, state, ttl);
76
- }
77
- /**
78
- * Merge the given object to the current state.
79
- *
80
- * > **Note**: If the storage currently has no state,
81
- * > then `fallback` must be provided.
82
- *
83
- * Basically a shorthand to calling `.get()`,
84
- * modifying and then calling `.set()`
85
- *
86
- * @param state State to be merged
87
- * @param fallback Default state
88
- * @param ttl TTL for the new state (in seconds)
89
- * @param forceLoad Whether to force load the old state from storage
90
- */
91
- async merge(state, params = {}) {
92
- const { fallback, ttl, forceLoad } = params;
93
- const old = await this.get(forceLoad);
94
- if (!old) {
95
- if (!fallback) {
96
- throw new MtArgumentError('Cannot use merge on empty state without fallback.');
97
- }
98
- const fallback_ = typeof fallback === 'function' ? fallback() : fallback;
99
- await this.set({ ...fallback_, ...state }, ttl);
100
- }
101
- else {
102
- await this.set({ ...old, ...state }, ttl);
103
- }
104
- // _cached is set by .set()
105
- return this._cached;
106
- }
107
- /**
108
- * Delete the state from the storage
109
- */
110
- async delete() {
111
- this._cached = null;
112
- await this._localStorage.deleteState(this._localKey);
113
- }
114
- /**
115
- * Enter some scene
116
- */
117
- async enter(scene, params) {
118
- const { with: with_, ttl, reset = true } = params ?? {};
119
- if (reset && this._scoped)
120
- await this.delete();
121
- if (!scene['_scene']) {
122
- throw new MtArgumentError('Cannot enter a non-scene Dispatcher');
123
- }
124
- if (!scene['_parent']) {
125
- throw new MtArgumentError('This scene has not been registered');
126
- }
127
- this._scene = scene['_scene'];
128
- this._scoped = scene['_sceneScoped'];
129
- this._updateLocalKey();
130
- await this._storage.setCurrentScene(this._key, this._scene, ttl);
131
- if (with_) {
132
- if (scene['_customStateKeyDelegate']) {
133
- throw new MtArgumentError('Cannot use `with` parameter when the scene uses a custom state key delegate');
134
- }
135
- await scene.getState(this._key).set(with_, ttl);
136
- }
137
- }
138
- /**
139
- * Exit from current scene to the root
140
- *
141
- * @param reset
142
- * Whether to reset scene state (only applicable in case this is a scoped scene)
143
- */
144
- async exit(reset = true) {
145
- if (reset && this._scoped)
146
- await this.delete();
147
- this._scene = null;
148
- this._updateLocalKey();
149
- await this._storage.deleteCurrentScene(this._key);
150
- }
151
- /**
152
- * Rate limit some handler.
153
- *
154
- * When the rate limit exceeds, {@link RateLimitError} is thrown.
155
- *
156
- * This is a simple rate-limiting solution that uses
157
- * the same key as the state. If you need something more
158
- * sophisticated and/or customizable, you'll have to implement
159
- * your own rate-limiter.
160
- *
161
- * > **Note**: `key` is used to prefix the local key
162
- * > derived using the given key delegate.
163
- *
164
- * @param key Key of the rate limit
165
- * @param limit Maximum number of requests in `window`
166
- * @param window Window size in seconds
167
- * @returns Tuple containing the number of remaining and
168
- * unix time in ms when the user can try again
169
- */
170
- async rateLimit(key, limit, window) {
171
- const [remaining, reset] = await this._localStorage.getRateLimit(`${key}:${this._localKey}`, limit, window);
172
- if (!remaining) {
173
- throw new RateLimitError(reset);
174
- }
175
- return [remaining - 1, reset];
176
- }
177
- /**
178
- * Throttle some handler.
179
- *
180
- * When the rate limit exceeds, this function waits for it to reset.
181
- *
182
- * This is a simple wrapper over {@link rateLimit}, and follows the same logic.
183
- *
184
- * > **Note**: `key` is used to prefix the local key
185
- * > derived using the given key delegate.
186
- *
187
- * @param key Key of the rate limit
188
- * @param limit Maximum number of requests in `window`
189
- * @param window Window size in seconds
190
- * @returns Tuple containing the number of remaining and
191
- * unix time in ms when the user can try again
192
- */
193
- async throttle(key, limit, window) {
194
- try {
195
- return await this.rateLimit(key, limit, window);
196
- }
197
- catch (e) {
198
- if (e instanceof RateLimitError) {
199
- await sleep(e.reset - Date.now());
200
- return this.throttle(key, limit, window);
201
- }
202
- throw e;
203
- }
204
- }
205
- /**
206
- * Reset the rate limit
207
- *
208
- * @param key Key of the rate limit
209
- */
210
- async resetRateLimit(key) {
211
- await this._localStorage.resetRateLimit(`${key}:${this._localKey}`);
212
- }
213
- }
214
- //# sourceMappingURL=update-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update-state.js","sourceRoot":"","sources":["../../../src/state/update-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { MtArgumentError, MtcuteError } from '@mtcute/core'\nimport { sleep } from '@mtcute/core/utils.js'\n\nimport type { Dispatcher } from '../dispatcher.js'\n\nimport type { StateService } from './service.js'\n\n/**\n * Error thrown by `.rateLimit()`\n */\nexport class RateLimitError extends MtcuteError {\n constructor(readonly reset: number) {\n super('You are being rate limited.')\n }\n}\n\n/**\n * State of the current update.\n *\n * @template State Type that represents the state\n * @template SceneName Possible scene names\n */\nexport class UpdateState<State extends object> {\n private _key: string\n private _localKey!: string\n\n private _storage: StateService\n\n private _scene: string | null\n private _scoped?: boolean\n private _cached?: State | null\n\n private _localStorage: StateService\n private _localKeyBase: string\n\n constructor(\n storage: StateService,\n key: string,\n scene: string | null,\n scoped?: boolean,\n customStorage?: StateService,\n customKey?: string,\n ) {\n this._storage = storage\n this._key = key\n this._scene = scene\n this._scoped = scoped\n\n this._localStorage = customStorage ?? storage\n this._localKeyBase = customKey ?? key\n\n this._updateLocalKey()\n }\n\n /** Name of the current scene */\n get scene(): string | null {\n return this._scene\n }\n\n private _updateLocalKey(): void {\n if (!this._scoped) {\n this._localKey = this._localKeyBase\n } else {\n this._localKey = this._scene ? `${this._scene}_${this._localKeyBase}` : this._localKeyBase\n }\n }\n\n /**\n * Retrieve the state from the storage, falling back to default\n * if not found\n *\n * @param fallback Default state value\n * @param force Whether to ignore cached state (def. `false`)\n */\n async get(fallback: State | (() => State), force?: boolean): Promise<State>\n\n /**\n * Retrieve the state from the storage, falling back to default\n * if not found\n *\n * @param fallback Default state value\n * @param force Whether to ignore cached state (def. `false`)\n */\n async get(fallback?: State | (() => State), force?: boolean): Promise<State | null>\n /**\n * Retrieve the state from the storage\n *\n * @param force Whether to ignore cached state (def. `false`)\n */\n async get(force?: boolean): Promise<State | null>\n async get(fallback?: State | (() => State) | boolean, force?: boolean): Promise<State | null> {\n if (typeof fallback === 'boolean') {\n force = fallback\n fallback = undefined\n }\n\n if (!force && this._cached !== undefined) {\n if (!this._cached && fallback) {\n return typeof fallback === 'function' ? fallback() : fallback\n }\n\n return this._cached\n }\n\n let res = (await this._localStorage.getState(this._localKey)) as State | null\n\n if (!res && fallback) {\n res = typeof fallback === 'function' ? fallback() : fallback\n }\n this._cached = res\n\n return res\n }\n\n /**\n * Set new state to the storage\n *\n * @param state New state\n * @param ttl TTL for the new state (in seconds)\n */\n async set(state: State, ttl?: number): Promise<void> {\n this._cached = state\n await this._localStorage.setState(this._localKey, state, ttl)\n }\n\n /**\n * Merge the given object to the current state.\n *\n * > **Note**: If the storage currently has no state,\n * > then `fallback` must be provided.\n *\n * Basically a shorthand to calling `.get()`,\n * modifying and then calling `.set()`\n *\n * @param state State to be merged\n * @param fallback Default state\n * @param ttl TTL for the new state (in seconds)\n * @param forceLoad Whether to force load the old state from storage\n */\n async merge(\n state: Partial<State>,\n params: {\n fallback?: State | (() => State)\n ttl?: number\n forceLoad?: boolean\n } = {},\n ): Promise<State> {\n const { fallback, ttl, forceLoad } = params\n\n const old = await this.get(forceLoad)\n\n if (!old) {\n if (!fallback) {\n throw new MtArgumentError('Cannot use merge on empty state without fallback.')\n }\n\n const fallback_ = typeof fallback === 'function' ? fallback() : fallback\n\n await this.set({ ...fallback_, ...state }, ttl)\n } else {\n await this.set({ ...old, ...state }, ttl)\n }\n\n // _cached is set by .set()\n\n return this._cached!\n }\n\n /**\n * Delete the state from the storage\n */\n async delete(): Promise<void> {\n this._cached = null\n await this._localStorage.deleteState(this._localKey)\n }\n\n /**\n * Enter some scene\n */\n async enter<SceneState extends object, Scene extends Dispatcher<SceneState>>(\n scene: Scene,\n params?: {\n /**\n * Initial state for the scene\n *\n * Note that this will only work if the scene uses the same key delegate as this state.\n */\n with?: SceneState\n\n /** TTL for the scene (in seconds) */\n ttl?: number\n\n /**\n * If currently in a scoped scene, whether to reset the state\n *\n * @default true\n */\n reset?: boolean\n },\n ): Promise<void> {\n const { with: with_, ttl, reset = true } = params ?? {}\n\n if (reset && this._scoped) await this.delete()\n\n if (!scene['_scene']) {\n throw new MtArgumentError('Cannot enter a non-scene Dispatcher')\n }\n\n if (!scene['_parent']) {\n throw new MtArgumentError('This scene has not been registered')\n }\n\n this._scene = scene['_scene']\n this._scoped = scene['_sceneScoped']\n this._updateLocalKey()\n\n await this._storage.setCurrentScene(this._key, this._scene, ttl)\n\n if (with_) {\n if (scene['_customStateKeyDelegate']) {\n throw new MtArgumentError('Cannot use `with` parameter when the scene uses a custom state key delegate')\n }\n\n await scene.getState(this._key).set(with_, ttl)\n }\n }\n\n /**\n * Exit from current scene to the root\n *\n * @param reset\n * Whether to reset scene state (only applicable in case this is a scoped scene)\n */\n async exit(reset = true): Promise<void> {\n if (reset && this._scoped) await this.delete()\n this._scene = null\n this._updateLocalKey()\n await this._storage.deleteCurrentScene(this._key)\n }\n\n /**\n * Rate limit some handler.\n *\n * When the rate limit exceeds, {@link RateLimitError} is thrown.\n *\n * This is a simple rate-limiting solution that uses\n * the same key as the state. If you need something more\n * sophisticated and/or customizable, you'll have to implement\n * your own rate-limiter.\n *\n * > **Note**: `key` is used to prefix the local key\n * > derived using the given key delegate.\n *\n * @param key Key of the rate limit\n * @param limit Maximum number of requests in `window`\n * @param window Window size in seconds\n * @returns Tuple containing the number of remaining and\n * unix time in ms when the user can try again\n */\n async rateLimit(key: string, limit: number, window: number): Promise<[number, number]> {\n const [remaining, reset] = await this._localStorage.getRateLimit(`${key}:${this._localKey}`, limit, window)\n\n if (!remaining) {\n throw new RateLimitError(reset)\n }\n\n return [remaining - 1, reset]\n }\n\n /**\n * Throttle some handler.\n *\n * When the rate limit exceeds, this function waits for it to reset.\n *\n * This is a simple wrapper over {@link rateLimit}, and follows the same logic.\n *\n * > **Note**: `key` is used to prefix the local key\n * > derived using the given key delegate.\n *\n * @param key Key of the rate limit\n * @param limit Maximum number of requests in `window`\n * @param window Window size in seconds\n * @returns Tuple containing the number of remaining and\n * unix time in ms when the user can try again\n */\n async throttle(key: string, limit: number, window: number): Promise<[number, number]> {\n try {\n return await this.rateLimit(key, limit, window)\n } catch (e: unknown) {\n if (e instanceof RateLimitError) {\n await sleep(e.reset - Date.now())\n\n return this.throttle(key, limit, window)\n }\n\n throw e\n }\n }\n\n /**\n * Reset the rate limit\n *\n * @param key Key of the rate limit\n */\n async resetRateLimit(key: string): Promise<void> {\n await this._localStorage.resetRateLimit(`${key}:${this._localKey}`)\n }\n}\n"]}
package/esm/wizard.js DELETED
@@ -1,101 +0,0 @@
1
- import { Dispatcher } from './dispatcher.js';
2
- import { filters } from './filters/index.js';
3
- /**
4
- * Action for the wizard scene.
5
- *
6
- * `Next`: Continue to the next registered step
7
- * (or exit, if this is the last step)
8
- *
9
- * `Stay`: Stay on the same step
10
- *
11
- * `Exit`: Exit from the wizard scene
12
- *
13
- * You can also return a `number` to jump to that step
14
- */
15
- export var WizardSceneAction;
16
- (function (WizardSceneAction) {
17
- WizardSceneAction["Next"] = "next";
18
- WizardSceneAction["Stay"] = "stay";
19
- WizardSceneAction["Exit"] = "exit";
20
- })(WizardSceneAction || (WizardSceneAction = {}));
21
- /**
22
- * Wizard is a special type of Dispatcher
23
- * that can be used to simplify implementing
24
- * step-by-step scenes.
25
- */
26
- export class WizardScene extends Dispatcher {
27
- _steps = 0;
28
- _defaultState = {};
29
- constructor(name, params) {
30
- super(undefined, { sceneName: name, ...params });
31
- }
32
- setDefaultState(defaultState) {
33
- this._defaultState = defaultState;
34
- }
35
- /**
36
- * Get the total number of registered steps
37
- */
38
- get totalSteps() {
39
- return this._steps;
40
- }
41
- /**
42
- * Go to the Nth step
43
- */
44
- async goToStep(state, step) {
45
- if (step >= this._steps) {
46
- await state.exit();
47
- }
48
- else {
49
- await state.merge({ $step: step }, this._defaultState);
50
- }
51
- }
52
- /**
53
- * Skip N steps
54
- */
55
- async skip(state, count = 1) {
56
- const { $step } = (await state.get()) || {};
57
- if ($step === undefined)
58
- throw new Error('Wizard state is not initialized');
59
- return this.goToStep(state, $step + count);
60
- }
61
- /**
62
- * Filter that will only pass if the current step is `step`
63
- */
64
- // eslint-disable-next-line ts/no-empty-object-type
65
- static onNthStep(step) {
66
- const filter = filters.state(it => it.$step === step);
67
- if (step === 0)
68
- return filters.or(filters.stateEmpty, filter);
69
- return filter;
70
- }
71
- /**
72
- * Filter that will only pass if the current step is the one after last one added
73
- */
74
- // eslint-disable-next-line ts/no-empty-object-type
75
- onCurrentStep() {
76
- return WizardScene.onNthStep(this._steps);
77
- }
78
- /**
79
- * Add a step to the wizard
80
- */
81
- addStep(handler) {
82
- const step = this._steps++;
83
- this.onNewMessage(WizardScene.onNthStep(step), async (msg, state) => {
84
- const result = await handler(msg, state);
85
- if (typeof result === 'number') {
86
- await this.goToStep(state, result);
87
- return;
88
- }
89
- switch (result) {
90
- case 'next': {
91
- await this.goToStep(state, step + 1);
92
- break;
93
- }
94
- case 'exit':
95
- await state.exit();
96
- break;
97
- }
98
- });
99
- }
100
- }
101
- //# sourceMappingURL=wizard.js.map
package/esm/wizard.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/wizard.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MaybePromise } from '@mtcute/core'\n\nimport type { MessageContext } from './context/message.js'\nimport type { DispatcherParams } from './dispatcher.js'\nimport { Dispatcher } from './dispatcher.js'\nimport type { UpdateFilter } from './filters/index.js'\nimport { filters } from './filters/index.js'\nimport type { UpdateState } from './state/update-state.js'\n\n/**\n * Action for the wizard scene.\n *\n * `Next`: Continue to the next registered step\n * (or exit, if this is the last step)\n *\n * `Stay`: Stay on the same step\n *\n * `Exit`: Exit from the wizard scene\n *\n * You can also return a `number` to jump to that step\n */\nexport enum WizardSceneAction {\n Next = 'next',\n Stay = 'stay',\n Exit = 'exit',\n}\n\ninterface WizardInternalState {\n $step?: number\n}\n\n/**\n * Wizard is a special type of Dispatcher\n * that can be used to simplify implementing\n * step-by-step scenes.\n */\nexport class WizardScene<State extends object> extends Dispatcher<State & WizardInternalState> {\n private _steps = 0\n\n private _defaultState: State & WizardInternalState = {} as State & WizardInternalState\n\n constructor(name: string, params?: Omit<DispatcherParams, 'sceneName'>) {\n super(undefined, { sceneName: name, ...params })\n }\n\n // remove inherited statics from Dispatcher\n declare static for: never\n declare static child: never\n declare static scene: never\n\n setDefaultState(defaultState: State): void {\n this._defaultState = defaultState as State & WizardInternalState\n }\n\n /**\n * Get the total number of registered steps\n */\n get totalSteps(): number {\n return this._steps\n }\n\n /**\n * Go to the Nth step\n */\n async goToStep(state: UpdateState<WizardInternalState>, step: number): Promise<void> {\n if (step >= this._steps) {\n await state.exit()\n } else {\n await state.merge({ $step: step }, this._defaultState)\n }\n }\n\n /**\n * Skip N steps\n */\n async skip(state: UpdateState<WizardInternalState>, count = 1): Promise<void> {\n const { $step } = (await state.get()) || {}\n if ($step === undefined) throw new Error('Wizard state is not initialized')\n\n return this.goToStep(state, $step + count)\n }\n\n /**\n * Filter that will only pass if the current step is `step`\n */\n // eslint-disable-next-line ts/no-empty-object-type\n static onNthStep(step: number): UpdateFilter<any, {}, WizardInternalState> {\n const filter = filters.state<WizardInternalState>(it => it.$step === step)\n\n if (step === 0) return filters.or(filters.stateEmpty, filter)\n\n return filter\n }\n\n /**\n * Filter that will only pass if the current step is the one after last one added\n */\n // eslint-disable-next-line ts/no-empty-object-type\n onCurrentStep(): UpdateFilter<any, {}, WizardInternalState> {\n return WizardScene.onNthStep(this._steps)\n }\n\n /**\n * Add a step to the wizard\n */\n addStep(\n handler: (\n msg: MessageContext,\n state: UpdateState<State & WizardInternalState>,\n ) => MaybePromise<WizardSceneAction | number>,\n ): void {\n const step = this._steps++\n\n this.onNewMessage(WizardScene.onNthStep(step), async (msg, state) => {\n const result = await handler(msg, state)\n\n if (typeof result === 'number') {\n await this.goToStep(state, result)\n\n return\n }\n\n switch (result) {\n case 'next': {\n await this.goToStep(state, step + 1)\n break\n }\n case 'exit':\n await state.exit()\n break\n }\n })\n }\n}\n"]}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes