@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,625 @@
1
+ import { Result, Struct } from "effect";
2
+ import * as Schema from "effect/Schema";
3
+ //#region src/microsoft/state.ts
4
+ /**
5
+ * Microsoft Graph emulator state: the typed entities, the seed input, the default seed, and the
6
+ * profiles (internal; re-exported by `src/microsoft.ts`).
7
+ *
8
+ * Entity shapes and the default entities follow the synthetic Microsoft conformance fixtures,
9
+ * copied as data (the same mailbox, calendar, event, message, folder, drive, and item ids as
10
+ * `microsoftConformanceFixtureSeeds`), never imported from SDK code. Where no fixture records a
11
+ * value, the default is synthesized and says so below: the user id, the well-known mail folders
12
+ * other than Drafts and Deleted Items, the attachment message itself, and the drive root and
13
+ * `Sources` folder have no fixture.
14
+ *
15
+ * @experimental
16
+ */
17
+ const Timestamp = Schema.String;
18
+ /** A recipient as stored: `name` falls back to the address when Graph has none. */
19
+ const MicrosoftEmulatorRecipient = Schema.Struct({
20
+ name: Schema.NullOr(Schema.String),
21
+ address: Schema.String
22
+ });
23
+ /** The mailbox owner every `/users/{userId}` route answers for (id, `mail`, or UPN). */
24
+ const MicrosoftEmulatorUser = Schema.Struct({
25
+ id: Schema.String,
26
+ displayName: Schema.String,
27
+ mail: Schema.String,
28
+ userPrincipalName: Schema.String
29
+ });
30
+ const WellKnownFolder = Schema.Literals([
31
+ "inbox",
32
+ "drafts",
33
+ "deleteditems"
34
+ ]);
35
+ /** A mail folder; `wellKnownName` lets routes address it by name (`deleteditems`). */
36
+ const MicrosoftEmulatorMailFolder = Schema.Struct({
37
+ id: Schema.String,
38
+ displayName: Schema.String,
39
+ wellKnownName: Schema.NullOr(WellKnownFolder)
40
+ });
41
+ const BodyContentType = Schema.Literals(["text", "html"]);
42
+ const messageFields = {
43
+ /** The immutable id (`Prefer: IdType="ImmutableId"`): stable across moves. */
44
+ id: Schema.String,
45
+ parentFolderId: Schema.String,
46
+ subject: Schema.String,
47
+ bodyContentType: BodyContentType,
48
+ bodyContent: Schema.String,
49
+ from: Schema.NullOr(MicrosoftEmulatorRecipient),
50
+ sender: Schema.NullOr(MicrosoftEmulatorRecipient),
51
+ toRecipients: Schema.Array(MicrosoftEmulatorRecipient),
52
+ ccRecipients: Schema.Array(MicrosoftEmulatorRecipient),
53
+ bccRecipients: Schema.Array(MicrosoftEmulatorRecipient),
54
+ replyTo: Schema.Array(MicrosoftEmulatorRecipient),
55
+ isRead: Schema.Boolean,
56
+ isDraft: Schema.Boolean,
57
+ importance: Schema.Literals([
58
+ "low",
59
+ "normal",
60
+ "high"
61
+ ]),
62
+ flagStatus: Schema.Literals([
63
+ "notFlagged",
64
+ "flagged",
65
+ "complete"
66
+ ]),
67
+ categories: Schema.Array(Schema.String),
68
+ /** Answered as stored (not derived from the attachments; no fixture shows the rule). */
69
+ hasAttachments: Schema.Boolean,
70
+ createdDateTime: Timestamp,
71
+ lastModifiedDateTime: Timestamp,
72
+ receivedDateTime: Timestamp,
73
+ sentDateTime: Timestamp,
74
+ conversationId: Schema.String,
75
+ internetMessageId: Schema.String,
76
+ changeKey: Schema.String
77
+ };
78
+ /** A stored message. Every message is addressed by its immutable id. */
79
+ const MicrosoftEmulatorMessage = Schema.Struct(messageFields);
80
+ const attachmentFields = {
81
+ id: Schema.String,
82
+ /** Immutable id of the owning message. */
83
+ messageId: Schema.String,
84
+ name: Schema.String,
85
+ contentType: Schema.String,
86
+ size: Schema.Int,
87
+ isInline: Schema.Boolean,
88
+ contentId: Schema.NullOr(Schema.String),
89
+ contentLocation: Schema.NullOr(Schema.String),
90
+ contentBytes: Schema.String,
91
+ lastModifiedDateTime: Timestamp
92
+ };
93
+ /** A stored file attachment (`#microsoft.graph.fileAttachment`). */
94
+ const MicrosoftEmulatorAttachment = Schema.Struct(attachmentFields);
95
+ const MicrosoftEmulatorCalendar = Schema.Struct({
96
+ id: Schema.String,
97
+ name: Schema.String
98
+ });
99
+ /** Graph local date-time in UTC with seven fractional digits (`2026-09-23T12:00:00.0000000`). */
100
+ const microsoftEmulatorDateTimePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{7}$/;
101
+ const UtcDateTime = Schema.String.check(Schema.isPattern(microsoftEmulatorDateTimePattern));
102
+ const eventFields = {
103
+ id: Schema.String,
104
+ calendarId: Schema.String,
105
+ subject: Schema.String,
106
+ bodyContentType: BodyContentType,
107
+ bodyContent: Schema.String,
108
+ /** Start in UTC, seven fractional digits. */
109
+ start: UtcDateTime,
110
+ /** End in UTC, seven fractional digits. */
111
+ end: UtcDateTime,
112
+ isCancelled: Schema.Boolean,
113
+ isReminderOn: Schema.Boolean,
114
+ showAs: Schema.Literals([
115
+ "free",
116
+ "tentative",
117
+ "busy",
118
+ "oof",
119
+ "workingElsewhere",
120
+ "unknown"
121
+ ]),
122
+ changeKey: Schema.String,
123
+ createdDateTime: Timestamp,
124
+ lastModifiedDateTime: Timestamp
125
+ };
126
+ /** A stored single-instance calendar event (no attendees, no recurrence). */
127
+ const MicrosoftEmulatorEvent = Schema.Struct(eventFields);
128
+ /** The one emulated drive. */
129
+ const MicrosoftEmulatorDrive = Schema.Struct({
130
+ id: Schema.String,
131
+ driveType: Schema.Literals(["business", "personal"]),
132
+ rootId: Schema.String
133
+ });
134
+ const driveItemFields = {
135
+ id: Schema.String,
136
+ /** `null` only for the drive root. */
137
+ parentId: Schema.NullOr(Schema.String),
138
+ name: Schema.String,
139
+ kind: Schema.Literals(["folder", "file"]),
140
+ /** File size in bytes; folders report the sum of their contents instead. */
141
+ size: Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)),
142
+ mimeType: Schema.NullOr(Schema.String),
143
+ quickXorHash: Schema.NullOr(Schema.String),
144
+ createdDateTime: Timestamp,
145
+ lastModifiedDateTime: Timestamp
146
+ };
147
+ /** A stored drive item (file or folder). Deleted items are removed (no recycle bin). */
148
+ const MicrosoftEmulatorDriveItem = Schema.Struct(driveItemFields);
149
+ const Counter = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
150
+ const Counters = Schema.Struct({
151
+ /** Next number in created event ids (`AAMkAGI2-synthetic-event-0101=`). */
152
+ nextEventNumber: Counter,
153
+ /** Next number in created message immutable ids. */
154
+ nextMessageNumber: Counter,
155
+ /** Next change key number (message and event writes). */
156
+ nextChangeKeyNumber: Counter,
157
+ /** Next number in created drive item ids. */
158
+ nextItemNumber: Counter
159
+ });
160
+ /** The whole emulator state (JSON-compatible; what `snapshot()` returns). */
161
+ const MicrosoftEmulatorStateSchema = Schema.Struct({
162
+ user: MicrosoftEmulatorUser,
163
+ mailFolders: Schema.Array(MicrosoftEmulatorMailFolder),
164
+ messages: Schema.Array(MicrosoftEmulatorMessage),
165
+ attachments: Schema.Array(MicrosoftEmulatorAttachment),
166
+ calendars: Schema.Array(MicrosoftEmulatorCalendar),
167
+ events: Schema.Array(MicrosoftEmulatorEvent),
168
+ drive: MicrosoftEmulatorDrive,
169
+ driveItems: Schema.Array(MicrosoftEmulatorDriveItem),
170
+ counters: Counters
171
+ });
172
+ /** A seeded message: `id`, `parentFolderId`, and `subject` are required. */
173
+ const MicrosoftEmulatorMessageSeed = Schema.Struct(Struct.mapOmit(messageFields, [
174
+ "id",
175
+ "parentFolderId",
176
+ "subject"
177
+ ], Schema.optionalKey));
178
+ /** A seeded attachment: `id`, `messageId`, and `name` are required. */
179
+ const MicrosoftEmulatorAttachmentSeed = Schema.Struct(Struct.mapOmit(attachmentFields, [
180
+ "id",
181
+ "messageId",
182
+ "name"
183
+ ], Schema.optionalKey));
184
+ /**
185
+ * A seeded event: `id`, `calendarId`, `subject`, `start`, and `end` are required. `start` and
186
+ * `end` are UTC: either an ISO instant ending in `Z` or a seven-digit local date-time.
187
+ */
188
+ const MicrosoftEmulatorEventSeed = Schema.Struct({
189
+ ...Struct.mapOmit(eventFields, [
190
+ "id",
191
+ "calendarId",
192
+ "subject",
193
+ "start",
194
+ "end"
195
+ ], Schema.optionalKey),
196
+ start: Schema.String,
197
+ end: Schema.String
198
+ });
199
+ /** A seeded drive item: `id`, `parentId`, `name`, and `kind` are required. */
200
+ const MicrosoftEmulatorDriveItemSeed = Schema.Struct(Struct.mapOmit(driveItemFields, [
201
+ "id",
202
+ "parentId",
203
+ "name",
204
+ "kind"
205
+ ], Schema.optionalKey));
206
+ /** Account-variance profiles for the default seed. */
207
+ const MicrosoftEmulatorProfile = Schema.Literals(["default", "empty"]);
208
+ /**
209
+ * A typed seed. Start from `profile` (default `'default'`, the fixture entities); every other
210
+ * key, when given, replaces that part of the profile.
211
+ */
212
+ const MicrosoftEmulatorSeed = Schema.Struct({
213
+ profile: Schema.optionalKey(MicrosoftEmulatorProfile),
214
+ user: Schema.optionalKey(MicrosoftEmulatorUser),
215
+ mailFolders: Schema.optionalKey(Schema.Array(MicrosoftEmulatorMailFolder)),
216
+ messages: Schema.optionalKey(Schema.Array(MicrosoftEmulatorMessageSeed)),
217
+ attachments: Schema.optionalKey(Schema.Array(MicrosoftEmulatorAttachmentSeed)),
218
+ calendars: Schema.optionalKey(Schema.Array(MicrosoftEmulatorCalendar)),
219
+ events: Schema.optionalKey(Schema.Array(MicrosoftEmulatorEventSeed)),
220
+ drive: Schema.optionalKey(MicrosoftEmulatorDrive),
221
+ driveItems: Schema.optionalKey(Schema.Array(MicrosoftEmulatorDriveItemSeed))
222
+ });
223
+ const strict = { onExcessProperty: "error" };
224
+ const decodeSeedInput = Schema.decodeUnknownResult(MicrosoftEmulatorSeed, strict);
225
+ const decodeStateInput = Schema.decodeUnknownResult(MicrosoftEmulatorStateSchema, strict);
226
+ const issueMessage = (issue) => new Schema.SchemaError(issue).message;
227
+ const ticksPerMilli = BigInt(1e4);
228
+ const ticksPerSecond = BigInt(1e7);
229
+ const instantPattern = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,7}))?(Z|[+-]\d{2}:\d{2})?$/;
230
+ /**
231
+ * Ticks of an ISO-8601 date-time. `zone` `'required'` needs `Z` or an offset; `'forbidden'`
232
+ * needs none (a Graph local date-time, read as UTC); `'optional'` reads a missing one as UTC.
233
+ */
234
+ const parseInstant = (value, zone) => {
235
+ const match = instantPattern.exec(value);
236
+ if (match === null) return void 0;
237
+ const [, year, month, day, hour, minute, second, fraction = "", offset] = match;
238
+ if (zone === "required" && offset === void 0 || zone === "forbidden" && offset !== void 0) return;
239
+ const wholeMillis = Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hour), Number(minute), Number(second));
240
+ const check = new Date(wholeMillis);
241
+ if (!Number.isFinite(wholeMillis) || check.getUTCFullYear() !== Number(year) || check.getUTCMonth() !== Number(month) - 1 || check.getUTCDate() !== Number(day) || check.getUTCHours() !== Number(hour) || check.getUTCMinutes() !== Number(minute)) return;
242
+ const offsetMinutes = offset === void 0 || offset === "Z" ? 0 : (offset.startsWith("-") ? -1 : 1) * (Number(offset.slice(1, 3)) * 60 + Number(offset.slice(4, 6)));
243
+ return BigInt(wholeMillis - offsetMinutes * 6e4) * ticksPerMilli + BigInt(fraction.padEnd(7, "0"));
244
+ };
245
+ const pad = (value, width) => String(value).padStart(width, "0");
246
+ /** A UTC local date-time with `digits` fractional digits (Graph uses seven). */
247
+ const formatLocalDateTime = (ticks, digits) => {
248
+ const millis = Number(ticks / ticksPerMilli);
249
+ const date = new Date(millis);
250
+ const fraction = pad(Number((ticks % ticksPerSecond + ticksPerSecond) % ticksPerSecond), 7);
251
+ const whole = `${pad(date.getUTCFullYear(), 4)}-${pad(date.getUTCMonth() + 1, 2)}-${pad(date.getUTCDate(), 2)}T${pad(date.getUTCHours(), 2)}:${pad(date.getUTCMinutes(), 2)}:${pad(date.getUTCSeconds(), 2)}`;
252
+ return digits === 0 ? whole : `${whole}.${fraction.slice(0, digits)}`;
253
+ };
254
+ const ada = {
255
+ id: "00000000-0000-4000-8000-00000000ada1",
256
+ displayName: "Ada Example",
257
+ mail: "ada@example.test",
258
+ userPrincipalName: "ada@example.test"
259
+ };
260
+ const grace = {
261
+ name: "Grace Example",
262
+ address: "grace@example.test"
263
+ };
264
+ const adaRecipient = {
265
+ name: "Ada Example",
266
+ address: "ada@example.test"
267
+ };
268
+ const inboxId = "AAMkAGI2-synthetic-inbox-folder=";
269
+ const pagingFolderId = "AAMkAGI2-synthetic-folder-0001=";
270
+ const defaultMailFolders = [
271
+ {
272
+ id: inboxId,
273
+ displayName: "Inbox",
274
+ wellKnownName: "inbox"
275
+ },
276
+ {
277
+ id: "AAMkAGI2-synthetic-drafts-folder=",
278
+ displayName: "Drafts",
279
+ wellKnownName: "drafts"
280
+ },
281
+ {
282
+ id: "AAMkAGI2-synthetic-deleteditems-folder=",
283
+ displayName: "Deleted Items",
284
+ wellKnownName: "deleteditems"
285
+ },
286
+ {
287
+ id: pagingFolderId,
288
+ displayName: "Synthetic updates",
289
+ wellKnownName: null
290
+ }
291
+ ];
292
+ const pagingMessage = (number, hour) => {
293
+ const id = `AAMkAGI2-synthetic-message-${pad(number, 4)}=`;
294
+ const at = `2026-09-22T${pad(hour, 2)}:00:00Z`;
295
+ return {
296
+ id,
297
+ parentFolderId: pagingFolderId,
298
+ subject: `Synthetic update ${number - 100}`,
299
+ bodyContent: "Synthetic message body.",
300
+ from: grace,
301
+ sender: grace,
302
+ toRecipients: [adaRecipient],
303
+ isRead: true,
304
+ isDraft: false,
305
+ receivedDateTime: at,
306
+ sentDateTime: at,
307
+ createdDateTime: at,
308
+ lastModifiedDateTime: at,
309
+ conversationId: `AAQkAGI2-synthetic-conversation-${pad(number, 4)}=`,
310
+ internetMessageId: `<synthetic-${pad(number, 4)}@example.test>`,
311
+ changeKey: `CQAAABYAAAAsynthetic${pad(number, 4)}`
312
+ };
313
+ };
314
+ const attachmentMessageId = "AAMkAGI2-synthetic-message-0001=";
315
+ const defaultMessages = [
316
+ {
317
+ id: attachmentMessageId,
318
+ parentFolderId: inboxId,
319
+ subject: "Synthetic message with attachments",
320
+ bodyContentType: "html",
321
+ bodyContent: "<p>Synthetic body <img src=\"cid:image001.png@01DD2E00.00000000\"></p>",
322
+ from: grace,
323
+ sender: grace,
324
+ toRecipients: [adaRecipient],
325
+ isRead: false,
326
+ isDraft: false,
327
+ hasAttachments: true,
328
+ receivedDateTime: "2026-09-22T08:15:00Z",
329
+ sentDateTime: "2026-09-22T08:15:00Z",
330
+ createdDateTime: "2026-09-22T08:15:00Z",
331
+ lastModifiedDateTime: "2026-09-22T08:15:00Z",
332
+ conversationId: "AAQkAGI2-synthetic-conversation-0001=",
333
+ internetMessageId: "<synthetic-0001@example.test>",
334
+ changeKey: "CQAAABYAAAAsynthetic0001"
335
+ },
336
+ pagingMessage(101, 9),
337
+ pagingMessage(102, 8),
338
+ pagingMessage(103, 7)
339
+ ];
340
+ const defaultAttachments = [{
341
+ id: "AAMkAGI2-synthetic-attachment-0001=",
342
+ messageId: attachmentMessageId,
343
+ name: "image001.png",
344
+ contentType: "image/png",
345
+ size: 1024,
346
+ isInline: true,
347
+ contentId: "image001.png@01DD2E00.00000000",
348
+ contentBytes: "iVBORw0KGgo=",
349
+ lastModifiedDateTime: "2026-09-22T08:15:00Z"
350
+ }, {
351
+ id: "AAMkAGI2-synthetic-attachment-0002=",
352
+ messageId: attachmentMessageId,
353
+ name: "synthetic-report.pdf",
354
+ contentType: "application/pdf",
355
+ size: 2048,
356
+ isInline: false,
357
+ contentId: null,
358
+ contentBytes: "JVBERi0xLjQK",
359
+ lastModifiedDateTime: "2026-09-22T08:15:00Z"
360
+ }];
361
+ const calendarId = "AAMkAGI2-synthetic-calendar-0001=";
362
+ const defaultCalendars = [{
363
+ id: calendarId,
364
+ name: "Calendar"
365
+ }];
366
+ const defaultEvents = [{
367
+ id: "AAMkAGI2-synthetic-event-0001=",
368
+ calendarId,
369
+ subject: "Synthetic planning session",
370
+ start: "2026-09-23T12:00:00Z",
371
+ end: "2026-09-23T13:00:00Z",
372
+ changeKey: "DwAAABYAAAAsynthetic0001"
373
+ }, {
374
+ id: "AAMkAGI2-synthetic-event-0002=",
375
+ calendarId,
376
+ subject: "Synthetic review",
377
+ start: "2026-09-24T08:30:00Z",
378
+ end: "2026-09-24T09:00:00Z",
379
+ changeKey: "DwAAABYAAAAsynthetic0002"
380
+ }];
381
+ const defaultDrive = {
382
+ id: "b!synthetic-drive-0001",
383
+ driveType: "business",
384
+ rootId: "01SYNTHETICROOTFOLDER00000000001"
385
+ };
386
+ const quickXorHash = "AAAAAAAAAAAAAAAAAAAAAAAAAAA=";
387
+ const conformanceFolderId = "01SYNTHETICPARENTFOLDER0000000001";
388
+ const sourcesFolderId = "01SYNTHETICSOURCEPARENT000000001";
389
+ const rootItem = {
390
+ id: defaultDrive.rootId,
391
+ parentId: null,
392
+ name: "root",
393
+ kind: "folder"
394
+ };
395
+ const defaultDriveItems = [
396
+ rootItem,
397
+ {
398
+ id: conformanceFolderId,
399
+ parentId: defaultDrive.rootId,
400
+ name: "Conformance",
401
+ kind: "folder"
402
+ },
403
+ {
404
+ id: "01SYNTHETICEXISTINGFILE000000001",
405
+ parentId: conformanceFolderId,
406
+ name: "synthetic-existing.txt",
407
+ kind: "file",
408
+ size: 12,
409
+ mimeType: "text/plain",
410
+ quickXorHash
411
+ },
412
+ {
413
+ id: sourcesFolderId,
414
+ parentId: defaultDrive.rootId,
415
+ name: "Sources",
416
+ kind: "folder"
417
+ },
418
+ {
419
+ id: "01SYNTHETICSOURCEFILE00000000001",
420
+ parentId: sourcesFolderId,
421
+ name: "synthetic-notes.txt",
422
+ kind: "file",
423
+ size: 24,
424
+ mimeType: "text/plain",
425
+ quickXorHash
426
+ }
427
+ ];
428
+ const profileEntities = (profile) => {
429
+ switch (profile) {
430
+ case "default": return {
431
+ user: ada,
432
+ mailFolders: defaultMailFolders,
433
+ messages: defaultMessages,
434
+ attachments: defaultAttachments,
435
+ calendars: defaultCalendars,
436
+ events: defaultEvents,
437
+ drive: defaultDrive,
438
+ driveItems: defaultDriveItems
439
+ };
440
+ case "empty": return {
441
+ user: ada,
442
+ mailFolders: defaultMailFolders.filter((folder) => folder.wellKnownName !== null),
443
+ messages: [],
444
+ attachments: [],
445
+ calendars: defaultCalendars,
446
+ events: [],
447
+ drive: defaultDrive,
448
+ driveItems: [rootItem]
449
+ };
450
+ }
451
+ };
452
+ const defaultTimestamp = "2026-09-29T10:00:00Z";
453
+ const messageFromSeed = (seed, user) => {
454
+ const owner = {
455
+ name: user.displayName,
456
+ address: user.mail
457
+ };
458
+ const created = seed.createdDateTime ?? defaultTimestamp;
459
+ return {
460
+ id: seed.id,
461
+ parentFolderId: seed.parentFolderId,
462
+ subject: seed.subject,
463
+ bodyContentType: seed.bodyContentType ?? "text",
464
+ bodyContent: seed.bodyContent ?? "",
465
+ from: seed.from === void 0 ? owner : seed.from,
466
+ sender: seed.sender === void 0 ? owner : seed.sender,
467
+ toRecipients: seed.toRecipients ?? [],
468
+ ccRecipients: seed.ccRecipients ?? [],
469
+ bccRecipients: seed.bccRecipients ?? [],
470
+ replyTo: seed.replyTo ?? [],
471
+ isRead: seed.isRead ?? true,
472
+ isDraft: seed.isDraft ?? false,
473
+ importance: seed.importance ?? "normal",
474
+ flagStatus: seed.flagStatus ?? "notFlagged",
475
+ categories: seed.categories ?? [],
476
+ hasAttachments: seed.hasAttachments ?? false,
477
+ createdDateTime: created,
478
+ lastModifiedDateTime: seed.lastModifiedDateTime ?? created,
479
+ receivedDateTime: seed.receivedDateTime ?? created,
480
+ sentDateTime: seed.sentDateTime ?? created,
481
+ conversationId: seed.conversationId ?? `AAQkAGI2-synthetic-conversation-${seed.id}`,
482
+ internetMessageId: seed.internetMessageId ?? `<${seed.id}@example.test>`,
483
+ changeKey: seed.changeKey ?? "CQAAABYAAAAsynthetic0000"
484
+ };
485
+ };
486
+ /** Decoded size of a base64 string (no validation beyond the padding count). */
487
+ const base64Size = (value) => Math.max(0, Math.floor(value.length * 3 / 4) - (value.match(/=+$/)?.[0].length ?? 0));
488
+ const attachmentFromSeed = (seed) => {
489
+ const contentBytes = seed.contentBytes ?? "";
490
+ return {
491
+ id: seed.id,
492
+ messageId: seed.messageId,
493
+ name: seed.name,
494
+ contentType: seed.contentType ?? "application/octet-stream",
495
+ size: seed.size ?? base64Size(contentBytes),
496
+ isInline: seed.isInline ?? false,
497
+ contentId: seed.contentId ?? null,
498
+ contentLocation: seed.contentLocation ?? null,
499
+ contentBytes,
500
+ lastModifiedDateTime: seed.lastModifiedDateTime ?? defaultTimestamp
501
+ };
502
+ };
503
+ /** A seeded start/end as a seven-digit UTC local date-time, or `undefined` when unreadable. */
504
+ const seedDateTime = (value) => {
505
+ const ticks = value.endsWith("Z") ? parseInstant(value, "required") : parseInstant(value, "forbidden");
506
+ return ticks === void 0 ? void 0 : formatLocalDateTime(ticks, 7);
507
+ };
508
+ const eventFromSeed = (seed, start, end) => ({
509
+ id: seed.id,
510
+ calendarId: seed.calendarId,
511
+ subject: seed.subject,
512
+ bodyContentType: seed.bodyContentType ?? "text",
513
+ bodyContent: seed.bodyContent ?? "",
514
+ start,
515
+ end,
516
+ isCancelled: seed.isCancelled ?? false,
517
+ isReminderOn: seed.isReminderOn ?? false,
518
+ showAs: seed.showAs ?? "busy",
519
+ changeKey: seed.changeKey ?? "DwAAABYAAAAsynthetic0000",
520
+ createdDateTime: seed.createdDateTime ?? defaultTimestamp,
521
+ lastModifiedDateTime: seed.lastModifiedDateTime ?? seed.createdDateTime ?? defaultTimestamp
522
+ });
523
+ const driveItemFromSeed = (seed) => ({
524
+ id: seed.id,
525
+ parentId: seed.parentId,
526
+ name: seed.name,
527
+ kind: seed.kind,
528
+ size: seed.kind === "folder" ? 0 : seed.size ?? 0,
529
+ mimeType: seed.kind === "folder" ? null : seed.mimeType ?? "application/octet-stream",
530
+ quickXorHash: seed.kind === "folder" ? null : seed.quickXorHash ?? null,
531
+ createdDateTime: seed.createdDateTime ?? defaultTimestamp,
532
+ lastModifiedDateTime: seed.lastModifiedDateTime ?? seed.createdDateTime ?? defaultTimestamp
533
+ });
534
+ const duplicate = (values) => values.find((value, index) => values.indexOf(value) !== index);
535
+ /** Integrity problems a decoded seed can still have (duplicates, dangling references, cycles). */
536
+ const seedProblem = (entities) => {
537
+ const folderIds = entities.mailFolders.map((folder) => folder.id);
538
+ const messageIds = entities.messages.map((message) => message.id);
539
+ const calendarIds = entities.calendars.map((calendar) => calendar.id);
540
+ const itemIds = entities.driveItems.map((item) => item.id);
541
+ const duplicates = [
542
+ ["mail folder id", duplicate(folderIds)],
543
+ ["well-known folder", duplicate(entities.mailFolders.flatMap((folder) => folder.wellKnownName ?? []))],
544
+ ["message id", duplicate(messageIds)],
545
+ ["attachment id", duplicate(entities.attachments.map((attachment) => attachment.id))],
546
+ ["calendar id", duplicate(calendarIds)],
547
+ ["event id", duplicate(entities.events.map((event) => event.id))],
548
+ ["drive item id", duplicate(itemIds)]
549
+ ];
550
+ for (const [label, value] of duplicates) if (value !== void 0) return `duplicate ${label} ${value}`;
551
+ for (const wellKnown of ["drafts", "deleteditems"]) if (!entities.mailFolders.some((folder) => folder.wellKnownName === wellKnown)) return `the mail folders need a ${wellKnown} folder`;
552
+ const message = entities.messages.find((candidate) => !folderIds.includes(candidate.parentFolderId));
553
+ if (message !== void 0) return `message ${message.id} references missing folder ${message.parentFolderId}`;
554
+ const attachment = entities.attachments.find((candidate) => !messageIds.includes(candidate.messageId));
555
+ if (attachment !== void 0) return `attachment ${attachment.id} references missing message ${attachment.messageId}`;
556
+ const event = entities.events.find((candidate) => !calendarIds.includes(candidate.calendarId));
557
+ if (event !== void 0) return `event ${event.id} references missing calendar ${event.calendarId}`;
558
+ const roots = entities.driveItems.filter((item) => item.parentId === null);
559
+ if (roots.length !== 1 || roots[0]?.id !== entities.drive.rootId || roots[0].kind !== "folder") return `the drive items need exactly one root folder with id ${entities.drive.rootId}`;
560
+ const byId = new Map(entities.driveItems.map((item) => [item.id, item]));
561
+ for (const item of entities.driveItems) {
562
+ let parentId = item.parentId;
563
+ let steps = 0;
564
+ while (parentId !== null) {
565
+ const parent = byId.get(parentId);
566
+ if (parent === void 0 || parent.kind !== "folder") return `drive item ${item.id} has a missing or non-folder parent ${parentId}`;
567
+ steps += 1;
568
+ if (steps > entities.driveItems.length) return `drive item ${item.id} is in a parent cycle`;
569
+ parentId = parent.parentId;
570
+ }
571
+ }
572
+ };
573
+ /** Build the emulator state for a decoded seed; a string is an integrity problem. */
574
+ const stateFromSeed = (seed) => {
575
+ const profile = profileEntities(seed.profile ?? "default");
576
+ const entities = {
577
+ user: seed.user ?? profile.user,
578
+ mailFolders: seed.mailFolders ?? profile.mailFolders,
579
+ messages: seed.messages ?? profile.messages,
580
+ attachments: seed.attachments ?? profile.attachments,
581
+ calendars: seed.calendars ?? profile.calendars,
582
+ events: seed.events ?? profile.events,
583
+ drive: seed.drive ?? profile.drive,
584
+ driveItems: seed.driveItems ?? profile.driveItems
585
+ };
586
+ const problem = seedProblem(entities);
587
+ if (problem !== void 0) return problem;
588
+ const events = [];
589
+ for (const event of entities.events) {
590
+ const start = seedDateTime(event.start);
591
+ const end = seedDateTime(event.end);
592
+ if (start === void 0 || end === void 0 || end < start) return `event ${event.id} needs readable UTC start and end, with end not before start`;
593
+ events.push(eventFromSeed(event, start, end));
594
+ }
595
+ return {
596
+ user: entities.user,
597
+ mailFolders: entities.mailFolders,
598
+ messages: entities.messages.map((message) => messageFromSeed(message, entities.user)),
599
+ attachments: entities.attachments.map(attachmentFromSeed),
600
+ calendars: entities.calendars,
601
+ events,
602
+ drive: entities.drive,
603
+ driveItems: entities.driveItems.map(driveItemFromSeed),
604
+ counters: {
605
+ nextEventNumber: 101,
606
+ nextMessageNumber: 1,
607
+ nextChangeKeyNumber: 1001,
608
+ nextItemNumber: 1
609
+ }
610
+ };
611
+ };
612
+ /** Decode and build a seed; a string is the reason it is invalid. */
613
+ const buildSeedState = (input) => {
614
+ const decoded = decodeSeedInput(input);
615
+ return Result.isFailure(decoded) ? issueMessage(decoded.failure.issue) : stateFromSeed(decoded.success);
616
+ };
617
+ /** Decode a full state (a restored snapshot); a string is the reason it is invalid. */
618
+ const decodeState = (input) => {
619
+ const decoded = decodeStateInput(input);
620
+ return Result.isFailure(decoded) ? issueMessage(decoded.failure.issue) : { ...decoded.success };
621
+ };
622
+ //#endregion
623
+ export { MicrosoftEmulatorAttachment, MicrosoftEmulatorAttachmentSeed, MicrosoftEmulatorCalendar, MicrosoftEmulatorDrive, MicrosoftEmulatorDriveItem, MicrosoftEmulatorDriveItemSeed, MicrosoftEmulatorEvent, MicrosoftEmulatorEventSeed, MicrosoftEmulatorMailFolder, MicrosoftEmulatorMessage, MicrosoftEmulatorMessageSeed, MicrosoftEmulatorProfile, MicrosoftEmulatorRecipient, MicrosoftEmulatorSeed, MicrosoftEmulatorStateSchema, MicrosoftEmulatorUser, buildSeedState, decodeState, formatLocalDateTime, microsoftEmulatorDateTimePattern, parseInstant };
624
+
625
+ //# sourceMappingURL=state.mjs.map