stitchkit 0.100.2 → 0.100.3

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 (225) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +2 -1
  3. package/dist/entrypoints/agent-runtime/browser.js +119 -119
  4. package/dist/entrypoints/agent-runtime/coding-tools.js +15 -20
  5. package/dist/entrypoints/agent-runtime/harness.js +55 -63
  6. package/dist/entrypoints/agent-runtime/openrouter.js +6 -6
  7. package/dist/entrypoints/agent-runtime/sandbox.js +20 -25
  8. package/dist/entrypoints/agent-runtime/sqlite/bun.js +11 -13
  9. package/dist/entrypoints/agent-runtime/sqlite/node.js +11 -13
  10. package/dist/entrypoints/agent-runtime/testing.js +32 -34
  11. package/dist/entrypoints/agent-runtime.js +395 -402
  12. package/dist/entrypoints/application/diagnostic-journal.js +26 -27
  13. package/dist/entrypoints/application/directory-inbox.js +16 -17
  14. package/dist/entrypoints/application/grammy.js +13 -13
  15. package/dist/entrypoints/application/opentelemetry.js +13 -13
  16. package/dist/entrypoints/application/schemas.js +24 -24
  17. package/dist/entrypoints/application.js +208 -210
  18. package/dist/entrypoints/bin/upgrade-cli.js +2 -2
  19. package/dist/entrypoints/cli.js +81 -84
  20. package/dist/entrypoints/contract.js +54 -57
  21. package/dist/entrypoints/declaration.js +22 -22
  22. package/dist/entrypoints/files.js +18 -21
  23. package/dist/entrypoints/geo.js +7 -8
  24. package/dist/entrypoints/google.js +2 -2
  25. package/dist/entrypoints/index.js +150 -154
  26. package/dist/entrypoints/live.js +45 -47
  27. package/dist/entrypoints/node.js +68 -74
  28. package/dist/entrypoints/oauth.js +6 -6
  29. package/dist/entrypoints/observability.d.ts +1 -0
  30. package/dist/entrypoints/observability.d.ts.map +1 -1
  31. package/dist/entrypoints/observability.js +115 -87
  32. package/dist/entrypoints/primitives.js +35 -35
  33. package/dist/entrypoints/react/keyboard.d.ts +4 -0
  34. package/dist/entrypoints/react/keyboard.d.ts.map +1 -0
  35. package/dist/entrypoints/react/keyboard.js +397 -0
  36. package/dist/entrypoints/react.js +10 -10
  37. package/dist/entrypoints/release.js +7 -7
  38. package/dist/entrypoints/remote.js +15 -17
  39. package/dist/entrypoints/server.js +198 -200
  40. package/dist/entrypoints/telegram/html.d.ts +5 -0
  41. package/dist/entrypoints/telegram/html.d.ts.map +1 -0
  42. package/dist/entrypoints/telegram/html.js +26 -0
  43. package/dist/entrypoints/telegram/screens.d.ts +14 -0
  44. package/dist/entrypoints/telegram/screens.d.ts.map +1 -0
  45. package/dist/entrypoints/telegram/screens.js +2028 -0
  46. package/dist/entrypoints/telegram.d.ts +5 -1
  47. package/dist/entrypoints/telegram.d.ts.map +1 -1
  48. package/dist/entrypoints/telegram.js +548 -156
  49. package/dist/entrypoints/testing.js +75 -79
  50. package/dist/entrypoints/tools/connections.js +30 -32
  51. package/dist/entrypoints/tools/contract.js +18 -20
  52. package/dist/entrypoints/tools/invoker.js +12 -17
  53. package/dist/entrypoints/tools.js +223 -229
  54. package/dist/entrypoints/tracking/server.js +6 -6
  55. package/dist/entrypoints/tracking.js +40 -42
  56. package/dist/entrypoints/voice.js +3 -3
  57. package/dist/{index-eaysmdtq.js → index-0ndk4555.js} +56 -56
  58. package/dist/{index-2bxbyab0.js → index-1bx1xv1k.js} +1 -1
  59. package/dist/{index-p5r7qpdd.js → index-1eeqpadm.js} +4 -4
  60. package/dist/{index-hadmp193.js → index-3ct7hhq6.js} +210 -210
  61. package/dist/{index-e01r054k.js → index-45tdvqa3.js} +26 -26
  62. package/dist/{index-dce5wxcq.js → index-4s0fep5q.js} +8 -8
  63. package/dist/index-50ejfz75.js +9 -0
  64. package/dist/{index-m9zn6cpq.js → index-5107q189.js} +12 -12
  65. package/dist/{index-sbdmyz75.js → index-5cc6r990.js} +3 -3
  66. package/dist/index-6k1svmjh.js +141 -0
  67. package/dist/{index-c6bxbsnc.js → index-7kxw1awn.js} +2 -2
  68. package/dist/{index-0r0fbk7z.js → index-7z9ym7t8.js} +28 -28
  69. package/dist/{index-p7hgdyhb.js → index-814xpr6d.js} +2 -2
  70. package/dist/{index-gtj3zc53.js → index-8kzct1d6.js} +99 -99
  71. package/dist/{index-1zbbzgfh.js → index-9pw0a51a.js} +4 -4
  72. package/dist/{index-79z7m7dt.js → index-a9pd417t.js} +35 -35
  73. package/dist/{index-ham5sz8m.js → index-aaj97r4y.js} +45 -45
  74. package/dist/{index-s812ycat.js → index-aan6hqb9.js} +3 -3
  75. package/dist/{index-10x2hbx0.js → index-adhgd4pe.js} +44 -44
  76. package/dist/{index-2gxzjvyr.js → index-afjvjyck.js} +23 -23
  77. package/dist/{index-qmy6zq75.js → index-ahvsksw5.js} +16 -16
  78. package/dist/{index-hr4tzbwq.js → index-ap3gqe56.js} +3 -3
  79. package/dist/{index-znfs20ss.js → index-b2bz0kdm.js} +16 -16
  80. package/dist/{index-r066jx76.js → index-c6aagrbd.js} +148 -120
  81. package/dist/{index-k30h66yd.js → index-ck71tbcf.js} +9 -9
  82. package/dist/{index-eqqvgdb3.js → index-ct75c3at.js} +2 -2
  83. package/dist/{index-gw8bmyaj.js → index-djjhhgjk.js} +41 -41
  84. package/dist/{index-8qt2m66q.js → index-dvwj1f43.js} +43 -43
  85. package/dist/{index-fhwqwxe0.js → index-ej331hah.js} +1 -1
  86. package/dist/{index-9t3dffv2.js → index-ewbaywk5.js} +5 -5
  87. package/dist/{index-7p1f0vp2.js → index-fyphpknh.js} +25 -25
  88. package/dist/{index-83bdg97s.js → index-g149e9pk.js} +1 -1
  89. package/dist/{index-ngfhvfpd.js → index-g6a3na27.js} +4 -4
  90. package/dist/{index-qwhynv6x.js → index-h124epcf.js} +20 -20
  91. package/dist/{index-h6eeys1v.js → index-h97tqqp1.js} +9 -9
  92. package/dist/{index-zcgf3gqf.js → index-hby4qhax.js} +10 -10
  93. package/dist/{index-5jrd0yng.js → index-j8aw2c0e.js} +4 -4
  94. package/dist/{index-d8m8zpd8.js → index-jzczzcsb.js} +14 -14
  95. package/dist/index-kqnd6a85.js +26 -0
  96. package/dist/{index-35mh5bhj.js → index-kw1ws0cs.js} +12 -12
  97. package/dist/{index-yw4fzmdz.js → index-kzz6rq0w.js} +28 -17
  98. package/dist/{index-4gcnakhx.js → index-m38ej7e5.js} +2 -2
  99. package/dist/{index-ndddxtyx.js → index-m79yr938.js} +19 -19
  100. package/dist/{index-5p2m7we1.js → index-m9fndta6.js} +11 -11
  101. package/dist/index-mnkk1ffz.js +150 -0
  102. package/dist/index-n15jny5b.js +4 -0
  103. package/dist/{index-2vtcmrj9.js → index-n53mswt3.js} +20 -20
  104. package/dist/{index-bt14acb5.js → index-n5yqxd3d.js} +21 -21
  105. package/dist/{index-bm5rx7n6.js → index-n9tyz8z3.js} +12 -12
  106. package/dist/index-nmaqxdx7.js +463 -0
  107. package/dist/{index-mqv3b5rh.js → index-nx6eazt0.js} +30 -30
  108. package/dist/{index-3z73fh2c.js → index-q0th8q0z.js} +9 -9
  109. package/dist/{index-v260df89.js → index-qjeggp8w.js} +20 -20
  110. package/dist/{index-zfrhfn82.js → index-r1z0rd9c.js} +20 -20
  111. package/dist/{index-wqgjfstn.js → index-r5c4fedv.js} +3 -3
  112. package/dist/{index-cyktc4bp.js → index-r5hsgkz5.js} +118 -118
  113. package/dist/{index-0b1ess5e.js → index-r7a7r7ha.js} +1 -1
  114. package/dist/{index-1j8pm5t0.js → index-rfkh44ss.js} +15 -15
  115. package/dist/index-rz3z13e9.js +47 -0
  116. package/dist/{index-k6gpggb9.js → index-s80awwsw.js} +35 -35
  117. package/dist/{index-vqr7f7v8.js → index-ssmd41kh.js} +124 -124
  118. package/dist/{index-ensd0r74.js → index-v14qqmys.js} +41 -41
  119. package/dist/{index-paz6sgdp.js → index-v4a2fjtk.js} +36 -36
  120. package/dist/{index-d9pk3td4.js → index-w0eqdhyd.js} +14 -14
  121. package/dist/{index-5qn1kx34.js → index-w575evhq.js} +29 -29
  122. package/dist/{index-3gye9wzb.js → index-w5s3xftz.js} +26 -26
  123. package/dist/{index-tm88avnj.js → index-wykebpn9.js} +3 -3
  124. package/dist/{index-sh3s86na.js → index-xkhk5d6g.js} +17 -17
  125. package/dist/{index-6k1937bx.js → index-xqhede6x.js} +4 -4
  126. package/dist/{index-f4fx2tza.js → index-zs4ms3th.js} +181 -181
  127. package/dist/{index-k5hsfc3j.js → index-zsvzhjtk.js} +1 -1
  128. package/dist/observability/bounded-logger.d.ts +2 -0
  129. package/dist/observability/bounded-logger.d.ts.map +1 -1
  130. package/dist/observability/sanitize.d.ts +6 -0
  131. package/dist/observability/sanitize.d.ts.map +1 -1
  132. package/dist/observability/secret-values.d.ts +25 -0
  133. package/dist/observability/secret-values.d.ts.map +1 -0
  134. package/dist/react/keyboard/hooks.d.ts +71 -0
  135. package/dist/react/keyboard/hooks.d.ts.map +1 -0
  136. package/dist/react/keyboard/layers.d.ts +98 -0
  137. package/dist/react/keyboard/layers.d.ts.map +1 -0
  138. package/dist/react/keyboard/zone.d.ts +139 -0
  139. package/dist/react/keyboard/zone.d.ts.map +1 -0
  140. package/dist/telegram/crypto.d.ts +16 -0
  141. package/dist/telegram/crypto.d.ts.map +1 -0
  142. package/dist/telegram/html/check.d.ts +26 -0
  143. package/dist/telegram/html/check.d.ts.map +1 -0
  144. package/dist/telegram/html/nodes.d.ts +70 -0
  145. package/dist/telegram/html/nodes.d.ts.map +1 -0
  146. package/dist/telegram/html/parse.d.ts +35 -0
  147. package/dist/telegram/html/parse.d.ts.map +1 -0
  148. package/dist/telegram/html/render.d.ts +39 -0
  149. package/dist/telegram/html/render.d.ts.map +1 -0
  150. package/dist/telegram/init-data.d.ts.map +1 -1
  151. package/dist/telegram/operator-channel.d.ts +36 -3
  152. package/dist/telegram/operator-channel.d.ts.map +1 -1
  153. package/dist/telegram/screens/callback-codec.d.ts +34 -0
  154. package/dist/telegram/screens/callback-codec.d.ts.map +1 -0
  155. package/dist/telegram/screens/dispatch.d.ts +22 -0
  156. package/dist/telegram/screens/dispatch.d.ts.map +1 -0
  157. package/dist/telegram/screens/display.d.ts +70 -0
  158. package/dist/telegram/screens/display.d.ts.map +1 -0
  159. package/dist/telegram/screens/execute.d.ts +57 -0
  160. package/dist/telegram/screens/execute.d.ts.map +1 -0
  161. package/dist/telegram/screens/html.d.ts +36 -0
  162. package/dist/telegram/screens/html.d.ts.map +1 -0
  163. package/dist/telegram/screens/outcome.d.ts +74 -0
  164. package/dist/telegram/screens/outcome.d.ts.map +1 -0
  165. package/dist/telegram/screens/path.d.ts +29 -0
  166. package/dist/telegram/screens/path.d.ts.map +1 -0
  167. package/dist/telegram/screens/reconcile.d.ts +67 -0
  168. package/dist/telegram/screens/reconcile.d.ts.map +1 -0
  169. package/dist/telegram/screens/registry.d.ts +23 -0
  170. package/dist/telegram/screens/registry.d.ts.map +1 -0
  171. package/dist/telegram/screens/render.d.ts +70 -0
  172. package/dist/telegram/screens/render.d.ts.map +1 -0
  173. package/dist/telegram/screens/runtime.d.ts +133 -0
  174. package/dist/telegram/screens/runtime.d.ts.map +1 -0
  175. package/dist/telegram/screens/screen-types.d.ts +130 -0
  176. package/dist/telegram/screens/screen-types.d.ts.map +1 -0
  177. package/dist/telegram/screens/screen.d.ts +138 -0
  178. package/dist/telegram/screens/screen.d.ts.map +1 -0
  179. package/dist/telegram/screens/state.d.ts +115 -0
  180. package/dist/telegram/screens/state.d.ts.map +1 -0
  181. package/dist/telegram/screens/telegram-screens.d.ts +18 -0
  182. package/dist/telegram/screens/telegram-screens.d.ts.map +1 -0
  183. package/dist/telegram/screens/test-chat-telegram.d.ts +47 -0
  184. package/dist/telegram/screens/test-chat-telegram.d.ts.map +1 -0
  185. package/dist/telegram/screens/test-chat.d.ts +66 -0
  186. package/dist/telegram/screens/test-chat.d.ts.map +1 -0
  187. package/dist/telegram/screens/view.d.ts +89 -0
  188. package/dist/telegram/screens/view.d.ts.map +1 -0
  189. package/dist/telegram/send-failure.d.ts +19 -0
  190. package/dist/telegram/send-failure.d.ts.map +1 -1
  191. package/dist/telegram/update-intake.d.ts +78 -0
  192. package/dist/telegram/update-intake.d.ts.map +1 -0
  193. package/dist/telegram/update-store-sqlite.d.ts +26 -0
  194. package/dist/telegram/update-store-sqlite.d.ts.map +1 -0
  195. package/dist/telegram/update-store.d.ts +67 -0
  196. package/dist/telegram/update-store.d.ts.map +1 -0
  197. package/dist/telegram/webhook.d.ts +105 -0
  198. package/dist/telegram/webhook.d.ts.map +1 -0
  199. package/dist/tools/cli/args-fields.d.ts +8 -0
  200. package/dist/tools/cli/args-fields.d.ts.map +1 -1
  201. package/dist/tools/cli/args-route.d.ts.map +1 -1
  202. package/dist/tools/cli/args.d.ts.map +1 -1
  203. package/dist/tools/cli/help.d.ts.map +1 -1
  204. package/llms/cli.txt +8 -2
  205. package/llms/observability.txt +2 -1
  206. package/llms/react-keyboard.txt +193 -0
  207. package/llms/stitchkit.txt +7 -1
  208. package/llms/telegram-html.txt +35 -0
  209. package/llms/telegram-screens.txt +365 -0
  210. package/llms/telegram.txt +160 -4
  211. package/llms-full.txt +736 -8
  212. package/llms.txt +10 -5
  213. package/package.json +17 -2
  214. package/dist/index-2k4yrqkc.js +0 -9
  215. package/dist/index-crykmqkr.js +0 -26
  216. package/dist/index-y64k3s0h.js +0 -150
  217. package/dist/index-y91ry9h2.js +0 -4
  218. /package/dist/{index-hffjpmq9.js → index-9jfdm5tg.js} +0 -0
  219. /package/dist/{index-zjjyynm3.js → index-d4pa2bgs.js} +0 -0
  220. /package/dist/{index-rxfy4cq7.js → index-dwfv9a85.js} +0 -0
  221. /package/dist/{index-5jm36zv1.js → index-gfk7nrht.js} +0 -0
  222. /package/dist/{index-b9aefrqd.js → index-n1dqr7gf.js} +0 -0
  223. /package/dist/{index-q3pyb9n0.js → index-sykb5ag7.js} +0 -0
  224. /package/dist/{index-48ffdxgk.js → index-xhzq2qvj.js} +0 -0
  225. /package/dist/{index-kzfs85xp.js → index-zsarb5xp.js} +0 -0
