@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.
- package/LICENSE +21 -0
- package/README.md +2135 -0
- package/dist/anthropic.d.mts +269 -0
- package/dist/anthropic.d.mts.map +1 -0
- package/dist/anthropic.mjs +177 -0
- package/dist/anthropic.mjs.map +1 -0
- package/dist/chat-completions.d.mts +288 -0
- package/dist/chat-completions.d.mts.map +1 -0
- package/dist/chat-completions.mjs +451 -0
- package/dist/chat-completions.mjs.map +1 -0
- package/dist/codex.d.mts +265 -0
- package/dist/codex.d.mts.map +1 -0
- package/dist/codex.mjs +199 -0
- package/dist/codex.mjs.map +1 -0
- package/dist/dropbox/api.d.mts +63 -0
- package/dist/dropbox/api.d.mts.map +1 -0
- package/dist/dropbox/api.mjs +565 -0
- package/dist/dropbox/api.mjs.map +1 -0
- package/dist/dropbox/state.d.mts +136 -0
- package/dist/dropbox/state.d.mts.map +1 -0
- package/dist/dropbox/state.mjs +209 -0
- package/dist/dropbox/state.mjs.map +1 -0
- package/dist/dropbox.d.mts +79 -0
- package/dist/dropbox.d.mts.map +1 -0
- package/dist/dropbox.mjs +124 -0
- package/dist/dropbox.mjs.map +1 -0
- package/dist/email-fixtures.d.mts +36 -0
- package/dist/email-fixtures.d.mts.map +1 -0
- package/dist/email-fixtures.mjs +1080 -0
- package/dist/email-fixtures.mjs.map +1 -0
- package/dist/email.d.mts +160 -0
- package/dist/email.d.mts.map +1 -0
- package/dist/email.mjs +608 -0
- package/dist/email.mjs.map +1 -0
- package/dist/emulator-compose.d.mts +40 -0
- package/dist/emulator-compose.d.mts.map +1 -0
- package/dist/emulator-compose.mjs +91 -0
- package/dist/emulator-compose.mjs.map +1 -0
- package/dist/emulator-http.d.mts +53 -0
- package/dist/emulator-http.d.mts.map +1 -0
- package/dist/emulator-http.mjs +117 -0
- package/dist/emulator-http.mjs.map +1 -0
- package/dist/emulator-kernel.d.mts +176 -0
- package/dist/emulator-kernel.d.mts.map +1 -0
- package/dist/emulator-kernel.mjs +413 -0
- package/dist/emulator-kernel.mjs.map +1 -0
- package/dist/fixture-route.d.mts +129 -0
- package/dist/fixture-route.d.mts.map +1 -0
- package/dist/fixture-route.mjs +257 -0
- package/dist/fixture-route.mjs.map +1 -0
- package/dist/fortnox/api.d.mts +92 -0
- package/dist/fortnox/api.d.mts.map +1 -0
- package/dist/fortnox/api.mjs +750 -0
- package/dist/fortnox/api.mjs.map +1 -0
- package/dist/fortnox/state.d.mts +533 -0
- package/dist/fortnox/state.d.mts.map +1 -0
- package/dist/fortnox/state.mjs +612 -0
- package/dist/fortnox/state.mjs.map +1 -0
- package/dist/fortnox.d.mts +128 -0
- package/dist/fortnox.d.mts.map +1 -0
- package/dist/fortnox.mjs +403 -0
- package/dist/fortnox.mjs.map +1 -0
- package/dist/gateway-evaluate-recordings.d.mts +12 -0
- package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
- package/dist/gateway-evaluate-recordings.mjs +128 -0
- package/dist/gateway-evaluate-recordings.mjs.map +1 -0
- package/dist/gateway.d.mts +272 -0
- package/dist/gateway.d.mts.map +1 -0
- package/dist/gateway.mjs +400 -0
- package/dist/gateway.mjs.map +1 -0
- package/dist/github/api.d.mts +63 -0
- package/dist/github/api.d.mts.map +1 -0
- package/dist/github/api.mjs +527 -0
- package/dist/github/api.mjs.map +1 -0
- package/dist/github/state.d.mts +272 -0
- package/dist/github/state.d.mts.map +1 -0
- package/dist/github/state.mjs +303 -0
- package/dist/github/state.mjs.map +1 -0
- package/dist/github.d.mts +77 -0
- package/dist/github.d.mts.map +1 -0
- package/dist/github.mjs +180 -0
- package/dist/github.mjs.map +1 -0
- package/dist/google/calendar.d.mts +10 -0
- package/dist/google/calendar.d.mts.map +1 -0
- package/dist/google/calendar.mjs +252 -0
- package/dist/google/calendar.mjs.map +1 -0
- package/dist/google/drive.d.mts +8 -0
- package/dist/google/drive.d.mts.map +1 -0
- package/dist/google/drive.mjs +252 -0
- package/dist/google/drive.mjs.map +1 -0
- package/dist/google/gmail.d.mts +10 -0
- package/dist/google/gmail.d.mts.map +1 -0
- package/dist/google/gmail.mjs +591 -0
- package/dist/google/gmail.mjs.map +1 -0
- package/dist/google/shared.d.mts +107 -0
- package/dist/google/shared.d.mts.map +1 -0
- package/dist/google/shared.mjs +146 -0
- package/dist/google/shared.mjs.map +1 -0
- package/dist/google/state.d.mts +385 -0
- package/dist/google/state.d.mts.map +1 -0
- package/dist/google/state.mjs +496 -0
- package/dist/google/state.mjs.map +1 -0
- package/dist/google.d.mts +75 -0
- package/dist/google.d.mts.map +1 -0
- package/dist/google.mjs +210 -0
- package/dist/google.mjs.map +1 -0
- package/dist/linkedin-search/api.d.mts +45 -0
- package/dist/linkedin-search/api.d.mts.map +1 -0
- package/dist/linkedin-search/api.mjs +181 -0
- package/dist/linkedin-search/api.mjs.map +1 -0
- package/dist/linkedin-search/state.d.mts +123 -0
- package/dist/linkedin-search/state.d.mts.map +1 -0
- package/dist/linkedin-search/state.mjs +261 -0
- package/dist/linkedin-search/state.mjs.map +1 -0
- package/dist/linkedin-search.d.mts +69 -0
- package/dist/linkedin-search.d.mts.map +1 -0
- package/dist/linkedin-search.mjs +158 -0
- package/dist/linkedin-search.mjs.map +1 -0
- package/dist/mcp/api.d.mts +44 -0
- package/dist/mcp/api.d.mts.map +1 -0
- package/dist/mcp/api.mjs +557 -0
- package/dist/mcp/api.mjs.map +1 -0
- package/dist/mcp/recordings.d.mts +40 -0
- package/dist/mcp/recordings.d.mts.map +1 -0
- package/dist/mcp/recordings.mjs +2390 -0
- package/dist/mcp/recordings.mjs.map +1 -0
- package/dist/mcp/state.d.mts +71 -0
- package/dist/mcp/state.d.mts.map +1 -0
- package/dist/mcp/state.mjs +83 -0
- package/dist/mcp/state.mjs.map +1 -0
- package/dist/mcp.d.mts +84 -0
- package/dist/mcp.d.mts.map +1 -0
- package/dist/mcp.mjs +241 -0
- package/dist/mcp.mjs.map +1 -0
- package/dist/messages.d.mts +183 -0
- package/dist/messages.d.mts.map +1 -0
- package/dist/messages.mjs +532 -0
- package/dist/messages.mjs.map +1 -0
- package/dist/microsoft/api.d.mts +47 -0
- package/dist/microsoft/api.d.mts.map +1 -0
- package/dist/microsoft/api.mjs +178 -0
- package/dist/microsoft/api.mjs.map +1 -0
- package/dist/microsoft/calendar.d.mts +30 -0
- package/dist/microsoft/calendar.d.mts.map +1 -0
- package/dist/microsoft/calendar.mjs +271 -0
- package/dist/microsoft/calendar.mjs.map +1 -0
- package/dist/microsoft/drive.d.mts +36 -0
- package/dist/microsoft/drive.d.mts.map +1 -0
- package/dist/microsoft/drive.mjs +298 -0
- package/dist/microsoft/drive.mjs.map +1 -0
- package/dist/microsoft/graph.d.mts +198 -0
- package/dist/microsoft/graph.d.mts.map +1 -0
- package/dist/microsoft/graph.mjs +264 -0
- package/dist/microsoft/graph.mjs.map +1 -0
- package/dist/microsoft/mail.d.mts +48 -0
- package/dist/microsoft/mail.d.mts.map +1 -0
- package/dist/microsoft/mail.mjs +488 -0
- package/dist/microsoft/mail.mjs.map +1 -0
- package/dist/microsoft/state.d.mts +480 -0
- package/dist/microsoft/state.d.mts.map +1 -0
- package/dist/microsoft/state.mjs +625 -0
- package/dist/microsoft/state.mjs.map +1 -0
- package/dist/microsoft.d.mts +168 -0
- package/dist/microsoft.d.mts.map +1 -0
- package/dist/microsoft.mjs +483 -0
- package/dist/microsoft.mjs.map +1 -0
- package/dist/node.d.mts +47 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +178 -0
- package/dist/node.mjs.map +1 -0
- package/dist/notion/api.d.mts +51 -0
- package/dist/notion/api.d.mts.map +1 -0
- package/dist/notion/api.mjs +507 -0
- package/dist/notion/api.mjs.map +1 -0
- package/dist/notion/state.d.mts +329 -0
- package/dist/notion/state.d.mts.map +1 -0
- package/dist/notion/state.mjs +432 -0
- package/dist/notion/state.mjs.map +1 -0
- package/dist/notion.d.mts +72 -0
- package/dist/notion.d.mts.map +1 -0
- package/dist/notion.mjs +127 -0
- package/dist/notion.mjs.map +1 -0
- package/dist/openai.d.mts +165 -0
- package/dist/openai.d.mts.map +1 -0
- package/dist/openai.mjs +141 -0
- package/dist/openai.mjs.map +1 -0
- package/dist/opencode-recordings.d.mts +7 -0
- package/dist/opencode-recordings.d.mts.map +1 -0
- package/dist/opencode-recordings.mjs +222 -0
- package/dist/opencode-recordings.mjs.map +1 -0
- package/dist/opencode.d.mts +70 -0
- package/dist/opencode.d.mts.map +1 -0
- package/dist/opencode.mjs +217 -0
- package/dist/opencode.mjs.map +1 -0
- package/dist/r2-fixtures.d.mts +36 -0
- package/dist/r2-fixtures.d.mts.map +1 -0
- package/dist/r2-fixtures.mjs +245 -0
- package/dist/r2-fixtures.mjs.map +1 -0
- package/dist/r2-guard.d.mts +43 -0
- package/dist/r2-guard.d.mts.map +1 -0
- package/dist/r2-guard.mjs +215 -0
- package/dist/r2-guard.mjs.map +1 -0
- package/dist/r2.d.mts +166 -0
- package/dist/r2.d.mts.map +1 -0
- package/dist/r2.mjs +517 -0
- package/dist/r2.mjs.map +1 -0
- package/dist/responses.d.mts +231 -0
- package/dist/responses.d.mts.map +1 -0
- package/dist/responses.mjs +556 -0
- package/dist/responses.mjs.map +1 -0
- package/dist/route-evidence.d.mts +45 -0
- package/dist/route-evidence.d.mts.map +1 -0
- package/dist/route-evidence.mjs +56 -0
- package/dist/route-evidence.mjs.map +1 -0
- package/dist/router.d.mts +93 -0
- package/dist/router.d.mts.map +1 -0
- package/dist/router.mjs +259 -0
- package/dist/router.mjs.map +1 -0
- package/dist/stateful-core.d.mts +17 -0
- package/dist/stateful-core.d.mts.map +1 -0
- package/dist/stateful-core.mjs +41 -0
- package/dist/stateful-core.mjs.map +1 -0
- package/dist/stateful-emulator.d.mts +565 -0
- package/dist/stateful-emulator.d.mts.map +1 -0
- package/dist/stateful-emulator.mjs +1228 -0
- package/dist/stateful-emulator.mjs.map +1 -0
- package/dist/stateful-secrets.d.mts +84 -0
- package/dist/stateful-secrets.d.mts.map +1 -0
- package/dist/stateful-secrets.mjs +216 -0
- package/dist/stateful-secrets.mjs.map +1 -0
- package/dist/subscription-usage-recordings.d.mts +9 -0
- package/dist/subscription-usage-recordings.d.mts.map +1 -0
- package/dist/subscription-usage-recordings.mjs +53 -0
- package/dist/subscription-usage-recordings.mjs.map +1 -0
- package/dist/subscription-usage.d.mts +53 -0
- package/dist/subscription-usage.d.mts.map +1 -0
- package/dist/subscription-usage.mjs +21 -0
- package/dist/subscription-usage.mjs.map +1 -0
- package/dist/telegram/api.d.mts +34 -0
- package/dist/telegram/api.d.mts.map +1 -0
- package/dist/telegram/api.mjs +257 -0
- package/dist/telegram/api.mjs.map +1 -0
- package/dist/telegram/state.d.mts +128 -0
- package/dist/telegram/state.d.mts.map +1 -0
- package/dist/telegram/state.mjs +154 -0
- package/dist/telegram/state.mjs.map +1 -0
- package/dist/telegram.d.mts +62 -0
- package/dist/telegram.d.mts.map +1 -0
- package/dist/telegram.mjs +127 -0
- package/dist/telegram.mjs.map +1 -0
- package/dist/todoist/api.d.mts +55 -0
- package/dist/todoist/api.d.mts.map +1 -0
- package/dist/todoist/api.mjs +415 -0
- package/dist/todoist/api.mjs.map +1 -0
- package/dist/todoist/state.d.mts +275 -0
- package/dist/todoist/state.d.mts.map +1 -0
- package/dist/todoist/state.mjs +345 -0
- package/dist/todoist/state.mjs.map +1 -0
- package/dist/todoist.d.mts +68 -0
- package/dist/todoist.d.mts.map +1 -0
- package/dist/todoist.mjs +181 -0
- package/dist/todoist.mjs.map +1 -0
- package/dist/xai.d.mts +267 -0
- package/dist/xai.d.mts.map +1 -0
- package/dist/xai.mjs +252 -0
- package/dist/xai.mjs.map +1 -0
- package/package.json +157 -0
- package/src/anthropic.ts +289 -0
- package/src/chat-completions.ts +924 -0
- package/src/codex.ts +296 -0
- package/src/dropbox/api.ts +1084 -0
- package/src/dropbox/state.ts +364 -0
- package/src/dropbox.ts +203 -0
- package/src/email-fixtures.ts +1297 -0
- package/src/email.ts +1108 -0
- package/src/emulator-compose.ts +147 -0
- package/src/emulator-http.ts +184 -0
- package/src/emulator-kernel.ts +844 -0
- package/src/fixture-route.ts +561 -0
- package/src/fortnox/api.ts +1352 -0
- package/src/fortnox/state.ts +798 -0
- package/src/fortnox.ts +801 -0
- package/src/gateway-evaluate-recordings.ts +153 -0
- package/src/gateway.ts +530 -0
- package/src/github/api.ts +986 -0
- package/src/github/state.ts +439 -0
- package/src/github.ts +271 -0
- package/src/google/calendar.ts +486 -0
- package/src/google/drive.ts +471 -0
- package/src/google/gmail.ts +1011 -0
- package/src/google/shared.ts +321 -0
- package/src/google/state.ts +686 -0
- package/src/google.ts +298 -0
- package/src/linkedin-search/api.ts +363 -0
- package/src/linkedin-search/state.ts +373 -0
- package/src/linkedin-search.ts +241 -0
- package/src/mcp/api.ts +995 -0
- package/src/mcp/recordings.ts +2665 -0
- package/src/mcp/state.ts +125 -0
- package/src/mcp.ts +319 -0
- package/src/messages.ts +844 -0
- package/src/microsoft/api.ts +426 -0
- package/src/microsoft/calendar.ts +491 -0
- package/src/microsoft/drive.ts +541 -0
- package/src/microsoft/graph.ts +550 -0
- package/src/microsoft/mail.ts +833 -0
- package/src/microsoft/state.ts +822 -0
- package/src/microsoft.ts +982 -0
- package/src/node.ts +293 -0
- package/src/notion/api.ts +976 -0
- package/src/notion/state.ts +512 -0
- package/src/notion.ts +210 -0
- package/src/openai.ts +198 -0
- package/src/opencode-recordings.ts +257 -0
- package/src/opencode.ts +271 -0
- package/src/r2-fixtures.ts +295 -0
- package/src/r2-guard.ts +323 -0
- package/src/r2.ts +890 -0
- package/src/responses.ts +901 -0
- package/src/route-evidence.ts +90 -0
- package/src/router.ts +490 -0
- package/src/stateful-core.ts +70 -0
- package/src/stateful-emulator.ts +2571 -0
- package/src/stateful-secrets.ts +299 -0
- package/src/subscription-usage-recordings.ts +77 -0
- package/src/subscription-usage.ts +68 -0
- package/src/telegram/api.ts +437 -0
- package/src/telegram/state.ts +229 -0
- package/src/telegram.ts +227 -0
- package/src/todoist/api.ts +736 -0
- package/src/todoist/state.ts +456 -0
- package/src/todoist.ts +316 -0
- package/src/xai.ts +341 -0
package/src/telegram.ts
ADDED
|
@@ -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
|
+
}
|