@yolk-sdk/emulators 0.1.0-canary.96

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 (333) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2135 -0
  3. package/dist/anthropic.d.mts +269 -0
  4. package/dist/anthropic.d.mts.map +1 -0
  5. package/dist/anthropic.mjs +177 -0
  6. package/dist/anthropic.mjs.map +1 -0
  7. package/dist/chat-completions.d.mts +288 -0
  8. package/dist/chat-completions.d.mts.map +1 -0
  9. package/dist/chat-completions.mjs +451 -0
  10. package/dist/chat-completions.mjs.map +1 -0
  11. package/dist/codex.d.mts +265 -0
  12. package/dist/codex.d.mts.map +1 -0
  13. package/dist/codex.mjs +199 -0
  14. package/dist/codex.mjs.map +1 -0
  15. package/dist/dropbox/api.d.mts +63 -0
  16. package/dist/dropbox/api.d.mts.map +1 -0
  17. package/dist/dropbox/api.mjs +565 -0
  18. package/dist/dropbox/api.mjs.map +1 -0
  19. package/dist/dropbox/state.d.mts +136 -0
  20. package/dist/dropbox/state.d.mts.map +1 -0
  21. package/dist/dropbox/state.mjs +209 -0
  22. package/dist/dropbox/state.mjs.map +1 -0
  23. package/dist/dropbox.d.mts +79 -0
  24. package/dist/dropbox.d.mts.map +1 -0
  25. package/dist/dropbox.mjs +124 -0
  26. package/dist/dropbox.mjs.map +1 -0
  27. package/dist/email-fixtures.d.mts +36 -0
  28. package/dist/email-fixtures.d.mts.map +1 -0
  29. package/dist/email-fixtures.mjs +1080 -0
  30. package/dist/email-fixtures.mjs.map +1 -0
  31. package/dist/email.d.mts +160 -0
  32. package/dist/email.d.mts.map +1 -0
  33. package/dist/email.mjs +608 -0
  34. package/dist/email.mjs.map +1 -0
  35. package/dist/emulator-compose.d.mts +40 -0
  36. package/dist/emulator-compose.d.mts.map +1 -0
  37. package/dist/emulator-compose.mjs +91 -0
  38. package/dist/emulator-compose.mjs.map +1 -0
  39. package/dist/emulator-http.d.mts +53 -0
  40. package/dist/emulator-http.d.mts.map +1 -0
  41. package/dist/emulator-http.mjs +117 -0
  42. package/dist/emulator-http.mjs.map +1 -0
  43. package/dist/emulator-kernel.d.mts +176 -0
  44. package/dist/emulator-kernel.d.mts.map +1 -0
  45. package/dist/emulator-kernel.mjs +413 -0
  46. package/dist/emulator-kernel.mjs.map +1 -0
  47. package/dist/fixture-route.d.mts +129 -0
  48. package/dist/fixture-route.d.mts.map +1 -0
  49. package/dist/fixture-route.mjs +257 -0
  50. package/dist/fixture-route.mjs.map +1 -0
  51. package/dist/fortnox/api.d.mts +92 -0
  52. package/dist/fortnox/api.d.mts.map +1 -0
  53. package/dist/fortnox/api.mjs +750 -0
  54. package/dist/fortnox/api.mjs.map +1 -0
  55. package/dist/fortnox/state.d.mts +533 -0
  56. package/dist/fortnox/state.d.mts.map +1 -0
  57. package/dist/fortnox/state.mjs +612 -0
  58. package/dist/fortnox/state.mjs.map +1 -0
  59. package/dist/fortnox.d.mts +128 -0
  60. package/dist/fortnox.d.mts.map +1 -0
  61. package/dist/fortnox.mjs +403 -0
  62. package/dist/fortnox.mjs.map +1 -0
  63. package/dist/gateway-evaluate-recordings.d.mts +12 -0
  64. package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
  65. package/dist/gateway-evaluate-recordings.mjs +128 -0
  66. package/dist/gateway-evaluate-recordings.mjs.map +1 -0
  67. package/dist/gateway.d.mts +272 -0
  68. package/dist/gateway.d.mts.map +1 -0
  69. package/dist/gateway.mjs +400 -0
  70. package/dist/gateway.mjs.map +1 -0
  71. package/dist/github/api.d.mts +63 -0
  72. package/dist/github/api.d.mts.map +1 -0
  73. package/dist/github/api.mjs +527 -0
  74. package/dist/github/api.mjs.map +1 -0
  75. package/dist/github/state.d.mts +272 -0
  76. package/dist/github/state.d.mts.map +1 -0
  77. package/dist/github/state.mjs +303 -0
  78. package/dist/github/state.mjs.map +1 -0
  79. package/dist/github.d.mts +77 -0
  80. package/dist/github.d.mts.map +1 -0
  81. package/dist/github.mjs +180 -0
  82. package/dist/github.mjs.map +1 -0
  83. package/dist/google/calendar.d.mts +10 -0
  84. package/dist/google/calendar.d.mts.map +1 -0
  85. package/dist/google/calendar.mjs +252 -0
  86. package/dist/google/calendar.mjs.map +1 -0
  87. package/dist/google/drive.d.mts +8 -0
  88. package/dist/google/drive.d.mts.map +1 -0
  89. package/dist/google/drive.mjs +252 -0
  90. package/dist/google/drive.mjs.map +1 -0
  91. package/dist/google/gmail.d.mts +10 -0
  92. package/dist/google/gmail.d.mts.map +1 -0
  93. package/dist/google/gmail.mjs +591 -0
  94. package/dist/google/gmail.mjs.map +1 -0
  95. package/dist/google/shared.d.mts +107 -0
  96. package/dist/google/shared.d.mts.map +1 -0
  97. package/dist/google/shared.mjs +146 -0
  98. package/dist/google/shared.mjs.map +1 -0
  99. package/dist/google/state.d.mts +385 -0
  100. package/dist/google/state.d.mts.map +1 -0
  101. package/dist/google/state.mjs +496 -0
  102. package/dist/google/state.mjs.map +1 -0
  103. package/dist/google.d.mts +75 -0
  104. package/dist/google.d.mts.map +1 -0
  105. package/dist/google.mjs +210 -0
  106. package/dist/google.mjs.map +1 -0
  107. package/dist/linkedin-search/api.d.mts +45 -0
  108. package/dist/linkedin-search/api.d.mts.map +1 -0
  109. package/dist/linkedin-search/api.mjs +181 -0
  110. package/dist/linkedin-search/api.mjs.map +1 -0
  111. package/dist/linkedin-search/state.d.mts +123 -0
  112. package/dist/linkedin-search/state.d.mts.map +1 -0
  113. package/dist/linkedin-search/state.mjs +261 -0
  114. package/dist/linkedin-search/state.mjs.map +1 -0
  115. package/dist/linkedin-search.d.mts +69 -0
  116. package/dist/linkedin-search.d.mts.map +1 -0
  117. package/dist/linkedin-search.mjs +158 -0
  118. package/dist/linkedin-search.mjs.map +1 -0
  119. package/dist/mcp/api.d.mts +44 -0
  120. package/dist/mcp/api.d.mts.map +1 -0
  121. package/dist/mcp/api.mjs +557 -0
  122. package/dist/mcp/api.mjs.map +1 -0
  123. package/dist/mcp/recordings.d.mts +40 -0
  124. package/dist/mcp/recordings.d.mts.map +1 -0
  125. package/dist/mcp/recordings.mjs +2390 -0
  126. package/dist/mcp/recordings.mjs.map +1 -0
  127. package/dist/mcp/state.d.mts +71 -0
  128. package/dist/mcp/state.d.mts.map +1 -0
  129. package/dist/mcp/state.mjs +83 -0
  130. package/dist/mcp/state.mjs.map +1 -0
  131. package/dist/mcp.d.mts +84 -0
  132. package/dist/mcp.d.mts.map +1 -0
  133. package/dist/mcp.mjs +241 -0
  134. package/dist/mcp.mjs.map +1 -0
  135. package/dist/messages.d.mts +183 -0
  136. package/dist/messages.d.mts.map +1 -0
  137. package/dist/messages.mjs +532 -0
  138. package/dist/messages.mjs.map +1 -0
  139. package/dist/microsoft/api.d.mts +47 -0
  140. package/dist/microsoft/api.d.mts.map +1 -0
  141. package/dist/microsoft/api.mjs +178 -0
  142. package/dist/microsoft/api.mjs.map +1 -0
  143. package/dist/microsoft/calendar.d.mts +30 -0
  144. package/dist/microsoft/calendar.d.mts.map +1 -0
  145. package/dist/microsoft/calendar.mjs +271 -0
  146. package/dist/microsoft/calendar.mjs.map +1 -0
  147. package/dist/microsoft/drive.d.mts +36 -0
  148. package/dist/microsoft/drive.d.mts.map +1 -0
  149. package/dist/microsoft/drive.mjs +298 -0
  150. package/dist/microsoft/drive.mjs.map +1 -0
  151. package/dist/microsoft/graph.d.mts +198 -0
  152. package/dist/microsoft/graph.d.mts.map +1 -0
  153. package/dist/microsoft/graph.mjs +264 -0
  154. package/dist/microsoft/graph.mjs.map +1 -0
  155. package/dist/microsoft/mail.d.mts +48 -0
  156. package/dist/microsoft/mail.d.mts.map +1 -0
  157. package/dist/microsoft/mail.mjs +488 -0
  158. package/dist/microsoft/mail.mjs.map +1 -0
  159. package/dist/microsoft/state.d.mts +480 -0
  160. package/dist/microsoft/state.d.mts.map +1 -0
  161. package/dist/microsoft/state.mjs +625 -0
  162. package/dist/microsoft/state.mjs.map +1 -0
  163. package/dist/microsoft.d.mts +168 -0
  164. package/dist/microsoft.d.mts.map +1 -0
  165. package/dist/microsoft.mjs +483 -0
  166. package/dist/microsoft.mjs.map +1 -0
  167. package/dist/node.d.mts +47 -0
  168. package/dist/node.d.mts.map +1 -0
  169. package/dist/node.mjs +178 -0
  170. package/dist/node.mjs.map +1 -0
  171. package/dist/notion/api.d.mts +51 -0
  172. package/dist/notion/api.d.mts.map +1 -0
  173. package/dist/notion/api.mjs +507 -0
  174. package/dist/notion/api.mjs.map +1 -0
  175. package/dist/notion/state.d.mts +329 -0
  176. package/dist/notion/state.d.mts.map +1 -0
  177. package/dist/notion/state.mjs +432 -0
  178. package/dist/notion/state.mjs.map +1 -0
  179. package/dist/notion.d.mts +72 -0
  180. package/dist/notion.d.mts.map +1 -0
  181. package/dist/notion.mjs +127 -0
  182. package/dist/notion.mjs.map +1 -0
  183. package/dist/openai.d.mts +165 -0
  184. package/dist/openai.d.mts.map +1 -0
  185. package/dist/openai.mjs +141 -0
  186. package/dist/openai.mjs.map +1 -0
  187. package/dist/opencode-recordings.d.mts +7 -0
  188. package/dist/opencode-recordings.d.mts.map +1 -0
  189. package/dist/opencode-recordings.mjs +222 -0
  190. package/dist/opencode-recordings.mjs.map +1 -0
  191. package/dist/opencode.d.mts +70 -0
  192. package/dist/opencode.d.mts.map +1 -0
  193. package/dist/opencode.mjs +217 -0
  194. package/dist/opencode.mjs.map +1 -0
  195. package/dist/r2-fixtures.d.mts +36 -0
  196. package/dist/r2-fixtures.d.mts.map +1 -0
  197. package/dist/r2-fixtures.mjs +245 -0
  198. package/dist/r2-fixtures.mjs.map +1 -0
  199. package/dist/r2-guard.d.mts +43 -0
  200. package/dist/r2-guard.d.mts.map +1 -0
  201. package/dist/r2-guard.mjs +215 -0
  202. package/dist/r2-guard.mjs.map +1 -0
  203. package/dist/r2.d.mts +166 -0
  204. package/dist/r2.d.mts.map +1 -0
  205. package/dist/r2.mjs +517 -0
  206. package/dist/r2.mjs.map +1 -0
  207. package/dist/responses.d.mts +231 -0
  208. package/dist/responses.d.mts.map +1 -0
  209. package/dist/responses.mjs +556 -0
  210. package/dist/responses.mjs.map +1 -0
  211. package/dist/route-evidence.d.mts +45 -0
  212. package/dist/route-evidence.d.mts.map +1 -0
  213. package/dist/route-evidence.mjs +56 -0
  214. package/dist/route-evidence.mjs.map +1 -0
  215. package/dist/router.d.mts +93 -0
  216. package/dist/router.d.mts.map +1 -0
  217. package/dist/router.mjs +259 -0
  218. package/dist/router.mjs.map +1 -0
  219. package/dist/stateful-core.d.mts +17 -0
  220. package/dist/stateful-core.d.mts.map +1 -0
  221. package/dist/stateful-core.mjs +41 -0
  222. package/dist/stateful-core.mjs.map +1 -0
  223. package/dist/stateful-emulator.d.mts +565 -0
  224. package/dist/stateful-emulator.d.mts.map +1 -0
  225. package/dist/stateful-emulator.mjs +1228 -0
  226. package/dist/stateful-emulator.mjs.map +1 -0
  227. package/dist/stateful-secrets.d.mts +84 -0
  228. package/dist/stateful-secrets.d.mts.map +1 -0
  229. package/dist/stateful-secrets.mjs +216 -0
  230. package/dist/stateful-secrets.mjs.map +1 -0
  231. package/dist/subscription-usage-recordings.d.mts +9 -0
  232. package/dist/subscription-usage-recordings.d.mts.map +1 -0
  233. package/dist/subscription-usage-recordings.mjs +53 -0
  234. package/dist/subscription-usage-recordings.mjs.map +1 -0
  235. package/dist/subscription-usage.d.mts +53 -0
  236. package/dist/subscription-usage.d.mts.map +1 -0
  237. package/dist/subscription-usage.mjs +21 -0
  238. package/dist/subscription-usage.mjs.map +1 -0
  239. package/dist/telegram/api.d.mts +34 -0
  240. package/dist/telegram/api.d.mts.map +1 -0
  241. package/dist/telegram/api.mjs +257 -0
  242. package/dist/telegram/api.mjs.map +1 -0
  243. package/dist/telegram/state.d.mts +128 -0
  244. package/dist/telegram/state.d.mts.map +1 -0
  245. package/dist/telegram/state.mjs +154 -0
  246. package/dist/telegram/state.mjs.map +1 -0
  247. package/dist/telegram.d.mts +62 -0
  248. package/dist/telegram.d.mts.map +1 -0
  249. package/dist/telegram.mjs +127 -0
  250. package/dist/telegram.mjs.map +1 -0
  251. package/dist/todoist/api.d.mts +55 -0
  252. package/dist/todoist/api.d.mts.map +1 -0
  253. package/dist/todoist/api.mjs +415 -0
  254. package/dist/todoist/api.mjs.map +1 -0
  255. package/dist/todoist/state.d.mts +275 -0
  256. package/dist/todoist/state.d.mts.map +1 -0
  257. package/dist/todoist/state.mjs +345 -0
  258. package/dist/todoist/state.mjs.map +1 -0
  259. package/dist/todoist.d.mts +68 -0
  260. package/dist/todoist.d.mts.map +1 -0
  261. package/dist/todoist.mjs +181 -0
  262. package/dist/todoist.mjs.map +1 -0
  263. package/dist/xai.d.mts +267 -0
  264. package/dist/xai.d.mts.map +1 -0
  265. package/dist/xai.mjs +252 -0
  266. package/dist/xai.mjs.map +1 -0
  267. package/package.json +157 -0
  268. package/src/anthropic.ts +289 -0
  269. package/src/chat-completions.ts +924 -0
  270. package/src/codex.ts +296 -0
  271. package/src/dropbox/api.ts +1084 -0
  272. package/src/dropbox/state.ts +364 -0
  273. package/src/dropbox.ts +203 -0
  274. package/src/email-fixtures.ts +1297 -0
  275. package/src/email.ts +1108 -0
  276. package/src/emulator-compose.ts +147 -0
  277. package/src/emulator-http.ts +184 -0
  278. package/src/emulator-kernel.ts +844 -0
  279. package/src/fixture-route.ts +561 -0
  280. package/src/fortnox/api.ts +1352 -0
  281. package/src/fortnox/state.ts +798 -0
  282. package/src/fortnox.ts +801 -0
  283. package/src/gateway-evaluate-recordings.ts +153 -0
  284. package/src/gateway.ts +530 -0
  285. package/src/github/api.ts +986 -0
  286. package/src/github/state.ts +439 -0
  287. package/src/github.ts +271 -0
  288. package/src/google/calendar.ts +486 -0
  289. package/src/google/drive.ts +471 -0
  290. package/src/google/gmail.ts +1011 -0
  291. package/src/google/shared.ts +321 -0
  292. package/src/google/state.ts +686 -0
  293. package/src/google.ts +298 -0
  294. package/src/linkedin-search/api.ts +363 -0
  295. package/src/linkedin-search/state.ts +373 -0
  296. package/src/linkedin-search.ts +241 -0
  297. package/src/mcp/api.ts +995 -0
  298. package/src/mcp/recordings.ts +2665 -0
  299. package/src/mcp/state.ts +125 -0
  300. package/src/mcp.ts +319 -0
  301. package/src/messages.ts +844 -0
  302. package/src/microsoft/api.ts +426 -0
  303. package/src/microsoft/calendar.ts +491 -0
  304. package/src/microsoft/drive.ts +541 -0
  305. package/src/microsoft/graph.ts +550 -0
  306. package/src/microsoft/mail.ts +833 -0
  307. package/src/microsoft/state.ts +822 -0
  308. package/src/microsoft.ts +982 -0
  309. package/src/node.ts +293 -0
  310. package/src/notion/api.ts +976 -0
  311. package/src/notion/state.ts +512 -0
  312. package/src/notion.ts +210 -0
  313. package/src/openai.ts +198 -0
  314. package/src/opencode-recordings.ts +257 -0
  315. package/src/opencode.ts +271 -0
  316. package/src/r2-fixtures.ts +295 -0
  317. package/src/r2-guard.ts +323 -0
  318. package/src/r2.ts +890 -0
  319. package/src/responses.ts +901 -0
  320. package/src/route-evidence.ts +90 -0
  321. package/src/router.ts +490 -0
  322. package/src/stateful-core.ts +70 -0
  323. package/src/stateful-emulator.ts +2571 -0
  324. package/src/stateful-secrets.ts +299 -0
  325. package/src/subscription-usage-recordings.ts +77 -0
  326. package/src/subscription-usage.ts +68 -0
  327. package/src/telegram/api.ts +437 -0
  328. package/src/telegram/state.ts +229 -0
  329. package/src/telegram.ts +227 -0
  330. package/src/todoist/api.ts +736 -0
  331. package/src/todoist/state.ts +456 -0
  332. package/src/todoist.ts +316 -0
  333. package/src/xai.ts +341 -0
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Stateful Telegram Bot API emulator (`https://api.telegram.org`), built on the upstream
3
+ * `@emulators/core` custom runtime, with a request ledger, status faults, and an `/_emulate/*`
4
+ * control plane.
5
+ *
6
+ * Fixture-only: it never imports SDK code; its wire shapes and default seed are copied as data
7
+ * from the synthetic Telegram conformance fixtures, and every route names the conformance cases it
8
+ * follows in `telegramEmulatorRoutes`. Only the routes the four Telegram cases need are emulated
9
+ * (`getChat`, `getFile`, the hosted file download, `sendMessage`); anything the fixtures do not
10
+ * record answers one ledgered 400 `{ error: { type: 'not_emulated', message } }`.
11
+ *
12
+ * The bot token travels in the URL path (`/bot<token>/<method>`). It is required but never checked
13
+ * against a value, stored, forwarded to the core, ledgered, or echoed. Resolution fails closed: a
14
+ * request is recognised only when its raw path is exactly an emulated route shape
15
+ * (`/bot<token>/<method>` or `/file/bot<token>/<file_path>`, the strict token on the raw segment,
16
+ * an emulated method, no other path text); the token is taken from that exact segment. Every other
17
+ * request is ledgered and answered with constant text only (`/<unrecognised>`, a standard method or
18
+ * `<other>`, no query or body, a constant reason). For a recognised request, the ledgered method,
19
+ * path (`/bot<redacted>/...`), query keys and values, and every not-emulated message are scrubbed
20
+ * of the token and its secret part, and a query, remaining path, or body that repeats either (raw,
21
+ * percent-decoded, or in any parsed JSON key, string value, or number) is refused with constant
22
+ * text. A token whose bot id is `0` names no bot: `getChat` answers the recorded 401.
23
+ *
24
+ * `sendMessage` is irreversible on the real service; the emulator records each sent message in its
25
+ * state (`sentMessages`) and never delivers anything.
26
+ *
27
+ * Request-shape latitude (the only accepted deviations from the fixture requests): any credential
28
+ * value of at least 8 characters that occurs nowhere else in the request (its path, query, or body;
29
+ * never checked against anything, stored, or ledgered); extra request headers; `content-type`
30
+ * parameters; a well-formed `<digits>:<secret>` bot token with a secret of at least 8 characters
31
+ * (the bot id `0` names no bot); any well-formed `chat_id` string (an integer or a public
32
+ * `@username`; one the bot is not in answers the recorded 400 on `getChat`); any non-empty message
33
+ * `text`.
34
+ *
35
+ * Node-only: `@emulators/core` imports Node builtins, so the core is loaded lazily by
36
+ * `makeTelegramEmulator` (importing this module has no side effects).
37
+ *
38
+ * @experimental
39
+ */
40
+ import { Data, Predicate } from 'effect'
41
+ import type { EmulatorRouteEvidence } from './route-evidence.ts'
42
+ import { statefulCoreRuntime } from './stateful-core.ts'
43
+ import {
44
+ makeHeaderlessStatefulEmulator,
45
+ routeEvidence,
46
+ type StatefulCoverage,
47
+ type StatefulErrorTexts,
48
+ type StatefulFault,
49
+ type StatefulFaultState,
50
+ type StatefulHeaderlessLedgerEntry,
51
+ type StatefulInputKind
52
+ } from './stateful-emulator.ts'
53
+ import {
54
+ resolveTelegramRequest,
55
+ telegramApiRoutes,
56
+ type TelegramApiEnv,
57
+ type TelegramEmulatorDrills
58
+ } from './telegram/api.ts'
59
+ import {
60
+ buildTelegramSeedState,
61
+ decodeTelegramState,
62
+ type TelegramEmulatorSeed,
63
+ type TelegramEmulatorState
64
+ } from './telegram/state.ts'
65
+
66
+ export type { EmulatorEvidence, EmulatorRouteEvidence } from './route-evidence.ts'
67
+
68
+ export { emulatorEvidenceHeader } from './route-evidence.ts'
69
+
70
+ export {
71
+ StatefulFault as TelegramFault,
72
+ StatefulFaultMatch as TelegramFaultMatch
73
+ } from './stateful-emulator.ts'
74
+
75
+ export type { TelegramEmulatorDrills } from './telegram/api.ts'
76
+
77
+ export {
78
+ TelegramEmulatorBot,
79
+ TelegramEmulatorChat,
80
+ TelegramEmulatorFile,
81
+ TelegramEmulatorProfile,
82
+ TelegramEmulatorSeed,
83
+ TelegramEmulatorSentMessage,
84
+ TelegramEmulatorStateSchema,
85
+ type TelegramEmulatorState
86
+ } from './telegram/state.ts'
87
+
88
+ /** Origin the connector calls (Bot API methods and hosted file downloads). */
89
+ export const telegramEmulatorDefaultOrigin = 'https://api.telegram.org'
90
+
91
+ /**
92
+ * Route evidence manifest: every emulated route, whether it writes, and the conformance cases
93
+ * whose (currently synthetic, unverified) wire claims it follows. `{token}` stands for the bot
94
+ * token path segment, which is never recorded.
95
+ */
96
+ export const telegramEmulatorRoutes: ReadonlyArray<EmulatorRouteEvidence> = telegramApiRoutes.map(
97
+ ({ route }) => routeEvidence(route)
98
+ )
99
+
100
+ export type TelegramFaultState = StatefulFaultState
101
+
102
+ export type TelegramLedgerEntry = StatefulHeaderlessLedgerEntry
103
+
104
+ export type TelegramCoverage = StatefulCoverage
105
+
106
+ /** Invalid emulator input from the JS API: a seed or a fault. A programmer error. */
107
+ export class TelegramEmulatorInputInvalid extends Data.TaggedError('TelegramEmulatorInputInvalid')<{
108
+ readonly input: 'seed' | 'fault'
109
+ readonly reason: string
110
+ }> {
111
+ override get message(): string {
112
+ return `Invalid Telegram emulator ${this.input}: ${this.reason}`
113
+ }
114
+ }
115
+
116
+ export type TelegramEmulatorOptions = {
117
+ /** Typed seed; defaults to the fixture entities (`profile: 'default'`). */
118
+ readonly seed?: TelegramEmulatorSeed
119
+ /** Clock in epoch milliseconds (`date` of sent messages). Defaults to `Date.now`. */
120
+ readonly now?: () => number
121
+ /** Drill knobs (tests only): make the emulator disagree with one conformance claim. */
122
+ readonly drills?: TelegramEmulatorDrills
123
+ }
124
+
125
+ export type TelegramEmulator = {
126
+ /** The fetch handler (Bot API routes, file downloads, and `/_emulate/*`). Never rejects. */
127
+ readonly fetch: (request: Request) => Promise<Response>
128
+ readonly ledger: {
129
+ readonly entries: () => ReadonlyArray<TelegramLedgerEntry>
130
+ readonly clear: () => void
131
+ }
132
+ readonly faults: {
133
+ /** Add a fault; throws `TelegramEmulatorInputInvalid` for an invalid fault. */
134
+ readonly add: (fault: StatefulFault) => TelegramFaultState
135
+ readonly list: () => ReadonlyArray<TelegramFaultState>
136
+ readonly clear: () => void
137
+ }
138
+ /** Restore the current seed (dropping sent messages) and clear the ledger and faults. */
139
+ readonly reset: () => Promise<void>
140
+ /**
141
+ * Replace the state with a new seed, which becomes what `reset` restores. Rejects with
142
+ * `TelegramEmulatorInputInvalid` for an invalid seed.
143
+ */
144
+ readonly seed: (seed: TelegramEmulatorSeed) => Promise<void>
145
+ /** A deep copy of the current state (entities, sent messages, and the message counter). */
146
+ readonly snapshot: () => TelegramEmulatorState
147
+ readonly coverage: () => TelegramCoverage
148
+ /** Close the core runtime. Later requests answer 503. Idempotent. */
149
+ readonly close: () => Promise<void>
150
+ }
151
+
152
+ /** The texts of Telegram's recovery answers (500 failed, 503 closed, 500 unhandled). */
153
+ const errorTexts: StatefulErrorTexts = {
154
+ failed: 'Synthetic: the emulator could not build the response.',
155
+ closed: 'Synthetic: the emulator is closed.',
156
+ unhandled: 'emulator failed to handle the request'
157
+ }
158
+
159
+ /** The wrapper reports invalid seeds and faults only (Telegram takes no other option input). */
160
+ const inputInvalid = (input: StatefulInputKind, reason: string) =>
161
+ new TelegramEmulatorInputInvalid({ input: input === 'seed' ? 'seed' : 'fault', reason })
162
+
163
+ /**
164
+ * Create a stateful Telegram Bot API emulator on the `@emulators/core` custom runtime. Each call
165
+ * has its own state, ledger, and faults. Rejects with `TelegramEmulatorInputInvalid` for an
166
+ * invalid seed. See `README.md` (Telegram emulator) for the wire claims.
167
+ */
168
+ export const makeTelegramEmulator = async (
169
+ options: TelegramEmulatorOptions = {}
170
+ ): Promise<TelegramEmulator> => {
171
+ const initial = buildTelegramSeedState(options.seed ?? {})
172
+
173
+ if (Predicate.isString(initial)) {
174
+ throw new TelegramEmulatorInputInvalid({ input: 'seed', reason: initial })
175
+ }
176
+
177
+ const drills = options.drills ?? {}
178
+
179
+ const env: TelegramApiEnv = {
180
+ now: options.now ?? (() => Date.now()),
181
+ drills: {
182
+ getChatOkFalse: drills.getChatOkFalse ?? false,
183
+ errorsAs200: drills.errorsAs200 ?? false,
184
+ fileSizeOffByOne: drills.fileSizeOffByOne ?? false,
185
+ sendOkFalse: drills.sendOkFalse ?? false
186
+ }
187
+ }
188
+
189
+ const emulator = await makeHeaderlessStatefulEmulator<
190
+ TelegramEmulatorState,
191
+ TelegramApiEnv,
192
+ TelegramEmulatorSeed
193
+ >(
194
+ {
195
+ routes: telegramApiRoutes.map(({ route }) => route),
196
+ env,
197
+ initial,
198
+ buildSeed: buildTelegramSeedState,
199
+ resolveRequest: resolveTelegramRequest,
200
+ errorTexts,
201
+ clearRuntime: () => undefined,
202
+ runtimeState: () => ({ runtime: {} }),
203
+ seedSummary: state => ({
204
+ chats: state.chats.length,
205
+ files: state.files.length
206
+ }),
207
+ inputInvalid
208
+ },
209
+ statefulCoreRuntime({
210
+ name: 'telegram',
211
+ initial,
212
+ decodeState: decodeTelegramState,
213
+ inputInvalid
214
+ })
215
+ )
216
+
217
+ return {
218
+ fetch: emulator.fetch,
219
+ ledger: emulator.ledger,
220
+ faults: emulator.faults,
221
+ reset: emulator.reset,
222
+ seed: emulator.seed,
223
+ snapshot: emulator.snapshot,
224
+ coverage: emulator.coverage,
225
+ close: emulator.close
226
+ }
227
+ }