@@ -0,0 +1,133 @@
1
+ /**
2
+ * The screens of one bot, as grammY middleware.
3
+ *
4
+ * `bot.use(screens)` takes the presses whose `callback_data` carries this
5
+ * runtime's prefix and the messages a shown screen takes as input; every other
6
+ * update goes to the next handler untouched, and it is handed on outside the
7
+ * chat's queue. `screens.open(ctx, screen)` shows a screen from a command or a
8
+ * deep link; `screens.button(link(…))` puts a link to a screen into a message
9
+ * the screens do not own — a notification.
10
+ *
11
+ * Every chat is handled one update at a time: read the chat's record, resolve
12
+ * the screen, render, reconcile against what the chat shows, carry the plan
13
+ * out, write the record. The record is written after Telegram has answered, so
14
+ * it never names a message that was not sent; a crash in between leaves the
15
+ * chat ahead of its record, and the next press is handled as a press on a
16
+ * message the record does not know. Two processes serving one chat — builds
17
+ * overlapping during a release, a webhook fan-out — are not serialised: the
18
+ * last write wins.
19
+ */
20
+ import type { Context, MiddlewareFn, MiddlewareObj } from 'grammy';
21
+ import type { InlineKeyboardButton } from 'grammy/types';
22
+ import { type DisplayRequest } from './display.js';
23
+ import type { ExecutionReport, ScreenApi } from './execute.js';
24
+ import type { ScreenOutcomeBuilders } from './outcome.js';
25
+ import { type DeclaredScreen, type ScreenRegistry } from './registry.js';
26
+ import type { AnyTelegramScreen, ScreenHandlerResult, ScreenLinkArgs } from './screen-types.js';
27
+ import { type ScreenChatState, type TelegramScreenStorage } from './state.js';
28
+ import type { ScreenButton } from './view.js';
29
+ /** Why a press could not be answered by the screen it names. */
30
+ export type ScreenStaleReason = 'malformed' | 'forged' | 'inaccessible' | 'unknown-token' | 'unknown-screen' | 'invalid-params' | 'unknown-action' | 'invalid-input';
31
+ export type ScreenTrigger = 'open' | 'press' | 'input';
32
+ export interface ScreenStaleContext<C extends Context> extends ScreenOutcomeBuilders {
33
+ readonly ctx: C;
34
+ readonly reason: ScreenStaleReason;
35
+ }
36
+ export interface ScreenErrorContext<C extends Context> extends ScreenOutcomeBuilders {
37
+ readonly ctx: C;
38
+ readonly trigger: ScreenTrigger;
39
+ }
40
+ /**
41
+ * What happened, for the application's journal. Never carries message text:
42
+ * screens are named by their path template, messages by id.
43
+ */
44
+ export type ScreenEvent = {
45
+ readonly type: 'transition';
46
+ readonly trigger: ScreenTrigger;
47
+ readonly chat: string;
48
+ /** The screen shown before, as its path template; absent when none was. */
49
+ readonly from: string | undefined;
50
+ readonly to: string;
51
+ readonly durationMs: number;
52
+ readonly report: ExecutionReport;
53
+ }
54
+ /** A stored record did not match this release's schema and was set aside. */
55
+ | {
56
+ readonly type: 'state-discarded';
57
+ readonly chat: string;
58
+ }
59
+ /** Messages Telegram would not delete — an expired remark, the user's input. */
60
+ | {
61
+ readonly type: 'message-kept';
62
+ readonly chat: string;
63
+ readonly messageIds: readonly number[];
64
+ }
65
+ /**
66
+ * Deleting expired remarks on their timer failed — no update was there to
67
+ * carry the error. The chat's next update sweeps them again.
68
+ */
69
+ | {
70
+ readonly type: 'sweep-failed';
71
+ readonly chat: string;
72
+ readonly error: unknown;
73
+ };
74
+ export interface TelegramScreensConfig<C extends Context> {
75
+ readonly screens: readonly DeclaredScreen<C>[];
76
+ /** Where each chat's screen survives a restart — any grammY `StorageAdapter`. */
77
+ readonly storage: TelegramScreenStorage;
78
+ /** The storage key of a chat's record. Default: `screens:<chat id>`, apart from grammY sessions. */
79
+ readonly chatKey?: (ctx: C) => string | undefined;
80
+ /** What every screen button's `callback_data` starts with. Default `"~"`. */
81
+ readonly callbackPrefix?: string;
82
+ /** Which chats screens answer in. Default `'private'`: in a group any member could press or type. */
83
+ readonly chats?: 'private' | 'all';
84
+ /** A press this bot no longer understands, or that no button carried. Default: answered silently. */
85
+ readonly onStale?: (c: ScreenStaleContext<C>) => ScreenHandlerResult;
86
+ /**
87
+ * A load, action or input that threw. Its outcome is shown instead; without
88
+ * it the press is answered silently and the error reaches `bot.catch`.
89
+ */
90
+ readonly onError?: (error: unknown, c: ScreenErrorContext<C>) => ScreenHandlerResult;
91
+ readonly onEvent?: (event: ScreenEvent) => void;
92
+ /** Epoch milliseconds, for expiring notices. Default `Date.now`. */
93
+ readonly clock?: () => number;
94
+ }
95
+ export interface OpenOptions {
96
+ /** The view the chat showed: kept as it is (default) or deleted. */
97
+ readonly previous?: 'keep' | 'delete';
98
+ }
99
+ export type OpenArgs<TScreen> = ScreenLinkArgs<TScreen> extends [params: infer P] ? [params: P, options?: OpenOptions] : ScreenLinkArgs<TScreen> extends [params?: infer P] ? [params?: P, options?: OpenOptions] : never;
100
+ export interface TelegramScreens<C extends Context> extends MiddlewareObj<C> {
101
+ middleware(): MiddlewareFn<C>;
102
+ /** Show a screen as a new message at the bottom of the chat. */
103
+ open<TScreen extends AnyTelegramScreen>(ctx: C, screen: TScreen, ...args: OpenArgs<TScreen>): Promise<void>;
104
+ /** A link for a message the screens do not own; pressing it opens the screen below. */
105
+ button(link: ScreenButton): InlineKeyboardButton.CallbackButton;
106
+ /** Cancel pending expiry timers; remarks left behind are swept on the chat's next update. */
107
+ close(): void;
108
+ }
109
+ /** What dispatch and display share for one bot. */
110
+ export interface ScreensRuntime<C extends Context> {
111
+ readonly registry: ScreenRegistry<C>;
112
+ readonly config: TelegramScreensConfig<C>;
113
+ readonly prefix: string;
114
+ readonly clock: () => number;
115
+ chatKey(ctx: C): string | undefined;
116
+ answers(ctx: C): boolean;
117
+ /** Run `task` alone in the chat; a call from inside the chat's own task runs inline. */
118
+ exclusive<T>(ctx: C, chat: string, task: () => Promise<T>): Promise<T>;
119
+ readState(chat: string): Promise<ScreenChatState>;
120
+ display(request: DisplayRequest<C>): Promise<void>;
121
+ /** `open` showed a screen for this update. */
122
+ markOpened(ctx: C): void;
123
+ /** Whether `open` showed a screen for this update — from inside its handler, its navigation stands. */
124
+ openedDuring(ctx: C): boolean;
125
+ scheduleSweep(api: ScreenApi, chat: string, chatId: number, delayMs: number): void;
126
+ emit(event: ScreenEvent): void;
127
+ }
128
+ export interface OwnedScreensRuntime<C extends Context> extends ScreensRuntime<C> {
129
+ /** Expiry timers not yet fired, so `close()` can cancel them. */
130
+ readonly timers: Set<ReturnType<typeof setTimeout>>;
131
+ }
132
+ export declare function createScreensRuntime<C extends Context>(config: TelegramScreensConfig<C>): OwnedScreensRuntime<C>;
133
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * The types a screen is declared with, and the loose shape the runtime drives.
3
+ *
4
+ * A declared screen is typed end to end — its params come from its path (or a
5
+ * params schema), its data from its loads, its action buttons from its
6
+ * actions — and the runtime sees none of that. It holds a
7
+ * {@link ScreenDefinition}: closures over the typed declaration that take raw,
8
+ * untrusted params and input, validate them, and only then call the
9
+ * application. The one crossing from raw to typed is the params schema, which
10
+ * runs on every resolution.
11
+ */
12
+ import type { Context } from 'grammy';
13
+ import type { Message } from 'grammy/types';
14
+ import type { ActionValue } from './callback-codec.js';
15
+ import type { TelegramText } from './html.js';
16
+ import type { ScreenOutcome, ScreenOutcomeBuilders } from './outcome.js';
17
+ import type { ScreenPath } from './path.js';
18
+ import type { ButtonLabel, ScreenButton, ScreenViewResult } from './view.js';
19
+ /** A param value after its schema: text, or a number a schema produced. */
20
+ export type ScreenParamValue = string | number;
21
+ export type ScreenParams = Readonly<Record<string, ScreenParamValue>>;
22
+ declare const noInput: unique symbol;
23
+ /** An action declared without an input schema. */
24
+ export type NoActionInput = typeof noInput;
25
+ /** Action name → what its button takes (`NoActionInput` when nothing). */
26
+ export type ScreenActions = Readonly<Record<string, unknown>>;
27
+ export type MaybePromise<TValue> = TValue | Promise<TValue>;
28
+ /** What a handler may answer with; nothing — a body with no `return` — is `stay()`. */
29
+ export type ScreenHandlerResult = MaybePromise<ScreenOutcome | undefined> | MaybePromise<void>;
30
+ export interface ScreenLoadContext<C extends Context, P extends ScreenParams, D> extends ScreenOutcomeBuilders {
31
+ /** The grammY context of the update being answered. */
32
+ readonly ctx: C;
33
+ /** Params from the button that was pressed — user input, validated by the params schema. */
34
+ readonly params: P;
35
+ /** What the enclosing group loaded; `undefined` outside a group. */
36
+ readonly data: D;
37
+ }
38
+ export interface ScreenActionContext<C extends Context, P extends ScreenParams, D, I> extends ScreenOutcomeBuilders {
39
+ readonly ctx: C;
40
+ readonly params: P;
41
+ /** What this screen's loads returned for this press. */
42
+ readonly data: D;
43
+ /** The button's input, parsed by the action's schema. */
44
+ readonly input: I;
45
+ }
46
+ /** An outcome after a message: there is no press to answer, so no toast. */
47
+ export type ScreenInputOutcomeBuilders = Omit<ScreenOutcomeBuilders, 'toast'>;
48
+ export interface ScreenInputContext<C extends Context, P extends ScreenParams, D> extends ScreenInputOutcomeBuilders {
49
+ readonly ctx: C;
50
+ readonly params: P;
51
+ readonly data: D;
52
+ /** The message as Telegram sent it. It is never stored. */
53
+ readonly message: Message;
54
+ /** Its text, or its caption, or `''`. */
55
+ readonly text: string;
56
+ /** Show a "working on it" message; it is removed when the handler ends, however it ends. */
57
+ pending(content: TelegramText): Promise<void>;
58
+ }
59
+ /** The action buttons of a screen, one factory per declared action. */
60
+ export type ScreenActionButtons<A extends ScreenActions> = {
61
+ readonly [K in keyof A]: A[K] extends NoActionInput ? (label: ButtonLabel) => ScreenButton : (label: ButtonLabel, input: A[K]) => ScreenButton;
62
+ };
63
+ export interface ScreenViewContext<C extends Context, P extends ScreenParams, D, A extends ScreenActions> {
64
+ readonly ctx: C;
65
+ readonly params: P;
66
+ readonly data: D;
67
+ readonly act: ScreenActionButtons<A>;
68
+ }
69
+ /** Message kinds a screen can take as input. */
70
+ export type ScreenInputKind = 'text' | 'rich' | 'photo' | 'video' | 'animation' | 'document' | 'audio' | 'voice' | 'video_note' | 'sticker' | 'location' | 'contact';
71
+ export interface ScreenInputOptions {
72
+ /** Leave the user's message in the chat. Default: removed before the handler runs. */
73
+ readonly keepMessage?: boolean;
74
+ }
75
+ /** Why raw params or input did not become a screen. */
76
+ export type ScreenRefusal = 'invalid-params' | 'unknown-action' | 'invalid-input';
77
+ /** A screen resolved for one update: params parsed, data loaded. */
78
+ export interface ResolvedScreen {
79
+ readonly params: ScreenParams;
80
+ render(): ScreenViewResult;
81
+ runAction(action: string, input: Readonly<Record<string, ActionValue>> | undefined): Promise<ScreenOutcome | undefined | ScreenRefusal>;
82
+ input(kind: ScreenInputKind): ResolvedScreenInput | undefined;
83
+ }
84
+ export interface ResolvedScreenInput {
85
+ readonly keepMessage: boolean;
86
+ handle(message: Message, pending: (content: TelegramText) => Promise<void>): Promise<ScreenOutcome | undefined>;
87
+ }
88
+ /** The loose screen the runtime drives. Methods, so a narrower context still assigns. */
89
+ export interface ScreenDefinition<C extends Context> {
90
+ readonly path: ScreenPath;
91
+ readonly id: string;
92
+ readonly explicitId: boolean;
93
+ /** Some load — the screen's own or a group's — runs before it: its params are checked. */
94
+ readonly guarded: boolean;
95
+ readonly actions: readonly string[];
96
+ readonly inputKinds: readonly ScreenInputKind[];
97
+ /** The screen takes this kind and leaves the user's message in the chat. */
98
+ keepsInput(kind: ScreenInputKind): boolean;
99
+ /** The params pass the schemas — no load runs. */
100
+ acceptsParams(params: Readonly<Record<string, ActionValue>>): boolean;
101
+ resolve(ctx: C, params: Readonly<Record<string, ActionValue>>): Promise<ResolvedScreen | ScreenOutcome | 'invalid-params'>;
102
+ }
103
+ /** A declared screen. The type parameters exist for the declaration's callers. */
104
+ export declare class TelegramScreen<C extends Context, P extends ScreenParams, D, A extends ScreenActions> {
105
+ readonly definition: ScreenDefinition<C>;
106
+ readonly '~types'?: {
107
+ readonly ctx: C;
108
+ readonly params: P;
109
+ readonly data: D;
110
+ readonly actions: A;
111
+ };
112
+ constructor(definition: ScreenDefinition<C>);
113
+ get path(): string;
114
+ }
115
+ /** Any declared screen, whatever its context, params, data and actions. */
116
+ export type AnyTelegramScreen = TelegramScreen<Context, ScreenParams, unknown, ScreenActions>;
117
+ /**
118
+ * The params argument of a link or a `go`: required exactly when the path has
119
+ * params, and refused when it has none — a param the path does not name would
120
+ * make the button unreadable.
121
+ */
122
+ export type ScreenLinkArgs<TScreen> = TScreen extends {
123
+ readonly '~types'?: {
124
+ readonly params: infer P;
125
+ };
126
+ } ? keyof P extends never ? [params?: {
127
+ readonly [name: string]: never;
128
+ }] : [params: P] : never;
129
+ export {};
130
+ //# sourceMappingURL=screen-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen-types.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/screen-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Declaring screens: `tg.screen(path).load(…).action(…).on(…).view(…)`, and
3
+ * groups that share a path, params and a load.
4
+ *
5
+ * Every step narrows the types the next one sees, the way a Hono route or an
6
+ * Elysia handler does: the path names the params, `load` names the data, each
7
+ * `action` adds a typed button factory to `act`. `load` comes first or not at
8
+ * all — actions and input run after it and read what it returned — and `view`
9
+ * ends the declaration.
10
+ *
11
+ * A group is where access is checked once for everything under it:
12
+ * `tg.group('/bot/:botId', { params }).load(ownedBot)` runs its params schema and
13
+ * its load before every screen of the group — before its load, its actions and
14
+ * its input — and hands the screen what it loaded as `c.data`. Params arrive
15
+ * from a button, so they are user input; a screen with params and no load
16
+ * anywhere above it is refused when the bot is composed.
17
+ *
18
+ * What the runtime receives is a {@link ScreenDefinition}: closures over the
19
+ * typed declaration that take raw params and raw button input, validate them,
20
+ * and only then call the application's functions.
21
+ */
22
+ import type { Context } from 'grammy';
23
+ import { z } from 'zod';
24
+ import { type ActionValue } from './callback-codec.js';
25
+ import { ScreenOutcome } from './outcome.js';
26
+ import { type ScreenPathParams } from './path.js';
27
+ import type { MaybePromise, NoActionInput, ScreenActionContext, ScreenActions, ScreenHandlerResult, ScreenInputContext, ScreenInputKind, ScreenInputOptions, ScreenLoadContext, ScreenParams, ScreenViewContext } from './screen-types.js';
28
+ import { TelegramScreen } from './screen-types.js';
29
+ import { type ScreenViewResult } from './view.js';
30
+ /** A schema for an action's input: an object whose fields a button can carry. */
31
+ export type ActionInputSchema = z.ZodType<Readonly<Record<string, unknown>>, Readonly<Record<string, ActionValue | undefined>>>;
32
+ /** A schema for the params a path segment adds: one field per `:name`. */
33
+ export type ParamsSchemaFor<TPath extends string> = z.ZodType<{
34
+ readonly [K in keyof ScreenPathParams<TPath>]: string | number;
35
+ }, {
36
+ readonly [K in keyof ScreenPathParams<TPath>]: unknown;
37
+ }>;
38
+ /**
39
+ * `S` when it accepts what it produces, else `never`. A button carries the
40
+ * parsed params, and the schema parses them again when it is pressed: a
41
+ * transform whose output its own input refuses — `z.string().transform(Number)`
42
+ * — would make every link to the screen stale. `z.coerce.number()` accepts it.
43
+ */
44
+ export type AcceptsOwnOutput<S> = S extends z.ZodType<infer O, infer I> ? ([O] extends [I] ? S : never) : never;
45
+ export interface ScopeOptions<TSchema> {
46
+ /** Validates (and may coerce) the params this path adds — they come from a button. */
47
+ readonly params?: TSchema;
48
+ }
49
+ export interface ScreenOptions<TSchema> extends ScopeOptions<TSchema> {
50
+ /**
51
+ * The id buttons carry instead of the path. Set it to keep buttons already
52
+ * sent working after the path is renamed. Default: derived from the path.
53
+ */
54
+ readonly id?: string;
55
+ }
56
+ /** What a scope — the root, or a group — hands the screens declared in it. */
57
+ export interface ScopeCore<C extends Context, P extends ScreenParams, D> {
58
+ readonly prefix: string;
59
+ readonly paramNames: readonly string[];
60
+ readonly parseParams: (raw: Readonly<Record<string, ActionValue>>) => P | undefined;
61
+ readonly load: (ctx: C, params: P) => Promise<D | ScreenOutcome>;
62
+ readonly guarded: boolean;
63
+ }
64
+ interface HandlerBase<C extends Context, P extends ScreenParams, D> {
65
+ readonly ctx: C;
66
+ readonly params: P;
67
+ readonly data: D;
68
+ }
69
+ type ActionEntry<C extends Context, P extends ScreenParams, D> = (base: HandlerBase<C, P, D>, input: Readonly<Record<string, ActionValue>> | undefined) => Promise<ScreenOutcome | undefined | 'invalid-input'>;
70
+ type InputEntry<C extends Context, P extends ScreenParams, D> = {
71
+ readonly keepMessage: boolean;
72
+ readonly handler: (c: ScreenInputContext<C, P, D>) => ScreenHandlerResult;
73
+ };
74
+ /** A screen after `load` (or without one): actions, input and the view. */
75
+ export declare class ScreenBodyBuilder<C extends Context, P extends ScreenParams, D, A extends ScreenActions> {
76
+ protected readonly core: ScopeCore<C, P, D>;
77
+ protected readonly id: {
78
+ readonly value: string;
79
+ readonly explicit: boolean;
80
+ };
81
+ protected readonly actions: ReadonlyMap<string, ActionEntry<C, P, D>>;
82
+ protected readonly inputs: ReadonlyMap<ScreenInputKind, InputEntry<C, P, D>>;
83
+ constructor(core: ScopeCore<C, P, D>, id: {
84
+ readonly value: string;
85
+ readonly explicit: boolean;
86
+ }, actions: ReadonlyMap<string, ActionEntry<C, P, D>>, inputs: ReadonlyMap<ScreenInputKind, InputEntry<C, P, D>>);
87
+ /** A button handler. Its button is `act.<name>(label)`. */
88
+ action<N extends string>(name: N, handler: (c: ScreenActionContext<C, P, D, undefined>) => ScreenHandlerResult): ScreenBodyBuilder<C, P, D, A & {
89
+ readonly [K in N]: NoActionInput;
90
+ }>;
91
+ /** A button handler with typed input. Its button is `act.<name>(label, input)`. */
92
+ action<N extends string, S extends ActionInputSchema>(name: N, schema: S, handler: (c: ScreenActionContext<C, P, D, z.output<S>>) => ScreenHandlerResult): ScreenBodyBuilder<C, P, D, A & {
93
+ readonly [K in N]: z.input<S>;
94
+ }>;
95
+ /**
96
+ * Messages of these kinds, while this screen is shown. Other kinds, and
97
+ * commands, go to the next handler.
98
+ */
99
+ on(kinds: ScreenInputKind | readonly ScreenInputKind[], handler: (c: ScreenInputContext<C, P, D>) => ScreenHandlerResult, options?: ScreenInputOptions): ScreenBodyBuilder<C, P, D, A>;
100
+ /** What the chat shows. Ends the declaration. */
101
+ view(render: (c: ScreenViewContext<C, P, D, A>) => ScreenViewResult): TelegramScreen<C, P, D, A>;
102
+ }
103
+ /** A screen before `load`: it may still load data. */
104
+ export declare class ScreenBuilder<C extends Context, P extends ScreenParams, D> extends ScreenBodyBuilder<C, P, D, Record<never, never>> {
105
+ /**
106
+ * The data this screen shows and its actions act on. Runs before every show,
107
+ * every action and every input, after the group's load, whose data it reads
108
+ * as `c.data`. Return an outcome instead of data to go somewhere else.
109
+ */
110
+ load<R>(fetch: (c: ScreenLoadContext<C, P, D>) => MaybePromise<R>): ScreenBodyBuilder<C, P, Exclude<R, ScreenOutcome>, Record<never, never>>;
111
+ }
112
+ /** Where screens are declared: the root, or a group of them. */
113
+ export declare class ScreenScope<C extends Context, P extends ScreenParams, D> {
114
+ protected readonly core: ScopeCore<C, P, D>;
115
+ constructor(core: ScopeCore<C, P, D>);
116
+ /** A screen at `path`, relative to this scope. */
117
+ screen<TPath extends string>(path: TPath, options?: ScreenOptions<undefined>): ScreenBuilder<C, P & ScreenPathParams<TPath>, D>;
118
+ screen<TPath extends string, S extends ParamsSchemaFor<TPath>>(path: TPath, options: ScreenOptions<S> & {
119
+ readonly params: S & AcceptsOwnOutput<S>;
120
+ }): ScreenBuilder<C, P & z.output<S>, D>;
121
+ /** Screens that share a path prefix, its params and — once `load` is called — a load. */
122
+ group<TPath extends string>(path: TPath, options?: ScopeOptions<undefined>): ScreenGroupBuilder<C, P & ScreenPathParams<TPath>, D>;
123
+ group<TPath extends string, S extends ParamsSchemaFor<TPath>>(path: TPath, options: ScopeOptions<S> & {
124
+ readonly params: S & AcceptsOwnOutput<S>;
125
+ }): ScreenGroupBuilder<C, P & z.output<S>, D>;
126
+ }
127
+ /** A group before `load`. */
128
+ export declare class ScreenGroupBuilder<C extends Context, P extends ScreenParams, D> extends ScreenScope<C, P, D> {
129
+ /**
130
+ * Runs before every screen of the group — before its load, its actions and
131
+ * its input. The place to check that the params are the user's to use.
132
+ */
133
+ load<R>(fetch: (c: ScreenLoadContext<C, P, D>) => MaybePromise<R>): ScreenScope<C, P, Exclude<R, ScreenOutcome>>;
134
+ }
135
+ /** The root: no prefix, no params, nothing loaded. */
136
+ export declare function rootScopeCore<C extends Context>(): ScopeCore<C, Record<never, never>, undefined>;
137
+ export {};
138
+ //# sourceMappingURL=screen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/screen.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * What a chat's screen is, kept where a restart cannot lose it.
3
+ *
4
+ * One record per chat: the view it shows — screen, params, the messages with
5
+ * their fingerprints, the tokens of buttons too long to carry their address —
6
+ * and the remarks waiting to expire. Nothing else: no history, no copy of
7
+ * application data. The record is read through its schema every time, because
8
+ * storage outlives releases and a record written by another version is not
9
+ * evidence of anything.
10
+ *
11
+ * The storage is grammY's own `StorageAdapter`, so any adapter a grammY bot
12
+ * already uses for sessions (`@grammyjs/storage-*`, `MemorySessionStorage` in
13
+ * tests, or ten lines over the application's database) keeps screens too.
14
+ */
15
+ import type { StorageAdapter } from 'grammy';
16
+ import { z } from 'zod';
17
+ /**
18
+ * How much one chat's record may hold. A view is checked against these when it
19
+ * is rendered, before anything reaches Telegram: a record refused after the
20
+ * calls would leave the chat showing messages nothing tracks.
21
+ */
22
+ export declare const RECORD_LIMITS: {
23
+ /** Messages in one view. */
24
+ messages: number;
25
+ /** Characters of a message key. */
26
+ key: number;
27
+ /** Buttons whose address is kept in the record, per view. */
28
+ tokens: number;
29
+ /** Characters of one kept address. */
30
+ tokenBody: number;
31
+ /** Remarks waiting to expire. */
32
+ remarks: number;
33
+ };
34
+ declare const ScreenViewStateSchema: z.ZodObject<{
35
+ screen: z.ZodString;
36
+ params: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
37
+ messages: z.ZodArray<z.ZodObject<{
38
+ key: z.ZodString;
39
+ id: z.ZodNumber;
40
+ kind: z.ZodEnum<{
41
+ animation: "animation";
42
+ audio: "audio";
43
+ document: "document";
44
+ photo: "photo";
45
+ rich: "rich";
46
+ text: "text";
47
+ video: "video";
48
+ }>;
49
+ fingerprint: z.ZodNullable<z.ZodObject<{
50
+ content: z.ZodString;
51
+ media: z.ZodString;
52
+ markup: z.ZodString;
53
+ }, z.core.$strict>>;
54
+ }, z.core.$strict>>;
55
+ tokens: z.ZodRecord<z.ZodString, z.ZodString>;
56
+ }, z.core.$strict>;
57
+ export declare const ScreenChatStateSchema: z.ZodObject<{
58
+ version: z.ZodLiteral<1>;
59
+ view: z.ZodNullable<z.ZodObject<{
60
+ screen: z.ZodString;
61
+ params: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
62
+ messages: z.ZodArray<z.ZodObject<{
63
+ key: z.ZodString;
64
+ id: z.ZodNumber;
65
+ kind: z.ZodEnum<{
66
+ animation: "animation";
67
+ audio: "audio";
68
+ document: "document";
69
+ photo: "photo";
70
+ rich: "rich";
71
+ text: "text";
72
+ video: "video";
73
+ }>;
74
+ fingerprint: z.ZodNullable<z.ZodObject<{
75
+ content: z.ZodString;
76
+ media: z.ZodString;
77
+ markup: z.ZodString;
78
+ }, z.core.$strict>>;
79
+ }, z.core.$strict>>;
80
+ tokens: z.ZodRecord<z.ZodString, z.ZodString>;
81
+ }, z.core.$strict>>;
82
+ expiring: z.ZodArray<z.ZodObject<{
83
+ id: z.ZodNumber;
84
+ at: z.ZodNumber;
85
+ }, z.core.$strict>>;
86
+ }, z.core.$strict>;
87
+ export type ScreenChatState = z.infer<typeof ScreenChatStateSchema>;
88
+ export type ScreenViewState = z.infer<typeof ScreenViewStateSchema>;
89
+ /** Where chats' screen state survives a restart: grammY's storage contract. */
90
+ export type TelegramScreenStorage = StorageAdapter<ScreenChatState>;
91
+ export declare const emptyChatState: () => ScreenChatState;
92
+ export interface ReadChatState {
93
+ readonly state: ScreenChatState;
94
+ /** The stored record did not match the schema and was set aside. */
95
+ readonly discarded: boolean;
96
+ }
97
+ /**
98
+ * The chat's record. A storage that fails to answer fails the update — reading
99
+ * "nothing" would send a message meant as input to whatever handles text next.
100
+ * A record that does not match this release's schema is set aside and
101
+ * reported: refusing it forever would leave the chat without screens.
102
+ */
103
+ export declare function readChatState(storage: TelegramScreenStorage, key: string): Promise<ReadChatState>;
104
+ export declare function writeChatState(storage: TelegramScreenStorage, key: string, state: ScreenChatState): Promise<void>;
105
+ /**
106
+ * One chat at a time, in arrival order. Two presses in one chat are two
107
+ * read-render-write passes over one record; interleaved, the second would draw
108
+ * over messages the first is deleting. A chat's queue is dropped once it
109
+ * drains, and bounded while it has work: a chat that sends faster than
110
+ * Telegram answers is refused rather than queued without end.
111
+ */
112
+ export type ChatQueue = <T>(key: string, task: () => Promise<T>) => Promise<T>;
113
+ export declare function createChatQueue(maxPending: number): ChatQueue;
114
+ export {};
115
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;GAIG;AACH,eAAO,MAAM,aAAa;IACxB,4BAA4B;IAC5B,QAAQ;IACR,mCAAmC;IACnC,GAAG;IACH,6DAA6D;IAC7D,MAAM;IACN,sCAAsC;IACtC,SAAS;IACT,iCAAiC;IACjC,OAAO;CACR,CAAC;AAeF,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;kBAUhB,CAAC;AAMZ,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAOvB,CAAC;AAEZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,+EAA+E;AAC/E,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,eAAe,CAAC,CAAC;AAEpE,eAAO,MAAM,cAAc,QAAO,eAIhC,CAAC;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,qBAAqB,EAC9B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,CAOxB;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,EAC9B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAE/E,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAiB7D"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `telegramScreens<Ctx>()` — where a bot's screens are declared and composed.
3
+ *
4
+ * The bot's grammY context type is named once; every screen, group and handler
5
+ * declared from here sees it. `create` checks the declaration as a whole — ids,
6
+ * paths, that every screen with params has a load above it — and returns the
7
+ * middleware.
8
+ */
9
+ import type { Context } from 'grammy';
10
+ import { type TelegramScreens, type TelegramScreensConfig } from './runtime.js';
11
+ import { ScreenScope } from './screen.js';
12
+ export declare class TelegramScreensRoot<C extends Context> extends ScreenScope<C, Record<never, never>, undefined> {
13
+ /** Compose the declared screens into grammY middleware. */
14
+ create(config: TelegramScreensConfig<C>): TelegramScreens<C>;
15
+ }
16
+ /** Declare a bot's screens against its grammY context type. */
17
+ export declare function telegramScreens<C extends Context>(): TelegramScreensRoot<C>;
18
+ //# sourceMappingURL=telegram-screens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-screens.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/telegram-screens.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC3B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAiB,WAAW,EAAE,MAAM,UAAU,CAAC;AAEtD,qBAAa,mBAAmB,CAAC,CAAC,SAAS,OAAO,CAAE,SAAQ,WAAW,CACrE,CAAC,EACD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EACpB,SAAS,CACV;IACC,2DAA2D;IAC3D,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAE3D;CACF;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAE3E"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The Telegram side of the test chat: the messages it keeps and how it answers
3
+ * the Bot API calls screens make.
4
+ *
5
+ * It keeps the rules screens depend on: an edit that changes nothing is
6
+ * refused as "message is not modified", a deleted message cannot be edited or
7
+ * deleted again, a text message has no caption to edit, a media message no
8
+ * text.
9
+ */
10
+ import type { Chat, InlineKeyboardMarkup, Message, User } from 'grammy/types';
11
+ export type TestMessageKind = 'text' | 'rich' | 'photo' | 'video' | 'animation' | 'document' | 'audio';
12
+ export interface StoredMessage {
13
+ id: number;
14
+ from: 'bot' | 'user';
15
+ kind: TestMessageKind;
16
+ text: string;
17
+ media: string | undefined;
18
+ rich: unknown;
19
+ markup: InlineKeyboardMarkup | undefined;
20
+ deleted: boolean;
21
+ }
22
+ export type TestChatPeer = Chat.PrivateChat | Chat.GroupChat | Chat.SupergroupChat;
23
+ export interface FakeTelegramIdentity {
24
+ readonly chat: TestChatPeer;
25
+ readonly botUser: User;
26
+ readonly user: User;
27
+ }
28
+ export interface FakeTelegramRefusal {
29
+ readonly ok: false;
30
+ readonly error_code: number;
31
+ readonly description: string;
32
+ }
33
+ export interface FakeTelegram {
34
+ /** Every message the chat has had, deleted ones marked. */
35
+ readonly stored: StoredMessage[];
36
+ /** Press answers — the toasts — in order. */
37
+ readonly answers: string[];
38
+ /** A message still in the chat. */
39
+ find(id: unknown): StoredMessage | undefined;
40
+ asTelegram(message: StoredMessage): Message;
41
+ /** A Bot API call answered the way Telegram would. */
42
+ answer(method: string, payload: Readonly<Record<string, unknown>>): unknown;
43
+ refuse(description: string, errorCode?: number): FakeTelegramRefusal;
44
+ nextMessageId(): number;
45
+ }
46
+ export declare function createFakeTelegram({ chat, botUser, user, }: FakeTelegramIdentity): FakeTelegram;
47
+ //# sourceMappingURL=test-chat-telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-chat-telegram.d.ts","sourceRoot":"","sources":["../../../src/telegram/screens/test-chat-telegram.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAK9E,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,MAAM,GACN,OAAO,GACP,OAAO,GACP,WAAW,GACX,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,IAAI,EAAE,eAAe,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC;AAEnF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IACnB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC;IACjC,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAAC;IAC7C,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC;IAC5C,sDAAsD;IACtD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC;IAC5E,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACrE,aAAa,IAAI,MAAM,CAAC;CACzB;AAkID,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,IAAI,GACL,EAAE,oBAAoB,GAAG,YAAY,CAgHrC"}