@satorio/machinery 0.2.1

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 (341) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +71 -0
  3. package/dictionary/all.json +4656 -0
  4. package/dictionary/all.toon +639 -0
  5. package/dictionary/core.json +221 -0
  6. package/dictionary/core.toon +33 -0
  7. package/dictionary/graphql.json +212 -0
  8. package/dictionary/graphql.toon +32 -0
  9. package/dictionary/http.json +113 -0
  10. package/dictionary/http.toon +21 -0
  11. package/dictionary/identifiers.json +266 -0
  12. package/dictionary/identifiers.toon +38 -0
  13. package/dictionary/index.json +96 -0
  14. package/dictionary/index.toon +18 -0
  15. package/dictionary/integration.json +131 -0
  16. package/dictionary/integration.toon +23 -0
  17. package/dictionary/money.json +383 -0
  18. package/dictionary/money.toon +51 -0
  19. package/dictionary/ports.json +392 -0
  20. package/dictionary/ports.toon +52 -0
  21. package/dictionary/postgres.json +473 -0
  22. package/dictionary/postgres.toon +61 -0
  23. package/dictionary/publishing.json +131 -0
  24. package/dictionary/publishing.toon +23 -0
  25. package/dictionary/queue.json +365 -0
  26. package/dictionary/queue.toon +49 -0
  27. package/dictionary/reference/api.mdx +843 -0
  28. package/dictionary/reference/uk/api.mdx +844 -0
  29. package/dictionary/storage.json +194 -0
  30. package/dictionary/storage.toon +30 -0
  31. package/dictionary/testing.json +707 -0
  32. package/dictionary/testing.toon +87 -0
  33. package/dictionary/time.json +311 -0
  34. package/dictionary/time.toon +43 -0
  35. package/dictionary/vitest.json +356 -0
  36. package/dictionary/vitest.toon +48 -0
  37. package/dictionary/workflow.json +185 -0
  38. package/dictionary/workflow.toon +29 -0
  39. package/dist/bin/command.d.ts +45 -0
  40. package/dist/bin/command.js +113 -0
  41. package/dist/bin.d.ts +2 -0
  42. package/dist/bin.js +11 -0
  43. package/dist/core/bigint-json.d.ts +6 -0
  44. package/dist/core/bigint-json.js +6 -0
  45. package/dist/core/closed-set.d.ts +14 -0
  46. package/dist/core/closed-set.js +8 -0
  47. package/dist/core/domain-error.d.ts +8 -0
  48. package/dist/core/domain-error.js +11 -0
  49. package/dist/core/environment.d.ts +124 -0
  50. package/dist/core/environment.js +115 -0
  51. package/dist/core/index.d.ts +13 -0
  52. package/dist/core/index.js +13 -0
  53. package/dist/core/ulid.d.ts +27 -0
  54. package/dist/core/ulid.js +27 -0
  55. package/dist/graphql/builder.d.ts +36 -0
  56. package/dist/graphql/builder.js +35 -0
  57. package/dist/graphql/context.d.ts +36 -0
  58. package/dist/graphql/context.js +69 -0
  59. package/dist/graphql/failure-classification.d.ts +11 -0
  60. package/dist/graphql/failure-classification.js +1 -0
  61. package/dist/graphql/failures.d.ts +62 -0
  62. package/dist/graphql/failures.js +30 -0
  63. package/dist/graphql/graphiql.d.ts +45 -0
  64. package/dist/graphql/graphiql.js +56 -0
  65. package/dist/graphql/index.d.ts +15 -0
  66. package/dist/graphql/index.js +14 -0
  67. package/dist/graphql/layer.d.ts +15 -0
  68. package/dist/graphql/layer.js +23 -0
  69. package/dist/graphql/request-handler.d.ts +26 -0
  70. package/dist/graphql/request-handler.js +33 -0
  71. package/dist/graphql/server.d.ts +19 -0
  72. package/dist/graphql/server.js +16 -0
  73. package/dist/graphql/settings.d.ts +55 -0
  74. package/dist/graphql/settings.js +82 -0
  75. package/dist/http/health.d.ts +70 -0
  76. package/dist/http/health.js +60 -0
  77. package/dist/http/index.d.ts +5 -0
  78. package/dist/http/index.js +5 -0
  79. package/dist/identifiers/client-code.d.ts +37 -0
  80. package/dist/identifiers/client-code.js +41 -0
  81. package/dist/identifiers/creditor-reference.d.ts +38 -0
  82. package/dist/identifiers/creditor-reference.js +32 -0
  83. package/dist/identifiers/damm.d.ts +22 -0
  84. package/dist/identifiers/damm.js +50 -0
  85. package/dist/identifiers/document-number.d.ts +68 -0
  86. package/dist/identifiers/document-number.js +73 -0
  87. package/dist/identifiers/document-numbers.d.ts +27 -0
  88. package/dist/identifiers/document-numbers.js +16 -0
  89. package/dist/identifiers/failures.d.ts +46 -0
  90. package/dist/identifiers/failures.js +48 -0
  91. package/dist/identifiers/index.d.ts +14 -0
  92. package/dist/identifiers/index.js +13 -0
  93. package/dist/identifiers/next-document-number.d.ts +26 -0
  94. package/dist/identifiers/next-document-number.js +31 -0
  95. package/dist/identifiers/ulid.d.ts +28 -0
  96. package/dist/identifiers/ulid.js +71 -0
  97. package/dist/integration/external-http-client.d.ts +22 -0
  98. package/dist/integration/external-http-client.js +74 -0
  99. package/dist/integration/index.d.ts +12 -0
  100. package/dist/integration/index.js +12 -0
  101. package/dist/integration/layer.d.ts +19 -0
  102. package/dist/integration/layer.js +30 -0
  103. package/dist/integration/retry.d.ts +65 -0
  104. package/dist/integration/retry.js +54 -0
  105. package/dist/integration/settings.d.ts +73 -0
  106. package/dist/integration/settings.js +92 -0
  107. package/dist/money/amount.d.ts +60 -0
  108. package/dist/money/amount.js +67 -0
  109. package/dist/money/arithmetic.d.ts +60 -0
  110. package/dist/money/arithmetic.js +73 -0
  111. package/dist/money/currency.d.ts +25 -0
  112. package/dist/money/currency.js +24 -0
  113. package/dist/money/decimal.d.ts +29 -0
  114. package/dist/money/decimal.js +39 -0
  115. package/dist/money/exchange-rate.d.ts +32 -0
  116. package/dist/money/exchange-rate.js +28 -0
  117. package/dist/money/failures.d.ts +86 -0
  118. package/dist/money/failures.js +97 -0
  119. package/dist/money/index.d.ts +15 -0
  120. package/dist/money/index.js +15 -0
  121. package/dist/money/percent.d.ts +35 -0
  122. package/dist/money/percent.js +50 -0
  123. package/dist/money/schema.d.ts +25 -0
  124. package/dist/money/schema.js +41 -0
  125. package/dist/ports/blob-store.d.ts +42 -0
  126. package/dist/ports/blob-store.js +13 -0
  127. package/dist/ports/document-number-counter.d.ts +36 -0
  128. package/dist/ports/document-number-counter.js +12 -0
  129. package/dist/ports/event-publisher.d.ts +29 -0
  130. package/dist/ports/event-publisher.js +13 -0
  131. package/dist/ports/external-http-client.d.ts +60 -0
  132. package/dist/ports/external-http-client.js +25 -0
  133. package/dist/ports/index.d.ts +17 -0
  134. package/dist/ports/index.js +17 -0
  135. package/dist/ports/integration-event-outbox.d.ts +44 -0
  136. package/dist/ports/integration-event-outbox.js +13 -0
  137. package/dist/ports/port-unavailable.d.ts +21 -0
  138. package/dist/ports/port-unavailable.js +30 -0
  139. package/dist/ports/processed-event-registry.d.ts +57 -0
  140. package/dist/ports/processed-event-registry.js +24 -0
  141. package/dist/ports/queue-message-producer.d.ts +26 -0
  142. package/dist/ports/queue-message-producer.js +12 -0
  143. package/dist/ports/queue-message-source.d.ts +39 -0
  144. package/dist/ports/queue-message-source.js +13 -0
  145. package/dist/ports/readiness-probe.d.ts +27 -0
  146. package/dist/ports/readiness-probe.js +13 -0
  147. package/dist/ports/transaction-boundary.d.ts +28 -0
  148. package/dist/ports/transaction-boundary.js +13 -0
  149. package/dist/postgres/client.d.ts +51 -0
  150. package/dist/postgres/client.js +81 -0
  151. package/dist/postgres/document-number-counter.d.ts +14 -0
  152. package/dist/postgres/document-number-counter.js +27 -0
  153. package/dist/postgres/failures.d.ts +28 -0
  154. package/dist/postgres/failures.js +18 -0
  155. package/dist/postgres/index.d.ts +18 -0
  156. package/dist/postgres/index.js +18 -0
  157. package/dist/postgres/integration-event-outbox.d.ts +15 -0
  158. package/dist/postgres/integration-event-outbox.js +60 -0
  159. package/dist/postgres/jsonb-value.d.ts +10 -0
  160. package/dist/postgres/jsonb-value.js +9 -0
  161. package/dist/postgres/layer.d.ts +57 -0
  162. package/dist/postgres/layer.js +72 -0
  163. package/dist/postgres/migrations/advisory-lock.d.ts +47 -0
  164. package/dist/postgres/migrations/advisory-lock.js +59 -0
  165. package/dist/postgres/migrations/runner.d.ts +56 -0
  166. package/dist/postgres/migrations/runner.js +69 -0
  167. package/dist/postgres/migrations/sql-file-loader.d.ts +59 -0
  168. package/dist/postgres/migrations/sql-file-loader.js +99 -0
  169. package/dist/postgres/processed-event-registry.d.ts +13 -0
  170. package/dist/postgres/processed-event-registry.js +44 -0
  171. package/dist/postgres/readiness-probe.d.ts +27 -0
  172. package/dist/postgres/readiness-probe.js +33 -0
  173. package/dist/postgres/settings.d.ts +134 -0
  174. package/dist/postgres/settings.js +210 -0
  175. package/dist/postgres/sql/0001_processed_event.sql +4 -0
  176. package/dist/postgres/sql/0002_integration_event_outbox.sql +13 -0
  177. package/dist/postgres/sql/0003_document_number_counter.sql +6 -0
  178. package/dist/postgres/sql-failure.d.ts +19 -0
  179. package/dist/postgres/sql-failure.js +22 -0
  180. package/dist/postgres/store-failure.d.ts +17 -0
  181. package/dist/postgres/store-failure.js +16 -0
  182. package/dist/postgres/transaction-boundary.d.ts +13 -0
  183. package/dist/postgres/transaction-boundary.js +21 -0
  184. package/dist/publishing/event-publisher.sns.d.ts +66 -0
  185. package/dist/publishing/event-publisher.sns.js +75 -0
  186. package/dist/publishing/event-publisher.stdout.d.ts +15 -0
  187. package/dist/publishing/event-publisher.stdout.js +24 -0
  188. package/dist/publishing/index.d.ts +10 -0
  189. package/dist/publishing/index.js +10 -0
  190. package/dist/publishing/layer.d.ts +25 -0
  191. package/dist/publishing/layer.js +39 -0
  192. package/dist/publishing/settings.d.ts +60 -0
  193. package/dist/publishing/settings.js +85 -0
  194. package/dist/queue/consumer.d.ts +91 -0
  195. package/dist/queue/consumer.js +92 -0
  196. package/dist/queue/envelope.d.ts +39 -0
  197. package/dist/queue/envelope.js +39 -0
  198. package/dist/queue/failures.d.ts +33 -0
  199. package/dist/queue/failures.js +15 -0
  200. package/dist/queue/index.d.ts +14 -0
  201. package/dist/queue/index.js +14 -0
  202. package/dist/queue/layer.d.ts +33 -0
  203. package/dist/queue/layer.js +58 -0
  204. package/dist/queue/message-codec.d.ts +43 -0
  205. package/dist/queue/message-codec.js +33 -0
  206. package/dist/queue/queue-message-producer.d.ts +61 -0
  207. package/dist/queue/queue-message-producer.js +52 -0
  208. package/dist/queue/queue-message-source.d.ts +93 -0
  209. package/dist/queue/queue-message-source.js +86 -0
  210. package/dist/queue/readiness.d.ts +78 -0
  211. package/dist/queue/readiness.js +86 -0
  212. package/dist/queue/settings.d.ts +106 -0
  213. package/dist/queue/settings.js +160 -0
  214. package/dist/storage/blob-store.d.ts +84 -0
  215. package/dist/storage/blob-store.js +109 -0
  216. package/dist/storage/index.d.ts +9 -0
  217. package/dist/storage/index.js +9 -0
  218. package/dist/storage/layer.d.ts +17 -0
  219. package/dist/storage/layer.js +30 -0
  220. package/dist/storage/settings.d.ts +48 -0
  221. package/dist/storage/settings.js +65 -0
  222. package/dist/testing/blob-store.d.ts +27 -0
  223. package/dist/testing/blob-store.js +45 -0
  224. package/dist/testing/clock.d.ts +29 -0
  225. package/dist/testing/clock.js +41 -0
  226. package/dist/testing/dna-perturbator/attention.d.ts +55 -0
  227. package/dist/testing/dna-perturbator/attention.js +49 -0
  228. package/dist/testing/dna-perturbator/chains.d.ts +31 -0
  229. package/dist/testing/dna-perturbator/chains.js +53 -0
  230. package/dist/testing/dna-perturbator/report.d.ts +12 -0
  231. package/dist/testing/dna-perturbator/report.js +22 -0
  232. package/dist/testing/dna-perturbator/verdict.d.ts +26 -0
  233. package/dist/testing/dna-perturbator/verdict.js +28 -0
  234. package/dist/testing/dna-perturbator.d.ts +48 -0
  235. package/dist/testing/dna-perturbator.js +145 -0
  236. package/dist/testing/document-number-counter.d.ts +29 -0
  237. package/dist/testing/document-number-counter.js +39 -0
  238. package/dist/testing/event-publisher.d.ts +28 -0
  239. package/dist/testing/event-publisher.js +33 -0
  240. package/dist/testing/external-http-client.d.ts +29 -0
  241. package/dist/testing/external-http-client.js +49 -0
  242. package/dist/testing/index.d.ts +24 -0
  243. package/dist/testing/index.js +24 -0
  244. package/dist/testing/integration-event-outbox.d.ts +37 -0
  245. package/dist/testing/integration-event-outbox.js +67 -0
  246. package/dist/testing/mutation-settings.d.ts +71 -0
  247. package/dist/testing/mutation-settings.js +57 -0
  248. package/dist/testing/postgres-rows.d.ts +12 -0
  249. package/dist/testing/postgres-rows.js +19 -0
  250. package/dist/testing/processed-event-registry.d.ts +25 -0
  251. package/dist/testing/processed-event-registry.js +39 -0
  252. package/dist/testing/queue-message-producer.d.ts +27 -0
  253. package/dist/testing/queue-message-producer.js +41 -0
  254. package/dist/testing/queue-message-source.d.ts +54 -0
  255. package/dist/testing/queue-message-source.js +71 -0
  256. package/dist/testing/quiet-reporter.d.ts +86 -0
  257. package/dist/testing/quiet-reporter.js +81 -0
  258. package/dist/testing/readiness-probe.d.ts +27 -0
  259. package/dist/testing/readiness-probe.js +33 -0
  260. package/dist/testing/scenario.d.ts +94 -0
  261. package/dist/testing/scenario.js +81 -0
  262. package/dist/testing/transaction-boundary.d.ts +30 -0
  263. package/dist/testing/transaction-boundary.js +36 -0
  264. package/dist/testing/typed-failure.d.ts +8 -0
  265. package/dist/testing/typed-failure.js +15 -0
  266. package/dist/time/calendar-day.d.ts +83 -0
  267. package/dist/time/calendar-day.js +112 -0
  268. package/dist/time/failures.d.ts +51 -0
  269. package/dist/time/failures.js +56 -0
  270. package/dist/time/index.d.ts +11 -0
  271. package/dist/time/index.js +11 -0
  272. package/dist/time/instant.d.ts +64 -0
  273. package/dist/time/instant.js +67 -0
  274. package/dist/time/period.d.ts +45 -0
  275. package/dist/time/period.js +55 -0
  276. package/dist/vitest/container-reuse.d.ts +14 -0
  277. package/dist/vitest/container-reuse.js +15 -0
  278. package/dist/vitest/dotenv.d.ts +16 -0
  279. package/dist/vitest/dotenv.js +48 -0
  280. package/dist/vitest/effect-single-instance.d.ts +36 -0
  281. package/dist/vitest/effect-single-instance.js +125 -0
  282. package/dist/vitest/fast-check-single-instance.d.ts +11 -0
  283. package/dist/vitest/fast-check-single-instance.js +26 -0
  284. package/dist/vitest/index.d.ts +31 -0
  285. package/dist/vitest/index.js +30 -0
  286. package/dist/vitest/localstack-container.d.ts +32 -0
  287. package/dist/vitest/localstack-container.js +55 -0
  288. package/dist/vitest/port-contract-tester.d.ts +8 -0
  289. package/dist/vitest/port-contract-tester.js +1 -0
  290. package/dist/vitest/port-contracts/blob-store.contract.d.ts +22 -0
  291. package/dist/vitest/port-contracts/blob-store.contract.js +108 -0
  292. package/dist/vitest/port-contracts/document-number-counter.contract.d.ts +18 -0
  293. package/dist/vitest/port-contracts/document-number-counter.contract.js +90 -0
  294. package/dist/vitest/port-contracts/event-publisher.contract.d.ts +35 -0
  295. package/dist/vitest/port-contracts/event-publisher.contract.js +67 -0
  296. package/dist/vitest/port-contracts/external-http-client.contract.d.ts +35 -0
  297. package/dist/vitest/port-contracts/external-http-client.contract.js +52 -0
  298. package/dist/vitest/port-contracts/integration-event-outbox.contract.d.ts +23 -0
  299. package/dist/vitest/port-contracts/integration-event-outbox.contract.js +75 -0
  300. package/dist/vitest/port-contracts/processed-event-registry.contract.d.ts +18 -0
  301. package/dist/vitest/port-contracts/processed-event-registry.contract.js +84 -0
  302. package/dist/vitest/port-contracts/queue-message-producer.contract.d.ts +26 -0
  303. package/dist/vitest/port-contracts/queue-message-producer.contract.js +48 -0
  304. package/dist/vitest/port-contracts/queue-message-source.contract.d.ts +29 -0
  305. package/dist/vitest/port-contracts/queue-message-source.contract.js +71 -0
  306. package/dist/vitest/port-contracts/readiness-probe.contract.d.ts +18 -0
  307. package/dist/vitest/port-contracts/readiness-probe.contract.js +41 -0
  308. package/dist/vitest/port-contracts/transaction-boundary.contract.d.ts +21 -0
  309. package/dist/vitest/port-contracts/transaction-boundary.contract.js +64 -0
  310. package/dist/vitest/postgres-container.d.ts +57 -0
  311. package/dist/vitest/postgres-container.js +118 -0
  312. package/dist/vitest/reader-port-contract.d.ts +41 -0
  313. package/dist/vitest/reader-port-contract.js +43 -0
  314. package/dist/vitest/repo-source-files.d.ts +37 -0
  315. package/dist/vitest/repo-source-files.js +61 -0
  316. package/dist/vitest/reset-tables.d.ts +18 -0
  317. package/dist/vitest/reset-tables.js +30 -0
  318. package/dist/vitest/settings-contract.d.ts +38 -0
  319. package/dist/vitest/settings-contract.js +77 -0
  320. package/dist/vitest/stub-server.d.ts +43 -0
  321. package/dist/vitest/stub-server.js +60 -0
  322. package/dist/vitest/term-registry.json +730 -0
  323. package/dist/vitest/testclock-fork-isolated-files.d.ts +13 -0
  324. package/dist/vitest/testclock-fork-isolated-files.js +18 -0
  325. package/dist/vitest/testclock-fork-isolation.d.ts +77 -0
  326. package/dist/vitest/testclock-fork-isolation.js +188 -0
  327. package/dist/workflow/claim-once.d.ts +16 -0
  328. package/dist/workflow/claim-once.js +9 -0
  329. package/dist/workflow/failures.d.ts +47 -0
  330. package/dist/workflow/failures.js +22 -0
  331. package/dist/workflow/index.d.ts +12 -0
  332. package/dist/workflow/index.js +12 -0
  333. package/dist/workflow/on-claim.d.ts +17 -0
  334. package/dist/workflow/on-claim.js +8 -0
  335. package/dist/workflow/publish-pending-events.d.ts +31 -0
  336. package/dist/workflow/publish-pending-events.js +31 -0
  337. package/dist/workflow/transactionally.d.ts +8 -0
  338. package/dist/workflow/transactionally.js +8 -0
  339. package/dist/workflow/versioned-payload.d.ts +35 -0
  340. package/dist/workflow/versioned-payload.js +43 -0
  341. package/package.json +309 -0
@@ -0,0 +1,843 @@
1
+ ---
2
+ title: Every name this package hands you
3
+ description: >-
4
+ Every name every mechanism hands you, with its shape and one sentence saying what it is, written out of the source itself.
5
+ sidebar:
6
+ order: 0
7
+ tableOfContents:
8
+ minHeadingLevel: 2
9
+ maxHeadingLevel: 2
10
+ ---
11
+
12
+ You know roughly what you need, and not the name it goes by. Somewhere in this package there is a name for it, and hunting through source files to find that name costs more than the change you came to make. This page is the whole list: every name every mechanism hands you, grouped the same way each time. The names, the shapes and the sentences all come from the source, so a page that disagrees with the code is a page nobody rebuilt. Search it by name, and you will be able to find what you need in a minute, with its shape and its default beside it.
13
+
14
+ ## The mechanisms
15
+
16
+ | Mechanism | What it is for | Import |
17
+ | --- | --- | --- |
18
+ | [core](#core) | Public entry to the core mechanism: the few pieces every other mechanism leans on, and which lean on nothing themselves. | `@satorio/machinery/core` |
19
+ | [http](#http) | Public entry to the http mechanism: readiness probes mounted on the same port as GraphQL. | `@satorio/machinery/http` |
20
+ | [money](#money) | Public entry to the money mechanism, over dinero.js, the optional peer your service installs: exact amounts of one currency, shares, rates, and rounding. | `@satorio/machinery/money` |
21
+ | [ports](#ports) | Public entry to the ports mechanism: every boundary a use case may ask for, and the failure each one raises. | `@satorio/machinery/ports` |
22
+ | [time](#time) | Public entry to the time mechanism: a day a person reads and writes, a period of days, and a moment on the clock. | `@satorio/machinery/time` |
23
+ | [identifiers](#identifiers) | Public entry to the identifiers mechanism: the id a machine mints, and the numbers a person reads off a document. | `@satorio/machinery/identifiers` |
24
+ | [workflow](#workflow) | Public entry to the workflow mechanism: the combinators a use case composes its own beat from. | `@satorio/machinery/workflow` |
25
+ | [graphql](#graphql) | Public entry to the graphql mechanism: one server that answers your operations and the readiness probes beside them. | `@satorio/machinery/graphql` |
26
+ | [integration](#integration) | Public entry to the integration mechanism: one HTTP client for reference data outside this service. | `@satorio/machinery/integration` |
27
+ | [postgres](#postgres) | Public entry to the postgres mechanism: every port this machinery defines, bound to a real database. | `@satorio/machinery/postgres` |
28
+ | [publishing](#publishing) | Public entry to the publishing mechanism: the event publisher, bound to a topic or to one line on stdout. | `@satorio/machinery/publishing` |
29
+ | [queue](#queue) | Public entry to the queue mechanism: the envelope a message travels in, and the consumer that decides its fate. | `@satorio/machinery/queue` |
30
+ | [storage](#storage) | Public entry to the storage mechanism: whole objects stored under a key and read back. | `@satorio/machinery/storage` |
31
+ | [testing](#testing) | Public entry to the testing mechanism: a stand-in for every port, a clock a test drives, and the scenario player. | `@satorio/machinery/testing` |
32
+ | [vitest](#vitest) | Public entry to the vitest mechanism: live stands, port contracts, and the guards that read the test runtime. | `@satorio/machinery/vitest` |
33
+
34
+ The mechanisms above stand in dependency order: core opens, each one below it may reach for the ones above, and the test kits close. Every section below carries the same groups in the same order, and every group the same four columns. For a name the code exports, the second column is the shape you write against. For a variable the environment decides, that column names one of three states: it falls back on a value, it refuses without one, or it hands the decision on.
35
+
36
+ ## core
37
+
38
+ Import from `@satorio/machinery/core` — [the whole page](../mechanisms/core.mdx).
39
+
40
+ ### Values
41
+
42
+ | Name | Signature or type | Default | What it is |
43
+ | --- | --- | --- | --- |
44
+ | <span id="core-ClosedSet-value">`ClosedSet`</span> | `interface` | — | Turns an array of string literals into a closed set: the values, a union type of their members, and an `is` guard, all from one source. |
45
+ | <span id="core-EnvironmentEntry-value">`EnvironmentEntry`</span> | `interface` | — | One variable a mechanism reads, and the one state it stands in. |
46
+ | <span id="core-EnvironmentState-value">`EnvironmentState`</span> | `type` | — | Which of three states a variable stands in. |
47
+ | <span id="core-Refusal-value">`Refusal`</span> | `interface` | — | A refusal in the three parts a reader needs: what happened, why this mechanism cannot go on without it, and what to do next. |
48
+ | <span id="core-Ulid-value">`Ulid`</span> | `string & { readonly [ulidBrand]: 'Ulid' }` | — | A ULID: the identifier a machine mints for a record, sortable by the moment it was minted, and a plain string everywhere it travels. |
49
+
50
+ ### Procedures
51
+
52
+ | Name | Signature or type | Default | What it is |
53
+ | --- | --- | --- | --- |
54
+ | <span id="core-bigIntsAsDecimalStrings-procedure">`bigIntsAsDecimalStrings`</span> | `(_key: string, value: unknown) => unknown` | — | Use as the replacer argument to `JSON.stringify`. |
55
+ | <span id="core-closedSet-procedure">`closedSet`</span> | `<const T extends readonly string[]>(values: T) => ClosedSet<T>` | — | Builds a closed set from an array of string literals, so the guard and the list it guards come from one source. |
56
+ | <span id="core-fallsBackTo-procedure">`fallsBackTo`</span> | `(value: string) => EnvironmentState` | — | The variable is safe to omit, and this is what happens instead. |
57
+ | <span id="core-handedOn-procedure">`handedOn`</span> | `(consequence: string) => EnvironmentState` | — | The variable is legitimately optional with no default, because somebody else decides it, and this is what follows from leaving it unset. |
58
+ | <span id="core-isUlid-procedure">`isUlid`</span> | `(value: string) => value is Ulid` | — | Whether a string is a ULID, as a type guard, so a caller narrows the type without raising anything. |
59
+ | <span id="core-optionalSecret-procedure">`optionalSecret`</span> | `(name: string) => Config.Config<Option.Option<Redacted.Redacted>>` | — | Reads a secret that is legitimately optional, and hands back `Option.none` when it is unset or blank. |
60
+ | <span id="core-optionalText-procedure">`optionalText`</span> | `(name: string) => Config.Config<Option.Option<string>>` | — | Reads a variable that is legitimately optional with no default, because somebody outside this process decides it. |
61
+ | <span id="core-refusalFor-procedure">`refusalFor`</span> | `(name: string, refusal: Refusal) => ConfigError.ConfigError` | — | The one failure a refusing variable raises, with its three parts sewn into a single line. |
62
+ | <span id="core-refusalText-procedure">`refusalText`</span> | `(refusal: Refusal) => string` | — | Sews a refusal into the one line an operator reads in a log or a startup failure. |
63
+ | <span id="core-refuses-procedure">`refuses`</span> | `(refusal: Refusal) => EnvironmentState` | — | The mechanism cannot work without the variable, and this is the three-part text a reader meets when it is missing. |
64
+ | <span id="core-requiredSecret-procedure">`requiredSecret`</span> | `(name: string, refusal: Refusal) => Config.Config<Redacted.Redacted>` | — | Reads a secret a mechanism cannot work without, and refuses in the same three parts when it is missing or blank. |
65
+ | <span id="core-requiredText-procedure">`requiredText`</span> | `(name: string, refusal: Refusal) => Config.Config<string>` | — | Reads a variable that a mechanism cannot work without, and refuses in three parts when it is missing or blank. |
66
+ | <span id="core-ulid-procedure">`ulid`</span> | `(raw: string) => Ulid` | — | Reads a string as a ULID and throws `NotAUlidError` when it is not one, so a raw string comes through one door. |
67
+ | <span id="core-variableNameOf-procedure">`variableNameOf`</span> | `(entry: EnvironmentEntry) => string` | — | The name an operator sets, with `<PREFIX>` standing in front of a suffix the application chooses at mount time. |
68
+ | <span id="core-wholeNumberFallingBackTo-procedure">`wholeNumberFallingBackTo`</span> | `(name: string, lowest: number, highest: number, fallback: number, refusal: Refusal) => Config.Config<number>` | — | Reads a whole number a mechanism is happy to do without, and falls back to the value it names when nobody set the variable. |
69
+ | <span id="core-wholeNumberWithin-procedure">`wholeNumberWithin`</span> | `(name: string, lowest: number, highest: number, refusal: Refusal) => Config.Config<number>` | — | Reads a whole number inside a range, and refuses in three parts when it is not one. |
70
+
71
+ ### Failures
72
+
73
+ | Name | Signature or type | Default | What it is |
74
+ | --- | --- | --- | --- |
75
+ | <span id="core-DomainError-failure">`DomainError`</span> | `Error` | — | Base class for domain errors. |
76
+ | <span id="core-NotAUlidError-failure">`NotAUlidError`</span> | `DomainError` | — | What a caller meets when a string that is not a ULID reaches `ulid`; the message quotes the exact value received. |
77
+
78
+ ## http
79
+
80
+ Import from `@satorio/machinery/http` — [the whole page](../mechanisms/http.mdx).
81
+
82
+ ### Values
83
+
84
+ | Name | Signature or type | Default | What it is |
85
+ | --- | --- | --- | --- |
86
+ | <span id="http-DEFAULT-HEALTH-CHECK-DEADLINE-MILLIS-value">`DEFAULT_HEALTH_CHECK_DEADLINE_MILLIS`</span> | `const` | — | How long one check gets before it counts as down. |
87
+ | <span id="http-HealthCheckStatus-value">`HealthCheckStatus`</span> | `'ok' \| 'down'` | — | How one dependency came back: it answered, or it is down. |
88
+ | <span id="http-HealthRoutesOptions-value">`HealthRoutesOptions`</span> | `interface` | — | What the readiness routes need: the runtime that runs a check, the checks themselves, and the deadline one check gets. |
89
+ | <span id="http-HEALTHZ-PATH-value">`HEALTHZ_PATH`</span> | `const` | — | Same check as READYZ_PATH, under a second name. |
90
+ | <span id="http-LIVEZ-PATH-value">`LIVEZ_PATH`</span> | `const` | — | The path that answers whether this process is alive at all, without checking a single dependency. |
91
+ | <span id="http-NamedHealthCheck-value">`NamedHealthCheck`</span> | `interface` | — | One dependency to check, under the name the answer reports it by. |
92
+ | <span id="http-ReadinessOutcome-value">`ReadinessOutcome`</span> | `interface` | — | What the readiness endpoint answers: whether the service is ready, and how each dependency came back. |
93
+ | <span id="http-READYZ-PATH-value">`READYZ_PATH`</span> | `const` | — | The path that answers whether this service can take traffic, after every mounted dependency has been asked. |
94
+ | <span id="http-RunHealthCheck-value">`RunHealthCheck`</span> | `type` | — | Runs a readiness check and returns its Exit. |
95
+
96
+ ### Procedures
97
+
98
+ | Name | Signature or type | Default | What it is |
99
+ | --- | --- | --- | --- |
100
+ | <span id="http-checkReadiness-procedure">`checkReadiness`</span> | `<R>(options: HealthRoutesOptions<R>) => Effect.Effect<ReadinessOutcome>` | — | Runs every check independently, in parallel, under its own deadline. |
101
+ | <span id="http-healthRoutesFetch-procedure">`healthRoutesFetch`</span> | `<R>(options: HealthRoutesOptions<R>) => ((request: Request) => Promise<Response \| null>)` | — | Handles the three readiness endpoints. |
102
+
103
+ ## money
104
+
105
+ Import from `@satorio/machinery/money` — [the whole page](../mechanisms/money.mdx).
106
+
107
+ ### Values
108
+
109
+ | Name | Signature or type | Default | What it is |
110
+ | --- | --- | --- | --- |
111
+ | <span id="money-Currency-value">`Currency`</span> | `DineroCurrency<bigint>` | — | One currency of the ISO 4217 table: its code, the base it counts in, and how many decimals one unit holds. |
112
+ | <span id="money-ExchangeRate-value">`ExchangeRate`</span> | `interface` | — | How many units of the currency you are going to, one unit of the currency you are coming from buys. |
113
+ | <span id="money-Money-value">`Money`</span> | `Dinero<bigint>` | — | An exact amount of one currency. |
114
+ | <span id="money-Percent-value">`Percent`</span> | `interface` | — | A share of an amount, held exactly. |
115
+ | <span id="money-PercentFromPercentageString-value">`PercentFromPercentageString`</span> | `Schema.Schema<Percent, string>` | — | Reads a share off the wire in the form a price list writes: `30` means thirty percent. |
116
+ | <span id="money-PercentFromRatioString-value">`PercentFromRatioString`</span> | `Schema.Schema<Percent, string>` | — | Reads a share off the wire in the form a table of rates writes: `0.3` means thirty percent. |
117
+
118
+ ### Procedures
119
+
120
+ | Name | Signature or type | Default | What it is |
121
+ | --- | --- | --- | --- |
122
+ | <span id="money-addMoney-procedure">`addMoney`</span> | `(left: Money, right: Money) => Either.Either<Money, CurrenciesDoNotMeetError>` | — | Adds two amounts of one currency. |
123
+ | <span id="money-atRate-procedure">`atRate`</span> | `(amount: Money, target: Currency, rate: ExchangeRate) => Money` | — | Turns an amount into another currency at the rate you name, keeping every digit of the product. |
124
+ | <span id="money-compareMoney-procedure">`compareMoney`</span> | `(left: Money, right: Money) => Either.Either<number, CurrenciesDoNotMeetError>` | — | Puts two amounts of one currency in order. |
125
+ | <span id="money-currencyCodeOf-procedure">`currencyCodeOf`</span> | `(currency: Currency) => string` | — | Writes a currency back as the three letters ISO 4217 gives it. |
126
+ | <span id="money-currencyOf-procedure">`currencyOf`</span> | `(code: string) => Either.Either<Currency, NotACurrencyCodeError>` | — | Reads a currency code somebody wrote: `USD`, `EUR`, `UAH`. |
127
+ | <span id="money-currencyOfMoney-procedure">`currencyOfMoney`</span> | `(amount: Money) => Currency` | — | The currency an amount is counted in. |
128
+ | <span id="money-decimalsOf-procedure">`decimalsOf`</span> | `(currency: Currency) => number` | — | How many decimals one unit of this currency holds: two for a currency counted in cents, zero for one counted in whole units. |
129
+ | <span id="money-exchangeRateFromDecimalForm-procedure">`exchangeRateFromDecimalForm`</span> | `(text: string) => Either.Either<ExchangeRate, NotAnExchangeRateError>` | — | Reads a rate somebody wrote: `0.89`, `41.57306`. |
130
+ | <span id="money-exchangeRateInDecimalForm-procedure">`exchangeRateInDecimalForm`</span> | `(rate: ExchangeRate) => string` | — | Writes a rate back, trimmed, the way the source that published it wrote it: `0.89`. |
131
+ | <span id="money-minorUnitsOf-procedure">`minorUnitsOf`</span> | `(amount: Money) => bigint` | — | The amount counted in the currency's own smallest unit, rounded to it by the one policy this mechanism keeps. |
132
+ | <span id="money-money-procedure">`money`</span> | `(currency: Currency, minorUnits: bigint) => Money` | — | An amount counted in the currency's own smallest unit: 4055 minor units of a currency counted in cents is 40.55. |
133
+ | <span id="money-moneyAtScale-procedure">`moneyAtScale`</span> | `(currency: Currency, units: bigint, scale: bigint) => Money` | — | An amount held at a scale finer than the currency's own, so a calculation drops no digit. |
134
+ | <span id="money-moneyFromDecimalForm-procedure">`moneyFromDecimalForm`</span> | `(currency: Currency, text: string) => Either.Either<Money, NotAnAmountError>` | — | Reads an amount somebody wrote: `40.0455`, `-25`, `0.10`. |
135
+ | <span id="money-MoneyFromDecimalString-procedure">`MoneyFromDecimalString`</span> | `(currency: Currency) => Schema.Schema<Money, string>` | — | Reads and writes an amount on the wire as decimal text, in the currency you name. |
136
+ | <span id="money-moneyInDecimalForm-procedure">`moneyInDecimalForm`</span> | `(amount: Money) => string` | — | Writes an amount for the wire and for a person: `40.0455`, `-25.00`. |
137
+ | <span id="money-negatedMoney-procedure">`negatedMoney`</span> | `(amount: Money) => Money` | — | Turns an amount around: what was owed becomes what is owed back. |
138
+ | <span id="money-percentFromPercentageForm-procedure">`percentFromPercentageForm`</span> | `(text: string) => Either.Either<Percent, NotAPercentError>` | — | Reads the form a price list writes: `30` means thirty percent. |
139
+ | <span id="money-percentFromRatioForm-procedure">`percentFromRatioForm`</span> | `(text: string) => Either.Either<Percent, NotAPercentError>` | — | Reads the form a table of rates writes: `0.3` means thirty percent. |
140
+ | <span id="money-percentInPercentageForm-procedure">`percentInPercentageForm`</span> | `(percent: Percent) => string` | — | Writes the percentage form back, trimmed: thirty percent reads `30`. |
141
+ | <span id="money-percentInRatioForm-procedure">`percentInRatioForm`</span> | `(percent: Percent) => string` | — | Writes the ratio form back, trimmed: thirty percent reads `0.3`. |
142
+ | <span id="money-percentOf-procedure">`percentOf`</span> | `(amount: Money, percent: Percent) => Money` | — | Takes a share of an amount and keeps every digit of the product. |
143
+ | <span id="money-roundedToTheCent-procedure">`roundedToTheCent`</span> | `(amount: Money) => Money` | — | Rounds an amount to the currency's own smallest unit, half away from zero. |
144
+ | <span id="money-sameMoney-procedure">`sameMoney`</span> | `(left: Money, right: Money) => boolean` | — | Whether two amounts are the same amount. |
145
+ | <span id="money-samePercent-procedure">`samePercent`</span> | `(left: Percent, right: Percent) => boolean` | — | Whether two shares are the same share, whichever form each was read from. |
146
+ | <span id="money-scaleOfMoney-procedure">`scaleOfMoney`</span> | `(amount: Money) => bigint` | — | The scale an amount is currently held at: how many decimals its own units are counted in, which grows as a calculation keeps precision. |
147
+ | <span id="money-sharesOf-procedure">`sharesOf`</span> | `(amount: Money, proportions: readonly bigint[]) => Either.Either<readonly Money[], ProportionsDoNotSplitError>` | — | Splits an amount into shares that add back up to exactly what went in. |
148
+ | <span id="money-sumOfMoney-procedure">`sumOfMoney`</span> | `(currency: Currency, amounts: readonly Money[]) => Either.Either<Money, CurrenciesDoNotMeetError>` | — | Adds up any number of amounts, starting from nothing in the currency you name. |
149
+ | <span id="money-zeroMoney-procedure">`zeroMoney`</span> | `(currency: Currency) => Money` | — | Nothing at all, in one currency. |
150
+
151
+ ### Failures
152
+
153
+ | Name | Signature or type | Default | What it is |
154
+ | --- | --- | --- | --- |
155
+ | <span id="money-CurrenciesDoNotMeetError-failure">`CurrenciesDoNotMeetError`</span> | `Data.TaggedError<{ readonly left: string; readonly right: string }>` | — | Two amounts in two currencies were asked to meet. |
156
+ | <span id="money-MoneyFailure-failure">`MoneyFailure`</span> | `type` | — | Every way this mechanism refuses a value. |
157
+ | <span id="money-NotACurrencyCodeError-failure">`NotACurrencyCodeError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The text handed in does not name a currency this mechanism knows. |
158
+ | <span id="money-NotAnAmountError-failure">`NotAnAmountError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The text handed in does not write an amount. |
159
+ | <span id="money-NotAnExchangeRateError-failure">`NotAnExchangeRateError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The text handed in does not write an exchange rate. |
160
+ | <span id="money-NotAPercentError-failure">`NotAPercentError`</span> | `Data.TaggedError<{ readonly text: string; readonly form: 'percentage' \| 'ratio' }>` | — | The text handed in does not write a percent. |
161
+ | <span id="money-ProportionsDoNotSplitError-failure">`ProportionsDoNotSplitError`</span> | `Data.TaggedError<{ readonly proportions: readonly bigint[] }>` | — | The proportions handed in cannot split an amount. |
162
+
163
+ ## ports
164
+
165
+ Import from `@satorio/machinery/ports` — [the whole page](../mechanisms/ports.mdx).
166
+
167
+ ### Values
168
+
169
+ | Name | Signature or type | Default | What it is |
170
+ | --- | --- | --- | --- |
171
+ | <span id="ports-BlobStoreShape-value">`BlobStoreShape`</span> | `interface` | — | The blob store's operations. |
172
+ | <span id="ports-claimAccepted-value">`claimAccepted`</span> | `ProcessedEventClaim` | — | The claim nobody had taken yet, so this run is the one that does the work. |
173
+ | <span id="ports-ClaimProcessedEventInput-value">`ClaimProcessedEventInput`</span> | `interface` | — | What a claim needs: which event is being claimed, and the moment it is claimed at. |
174
+ | <span id="ports-DocumentNumberCounterShape-value">`DocumentNumberCounterShape`</span> | `interface` | — | What the counter offers: one call that moves a client's month on and hands back the count the next document takes. |
175
+ | <span id="ports-DocumentNumberCountInput-value">`DocumentNumberCountInput`</span> | `interface` | — | Which counter to move on: one client, one reporting month. |
176
+ | <span id="ports-EventPublisherShape-value">`EventPublisherShape`</span> | `interface` | — | What a publisher offers: one call that sends a batch of outbox messages out of this service. |
177
+ | <span id="ports-ExternalHttpClientShape-value">`ExternalHttpClientShape`</span> | `interface` | — | One external HTTP service, read through one operation. |
178
+ | <span id="ports-IntegrationEventOutboxShape-value">`IntegrationEventOutboxShape`</span> | `interface` | — | The outbox holds messages a use case enqueues in the same transaction as its state change. |
179
+ | <span id="ports-OutboxMessage-value">`OutboxMessage`</span> | `interface` | — | One message waiting in the outbox: its own id, what it is, which schema shaped it, when it happened, and what it carries. |
180
+ | <span id="ports-PORT-FAILURES-IN-THE-EVENTS-LANGUAGE-value">`PORT_FAILURES_IN_THE_EVENTS_LANGUAGE`</span> | `Readonly<Record<string, string>>` | — | A port failure named in the event's language rather than as `<Port>UnavailableError`, with the sentence that earns the exception. |
181
+ | <span id="ports-ProcessedEventClaim-value">`ProcessedEventClaim`</span> | `type` | — | The two states of the claim-once lock: this run took the event, or somebody already had. |
182
+ | <span id="ports-ProcessedEventRegistryShape-value">`ProcessedEventRegistryShape`</span> | `interface` | — | What the claim-once lock offers: one call that either takes an event for the first time or says when it was taken before. |
183
+ | <span id="ports-QueueMessageProducerShape-value">`QueueMessageProducerShape`</span> | `interface` | — | What a producer offers: one call that puts a message body onto the queue. |
184
+ | <span id="ports-QueueMessageSourceShape-value">`QueueMessageSourceShape`</span> | `interface` | — | A source of queue messages: it receives a batch and acknowledges what was taken. |
185
+ | <span id="ports-RawQueueMessage-value">`RawQueueMessage`</span> | `interface` | — | One message as the queue hands it over: its own id, the receipt an acknowledgement quotes, and the body, still text. |
186
+ | <span id="ports-ReadinessProbeShape-value">`ReadinessProbeShape`</span> | `interface` | — | What a readiness probe offers: one check that the database answers, so the endpoint reports a dependency rather than a guess. |
187
+ | <span id="ports-StoredBlob-value">`StoredBlob`</span> | `interface` | — | A stored blob's bytes, content type, and free-form text metadata. |
188
+ | <span id="ports-TransactionBoundaryShape-value">`TransactionBoundaryShape`</span> | `interface` | — | What a transaction boundary offers: one call that runs work inside a transaction, and rolls the whole of it back when the work fails. |
189
+
190
+ ### Procedures
191
+
192
+ | Name | Signature or type | Default | What it is |
193
+ | --- | --- | --- | --- |
194
+ | <span id="ports-alreadyProcessed-procedure">`alreadyProcessed`</span> | `(processedAt: DateTime.Utc) => ProcessedEventClaim` | — | The claim somebody else already took, with the moment they took it. |
195
+ | <span id="ports-portUnavailable-procedure">`portUnavailable`</span> | `<E>(Unavailable: new (fields: { readonly operation: string; readonly cause: unknown }) => E)` | — | Builds the "did not answer" failure factory around one port's own `<Port>UnavailableError` constructor. |
196
+
197
+ ### Ports
198
+
199
+ | Name | Signature or type | Default | What it is |
200
+ | --- | --- | --- | --- |
201
+ | <span id="ports-BlobStore-port">`BlobStore`</span> | `Context.Tag('BlobStore')` | — | The port a use case asks for when it stores whole objects under a key and reads them back. |
202
+ | <span id="ports-DocumentNumberCounter-port">`DocumentNumberCounter`</span> | `Context.Tag('DocumentNumberCounter')` | — | The port a use case asks for when it numbers a document a person will read. |
203
+ | <span id="ports-EventPublisher-port">`EventPublisher`</span> | `Context.Tag('EventPublisher')` | — | The port the outbox relay asks for when it announces what has already happened. |
204
+ | <span id="ports-ExternalHttpClient-port">`ExternalHttpClient`</span> | `Context.Tag('ExternalHttpClient')` | — | The port a use case asks for when it reads reference data from a service outside this one. |
205
+ | <span id="ports-IntegrationEventOutbox-port">`IntegrationEventOutbox`</span> | `Context.Tag( 'IntegrationEventOutbox', )` | — | The port a use case asks for when it enqueues an event in the same transaction as the state change that caused it. |
206
+ | <span id="ports-ProcessedEventRegistry-port">`ProcessedEventRegistry`</span> | `Context.Tag( 'ProcessedEventRegistry', )` | — | The port a use case asks for when an event must be acted on exactly once, however many times it arrives. |
207
+ | <span id="ports-QueueMessageProducer-port">`QueueMessageProducer`</span> | `Context.Tag('QueueMessageProducer')` | — | The port a use case asks for when it sends a message to a queue. |
208
+ | <span id="ports-QueueMessageSource-port">`QueueMessageSource`</span> | `Context.Tag('QueueMessageSource')` | — | The port a consumer asks for when it receives messages from a queue and acknowledges what it took. |
209
+ | <span id="ports-ReadinessProbe-port">`ReadinessProbe`</span> | `Context.Tag('ReadinessProbe')` | — | The port the readiness endpoint asks for when it has to say whether this service can take traffic. |
210
+ | <span id="ports-TransactionBoundary-port">`TransactionBoundary`</span> | `Context.Tag('TransactionBoundary')` | — | The port a use case asks for when its writes must land together or not at all. |
211
+
212
+ ### Failures
213
+
214
+ | Name | Signature or type | Default | What it is |
215
+ | --- | --- | --- | --- |
216
+ | <span id="ports-BlobStoreUnavailableError-failure">`BlobStoreUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The object store did not answer; a key that is not there at all is never this failure. |
217
+ | <span id="ports-DatabaseDidNotAnswerError-failure">`DatabaseDidNotAnswerError`</span> | `Data.TaggedError<{ readonly reason: string }>` | — | The readiness check against the database did not come back; `reason` says what stopped it. |
218
+ | <span id="ports-DocumentNumberCounterUnavailableError-failure">`DocumentNumberCounterUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The counter behind a document number did not answer; `operation` names the call and `cause` carries the driver's own error. |
219
+ | <span id="ports-EventPublisherUnavailableError-failure">`EventPublisherUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The publisher did not answer, or no topic is configured; `cause` says which of the two it was. |
220
+ | <span id="ports-ExternalServiceRefusedError-failure">`ExternalServiceRefusedError`</span> | `Data.TaggedError<{ readonly service: string; readonly operation: string; readonly status: number }>` | — | The external service answered with a refusal of its own, so the same request will fail again until the request changes. |
221
+ | <span id="ports-ExternalServiceResponseMalformedError-failure">`ExternalServiceResponseMalformedError`</span> | `Data.TaggedError<{ readonly service: string; readonly operation: string; readonly cause: unknown }>` | — | The external service answered, but the body did not fit the schema the caller handed in. |
222
+ | <span id="ports-ExternalServiceUnavailableError-failure">`ExternalServiceUnavailableError`</span> | `Data.TaggedError<{ readonly service: string; readonly operation: string; readonly cause: unknown }>` | — | A network failure, a timeout, or a server error after the retries ran out; the same request may well succeed later. |
223
+ | <span id="ports-IntegrationEventOutboxUnavailableError-failure">`IntegrationEventOutboxUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The outbox driver did not answer; `operation` names the call and `cause` carries the driver's own error. |
224
+ | <span id="ports-ProcessedEventRegistryUnavailableError-failure">`ProcessedEventRegistryUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The claim-once driver did not answer; `operation` names the call and `cause` carries the driver's own error. |
225
+ | <span id="ports-QueueMessageProducerUnavailableError-failure">`QueueMessageProducerUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The queue producer did not answer; `operation` names the call and `cause` carries the driver's own error. |
226
+ | <span id="ports-QueueMessageSourceUnavailableError-failure">`QueueMessageSourceUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The queue source did not answer; `operation` names the call and `cause` carries the driver's own error. |
227
+ | <span id="ports-TransactionBoundaryUnavailableError-failure">`TransactionBoundaryUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | The transaction driver did not answer; `operation` names the call and `cause` carries the driver's own error. |
228
+
229
+ ## time
230
+
231
+ Import from `@satorio/machinery/time` — [the whole page](../mechanisms/time.mdx).
232
+
233
+ ### Values
234
+
235
+ | Name | Signature or type | Default | What it is |
236
+ | --- | --- | --- | --- |
237
+ | <span id="time-CalendarDay-value">`CalendarDay`</span> | `type` | — | One day of the calendar, with no time and no zone in it. |
238
+ | <span id="time-CalendarDayFromHumanString-value">`CalendarDayFromHumanString`</span> | `Schema.Schema<CalendarDay, string>` | — | Reads a day off the wire from the form a person writes, and writes it back in that same form. |
239
+ | <span id="time-CalendarDayOrder-value">`CalendarDayOrder`</span> | `Order.Order<CalendarDay>` | — | Puts two days in calendar order, earliest first. |
240
+ | <span id="time-CalendarDayRefusalReason-value">`CalendarDayRefusalReason`</span> | `type` | — | Why a written day is not a calendar day. |
241
+ | <span id="time-Instant-value">`Instant`</span> | `interface` | — | One moment on the world's clock, held as whole milliseconds since the start of 1970. |
242
+ | <span id="time-Period-value">`Period`</span> | `interface` | — | A run of calendar days. |
243
+ | <span id="time-TimeZone-value">`TimeZone`</span> | `type` | — | One named time zone, as the runtime's own zone table knows it. |
244
+
245
+ ### Procedures
246
+
247
+ | Name | Signature or type | Default | What it is |
248
+ | --- | --- | --- | --- |
249
+ | <span id="time-addDays-procedure">`addDays`</span> | `(day: CalendarDay, days: number) => CalendarDay` | — | Moves a day by whole days. |
250
+ | <span id="time-addMonths-procedure">`addMonths`</span> | `(day: CalendarDay, months: number) => CalendarDay` | — | Moves a day by whole months, landing on the last day of a month too short to hold it. |
251
+ | <span id="time-calendarDayFromHumanForm-procedure">`calendarDayFromHumanForm`</span> | `(text: string) => Either.Either<CalendarDay, NotACalendarDayError>` | — | Reads the form a person writes a day in: `19.03.2026`. |
252
+ | <span id="time-calendarDayFromIsoForm-procedure">`calendarDayFromIsoForm`</span> | `(text: string) => Either.Either<CalendarDay, NotACalendarDayError>` | — | Reads the form a machine writes a day in: `2026-03-19`. |
253
+ | <span id="time-dateTimeOfInstant-procedure">`dateTimeOfInstant`</span> | `(instant: Instant) => DateTime.Utc` | — | Hands a moment back as Effect's own UTC value, for a row, an envelope, or any code that already speaks that type. |
254
+ | <span id="time-dayInHumanForm-procedure">`dayInHumanForm`</span> | `(day: CalendarDay) => string` | — | Writes a day the way a person reads it: `19.03.2026`. |
255
+ | <span id="time-dayInIsoForm-procedure">`dayInIsoForm`</span> | `(day: CalendarDay) => string` | — | Writes a day the way a machine reads it: `2026-03-19`. |
256
+ | <span id="time-dayOfInstant-procedure">`dayOfInstant`</span> | `(instant: Instant, zone: TimeZone) => CalendarDay` | — | The calendar day a moment falls on for a person standing in that zone. |
257
+ | <span id="time-daysBetween-procedure">`daysBetween`</span> | `(earlier: CalendarDay, later: CalendarDay) => number` | — | Counts whole days from the first day to the second. |
258
+ | <span id="time-instantInHumanForm-procedure">`instantInHumanForm`</span> | `(instant: Instant, zone: TimeZone) => string` | — | Writes a moment the way a person in that zone reads it: `19.03.2026 14:05 +02:00`. |
259
+ | <span id="time-instantOfDateTime-procedure">`instantOfDateTime`</span> | `(moment: DateTime.Utc) => Instant` | — | Takes a moment the machinery already holds as Effect's own UTC value. |
260
+ | <span id="time-lastDayOfTheMonthOf-procedure">`lastDayOfTheMonthOf`</span> | `(day: CalendarDay) => CalendarDay` | — | The last day of the month the given day falls in. |
261
+ | <span id="time-lengthInDays-procedure">`lengthInDays`</span> | `(period: Period) => number` | — | Counts the days a period holds, both bounds included. |
262
+ | <span id="time-monthOf-procedure">`monthOf`</span> | `(day: CalendarDay) => Period` | — | The whole calendar month the given day falls in, as a period. |
263
+ | <span id="time-monthsOf-procedure">`monthsOf`</span> | `(period: Period) => readonly Period[]` | — | Cuts a period into one part per calendar month it runs over, in order. |
264
+ | <span id="time-periodContains-procedure">`periodContains`</span> | `(period: Period, day: CalendarDay) => boolean` | — | Answers whether the day belongs to the period. |
265
+ | <span id="time-periodOf-procedure">`periodOf`</span> | `(from: CalendarDay, to: CalendarDay) => Either.Either<Period, PeriodEndsBeforeItStartsError>` | — | Takes two days as a period, earliest first. |
266
+ | <span id="time-periodsOverlap-procedure">`periodsOverlap`</span> | `(left: Period, right: Period) => boolean` | — | Answers whether two periods share at least one day. |
267
+ | <span id="time-startOfDay-procedure">`startOfDay`</span> | `(day: CalendarDay, zone: TimeZone) => Instant` | — | The moment a calendar day begins in that zone. |
268
+ | <span id="time-todayIn-procedure">`todayIn`</span> | `(zone: TimeZone) => Effect.Effect<CalendarDay>` | — | Today, as the calendar of that zone counts it, read from the clock the service already shares. |
269
+ | <span id="time-zoneIdOf-procedure">`zoneIdOf`</span> | `(zone: TimeZone) => string` | — | Reads the IANA name back out of a zone, for a log line or a row. |
270
+ | <span id="time-zoneNamed-procedure">`zoneNamed`</span> | `(zoneId: string) => Either.Either<TimeZone, UnknownTimeZoneError>` | — | Takes an IANA zone name, and refuses a name the runtime does not know. |
271
+
272
+ ### Failures
273
+
274
+ | Name | Signature or type | Default | What it is |
275
+ | --- | --- | --- | --- |
276
+ | <span id="time-NotACalendarDayError-failure">`NotACalendarDayError`</span> | `Data.TaggedError<{ readonly text: string; readonly reason: CalendarDayRefusalReason }>` | — | The text a reader was handed does not name a day any calendar holds. |
277
+ | <span id="time-PeriodEndsBeforeItStartsError-failure">`PeriodEndsBeforeItStartsError`</span> | `Data.TaggedError<{ readonly from: string; readonly to: string }>` | — | The two days handed in run backwards. |
278
+ | <span id="time-TimeFailure-failure">`TimeFailure`</span> | `type` | — | Every way this mechanism refuses a value. |
279
+ | <span id="time-UnknownTimeZoneError-failure">`UnknownTimeZoneError`</span> | `Data.TaggedError<{ readonly zoneId: string }>` | — | The runtime has no zone under that name. |
280
+
281
+ ## identifiers
282
+
283
+ Import from `@satorio/machinery/identifiers` — [the whole page](../mechanisms/identifiers.mdx).
284
+
285
+ ### Values
286
+
287
+ | Name | Signature or type | Default | What it is |
288
+ | --- | --- | --- | --- |
289
+ | <span id="identifiers-ClientCode-value">`ClientCode`</span> | `string & { readonly [clientCodeBrand]: 'ClientCode' }` | — | The number a client quotes back to you: eight digits, the last of which checks the other seven. |
290
+ | <span id="identifiers-CreditorReference-value">`CreditorReference`</span> | `type` | — | The reference a payer copies into a bank transfer, with its own check digits. |
291
+ | <span id="identifiers-DocumentNumber-value">`DocumentNumber`</span> | `type` | — | The number printed on a document, in the form a person reads it. |
292
+ | <span id="identifiers-DocumentNumberParts-value">`DocumentNumberParts`</span> | `interface` | — | What a document number is made of. |
293
+ | <span id="identifiers-DocumentNumbers-value">`DocumentNumbers`</span> | `interface` | — | The document numbers of one closed set of series: minting bound to that set, reading that refuses any series outside it, and the set itself, so a caller lists its own series in one place and reads them back from the same one. |
294
+ | <span id="identifiers-newClientCode-value">`newClientCode`</span> | `Effect.Effect<ClientCode>` | — | A fresh client code, drawn from the randomness the service already shares. |
295
+ | <span id="identifiers-newUlid-value">`newUlid`</span> | `Effect.Effect<Ulid>` | — | A fresh identifier, minted from the clock and the randomness the service already shares. |
296
+ | <span id="identifiers-NextDocumentNumberInput-value">`NextDocumentNumberInput`</span> | `interface` | — | Which document to number: its series, who it goes to, and the month it reports on. |
297
+ | <span id="identifiers-ulidsInOrder-value">`ulidsInOrder`</span> | `Effect.Effect<Effect.Effect<Ulid>>` | — | A maker of identifiers that keep their order even when two of them land inside one millisecond. |
298
+
299
+ ### Procedures
300
+
301
+ | Name | Signature or type | Default | What it is |
302
+ | --- | --- | --- | --- |
303
+ | <span id="identifiers-clientCodeFrom-procedure">`clientCodeFrom`</span> | `(text: string) => Either.Either<ClientCode, NotAClientCodeError>` | — | Reads a client code somebody typed, forgiving the spaces and hyphens a person puts between the groups. |
304
+ | <span id="identifiers-clientCodeInGroupedForm-procedure">`clientCodeInGroupedForm`</span> | `(code: ClientCode) => string` | — | The form a person reads off a document: two groups of four. |
305
+ | <span id="identifiers-clientCodeOfDocumentNumber-procedure">`clientCodeOfDocumentNumber`</span> | `(number: DocumentNumber) => ClientCode` | — | The client code printed inside a document number. |
306
+ | <span id="identifiers-creditorReferenceFrom-procedure">`creditorReferenceFrom`</span> | `(text: string) => Either.Either<CreditorReference, NotACreditorReferenceError>` | — | Reads a reference somebody typed, forgiving case, spaces and the hyphens a person copies along with it. |
307
+ | <span id="identifiers-creditorReferenceInGroupedForm-procedure">`creditorReferenceInGroupedForm`</span> | `(reference: CreditorReference) => string` | — | The form a person reads off a document and types into a bank: groups of four, the way ISO 11649 prints one. |
308
+ | <span id="identifiers-creditorReferenceOf-procedure">`creditorReferenceOf`</span> | `(number: DocumentNumber) => CreditorReference` | — | The payment reference for a document that somebody has to pay. |
309
+ | <span id="identifiers-dammCheckDigit-procedure">`dammCheckDigit`</span> | `(digits: string) => string \| null` | — | The check digit that makes a run of digits self-checking, by Damm's algorithm. |
310
+ | <span id="identifiers-dammHolds-procedure">`dammHolds`</span> | `(digits: string) => boolean` | — | Whether a run of digits already carries a check digit that holds. |
311
+ | <span id="identifiers-digitsOfClientCode-procedure">`digitsOfClientCode`</span> | `(code: ClientCode) => string` | — | The eight digits with nothing between them, which is the form a document number and a payment reference are built from. |
312
+ | <span id="identifiers-digitsOfCreditorReference-procedure">`digitsOfCreditorReference`</span> | `(reference: CreditorReference) => string` | — | The digits of the document number this reference points at. |
313
+ | <span id="identifiers-digitsOfDocumentNumber-procedure">`digitsOfDocumentNumber`</span> | `(number: DocumentNumber) => string` | — | The digits of a document number with the series and the hyphens taken off, which is what a payment reference is built over. |
314
+ | <span id="identifiers-makeDocumentNumbers-procedure">`makeDocumentNumbers`</span> | `<const Series extends readonly string[]>(series: ClosedSet<Series>) => DocumentNumbers<Series>` | — | Binds document numbers to the series one service issues. |
315
+ | <span id="identifiers-reportingMonthOf-procedure">`reportingMonthOf`</span> | `(day: CalendarDay) => string` | — | The two digits of year and two of month a reporting period is written as: March 2026 reads `2603`. |
316
+ | <span id="identifiers-ulidOfSeed-procedure">`ulidOfSeed`</span> | `(moment: DateTime.Utc, seed: string) => Ulid` | — | The identifier a moment and a seed always mint the same way. |
317
+ | <span id="identifiers-withDammCheckDigit-procedure">`withDammCheckDigit`</span> | `(digits: string) => string \| null` | — | The same digits with their check digit written on the end. |
318
+
319
+ ### Failures
320
+
321
+ | Name | Signature or type | Default | What it is |
322
+ | --- | --- | --- | --- |
323
+ | <span id="identifiers-IdentifierFailure-failure">`IdentifierFailure`</span> | `type` | — | Every way this mechanism refuses a value. |
324
+ | <span id="identifiers-NotAClientCodeError-failure">`NotAClientCodeError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The text handed in is not a client code. |
325
+ | <span id="identifiers-NotACreditorReferenceError-failure">`NotACreditorReferenceError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The text handed in is not a payment reference this mechanism issued. |
326
+ | <span id="identifiers-NotADocumentNumberError-failure">`NotADocumentNumberError`</span> | `Data.TaggedError<{ readonly text: string }>` | — | The parts handed in cannot make a document number, or the text handed in does not read as one. |
327
+
328
+ ## workflow
329
+
330
+ Import from `@satorio/machinery/workflow` — [the whole page](../mechanisms/workflow.mdx).
331
+
332
+ ### Values
333
+
334
+ | Name | Signature or type | Default | What it is |
335
+ | --- | --- | --- | --- |
336
+ | <span id="workflow-ClaimOnce-value">`ClaimOnce`</span> | `type` | — | The exactly-once claim: shared ground for every use case that takes an event or command once. |
337
+ | <span id="workflow-DEFAULT-PUBLISH-PENDING-EVENTS-SETTINGS-value">`DEFAULT_PUBLISH_PENDING_EVENTS_SETTINGS`</span> | `PublishPendingEventsSettings` | — | The pace the relay keeps when a service names none of its own. |
338
+ | <span id="workflow-OnClaimMatchers-value">`OnClaimMatchers`</span> | `interface` | — | The two branches `onClaim` takes: what to do when the event was already claimed, and what to do when this run claims it. |
339
+ | <span id="workflow-PublishPendingEventsSettings-value">`PublishPendingEventsSettings`</span> | `interface` | — | How the relay paces itself: how many messages one beat takes, and how long it waits between beats. |
340
+ | <span id="workflow-UpcastStep-value">`UpcastStep`</span> | `interface` | — | One lift, from the version it names to the next one up. |
341
+ | <span id="workflow-VersionedEventDefinition-value">`VersionedEventDefinition`</span> | `interface` | — | An event stored yesterday is read by today's code. |
342
+
343
+ ### Procedures
344
+
345
+ | Name | Signature or type | Default | What it is |
346
+ | --- | --- | --- | --- |
347
+ | <span id="workflow-claimAsProcessedAt-procedure">`claimAsProcessedAt`</span> | `(idempotencyKey: string, processedAt: DateTime.Utc) => ClaimOnce` | — | Claims with a processedAt supplied by the caller, for a handler that has already read the clock and must store that exact moment. |
348
+ | <span id="workflow-claimAsProcessedNow-procedure">`claimAsProcessedNow`</span> | `(idempotencyKey: string) => ClaimOnce` | — | Claims with the current time, for a caller that only needs the claim. |
349
+ | <span id="workflow-decodeStoredPayload-procedure">`decodeStoredPayload`</span> | `<S extends Schema.Schema.AnyNoContext>(definition: VersionedEventDefinition<S>, storedVersion: number, payload: unknown) => Effect.Effect<Schema.Schema.Type<S>, VersionedPayloadFailure \| ParseResult.ParseError>` | — | Lifts a stored payload to the current version and decodes it with the current schema. |
350
+ | <span id="workflow-keepPublishingPendingEvents-procedure">`keepPublishingPendingEvents`</span> | `(settings: PublishPendingEventsSettings = DEFAULT_PUBLISH_PENDING_EVENTS_SETTINGS) => Effect.Effect<never, never, IntegrationEventOutbox \| EventPublisher>` | — | Runs the outbox relay for as long as the service lives. |
351
+ | <span id="workflow-onClaim-procedure">`onClaim`</span> | `<A1, E1, R1, A2, E2, R2, EClaim, RClaim>(claim: Effect.Effect<ProcessedEventClaim, EClaim, RClaim>, matchers: OnClaimMatchers<A1, E1, R1, A2, E2, R2>) => Effect.Effect<A1 \| A2, EClaim \| E1 \| E2, RClaim \| R1 \| R2>` | — | Branches on the state of the exactly-once claim: AlreadyProcessed goes one way, ClaimAccepted the other. |
352
+ | <span id="workflow-publishOneBatch-procedure">`publishOneBatch`</span> | `(batchLimit: number) => Effect.Effect<number, PublishPendingEventsFailure, IntegrationEventOutbox \| EventPublisher>` | — | One outbox relay beat: take a batch of undelivered messages, hand it to the publisher, then mark it dispatched. |
353
+ | <span id="workflow-transactionally-procedure">`transactionally`</span> | `<A, E, R>(work: Effect.Effect<A, E, R>)` | — | Wraps work in a transaction boundary: pulls TransactionBoundary from context and runs the work through it. |
354
+ | <span id="workflow-upcastToCurrentVersion-procedure">`upcastToCurrentVersion`</span> | `<S extends Schema.Schema.AnyNoContext>(definition: VersionedEventDefinition<S>, storedVersion: number, payload: unknown) => Effect.Effect<unknown, VersionedPayloadFailure>` | — | Lifts a stored payload from the version it was written at to the version this code reads, one step per version, in order. |
355
+
356
+ ### Failures
357
+
358
+ | Name | Signature or type | Default | What it is |
359
+ | --- | --- | --- | --- |
360
+ | <span id="workflow-MissingUpcastStepError-failure">`MissingUpcastStepError`</span> | `Data.TaggedError<{ readonly eventType: string; readonly fromVersion: number; readonly currentVersion: number }>` | — | One version between the stored payload and the current one has no upcast step, so the lift cannot finish. |
361
+ | <span id="workflow-PublishPendingEventsFailure-failure">`PublishPendingEventsFailure`</span> | `type` | — | What one beat of the relay can meet: the outbox did not answer, or the publisher did not. |
362
+ | <span id="workflow-SchemaVersionFromTheFutureError-failure">`SchemaVersionFromTheFutureError`</span> | `Data.TaggedError<{ readonly eventType: string; readonly storedVersion: number; readonly currentVersion: number }>` | — | The stored payload says it was written by a newer version of this code than the one reading it. |
363
+ | <span id="workflow-UpcastStepFailedError-failure">`UpcastStepFailedError`</span> | `Data.TaggedError<{ readonly eventType: string; readonly fromVersion: number; readonly cause: unknown }>` | — | An upcast step threw while lifting the payload one version up. |
364
+ | <span id="workflow-VersionedPayloadFailure-failure">`VersionedPayloadFailure`</span> | `type` | — | Every way reading a stored payload can refuse. |
365
+
366
+ ## graphql
367
+
368
+ Import from `@satorio/machinery/graphql` — [the whole page](../mechanisms/graphql.mdx).
369
+
370
+ ### Values
371
+
372
+ | Name | Signature or type | Default | What it is |
373
+ | --- | --- | --- | --- |
374
+ | <span id="graphql-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
375
+ | <span id="graphql-EveryFailureIsClassified-value">`EveryFailureIsClassified`</span> | `type` | — | The proof that every failure a service can raise is mapped at this boundary. |
376
+ | <span id="graphql-graphiqlEnabledFromEnvironment-value">`graphiqlEnabledFromEnvironment`</span> | `Config.Config<boolean>` | — | Whether to serve the editor page. |
377
+ | <span id="graphql-GraphiqlPage-value">`GraphiqlPage`</span> | `interface` | — | A GraphiQL page: a title and a pre-filled document. |
378
+ | <span id="graphql-GRAPHQL-ENDPOINT-value">`GRAPHQL_ENDPOINT`</span> | `const` | — | The one path the GraphQL endpoint answers on. |
379
+ | <span id="graphql-GraphQLContext-value">`GraphQLContext`</span> | `interface` | — | What a resolver reads from its context: one call that runs a use case's program and answers with its value or a `GraphQLError`. |
380
+ | <span id="graphql-graphqlPortFromEnvironment-value">`graphqlPortFromEnvironment`</span> | `Config.Config<number>` | — | The port to listen on. |
381
+ | <span id="graphql-RunOperationsExit-value">`RunOperationsExit`</span> | `type` | — | The minimal capability a resolver borrows from the runtime: run a program that needs `R` and return its `Exit`. |
382
+
383
+ ### Procedures
384
+
385
+ | Name | Signature or type | Default | What it is |
386
+ | --- | --- | --- | --- |
387
+ | <span id="graphql-asGraphQLError-procedure">`asGraphQLError`</span> | `(failure: OperationFailure \| ParseResult.ParseError) => GraphQLError` | — | Maps a GraphQL failure to a `GraphQLError`: the same three-class operation failure channel, plus input decoder failures — no second catalog. |
388
+ | <span id="graphql-graphiqlExampleProblems-procedure">`graphiqlExampleProblems`</span> | `(schema: GraphQLSchema, page: GraphiqlPage) => readonly GraphiqlExampleProblem[]` | — | Checks a GraphiQL page's default query against a schema. |
389
+ | <span id="graphql-graphqlContextFrom-procedure">`graphqlContextFrom`</span> | `<R>(runExit: RunOperationsExit<R>) => GraphQLContext<R>` | — | Builds that context around the runtime's own `runPromiseExit`, so a resolver never touches the runtime directly. |
390
+ | <span id="graphql-makeSubGraphSchemaBuilder-procedure">`makeSubGraphSchemaBuilder`</span> | `<Context extends object>()` | — | Returns a builder factory carrying the resolver context type. |
391
+ | <span id="graphql-makeYogaServer-procedure">`makeYogaServer`</span> | `<R>(options: GraphQLServerOptions<R>) => YogaServerInstance<Record<string, never>, GraphQLContext<R>>` | — | Builds a Yoga GraphQL server for Bun. |
392
+ | <span id="graphql-serverCannotListen-procedure">`serverCannotListen`</span> | `(port: number, cause: unknown) => ServerCannotListenError` | — | Turns whatever the runtime threw while opening the socket into the named failure a caller reads. |
393
+
394
+ ### Adapters
395
+
396
+ | Name | Signature or type | Default | What it is |
397
+ | --- | --- | --- | --- |
398
+ | <span id="graphql-graphqlServerLive-adapter">`graphqlServerLive`</span> | `<R>(options: GraphQLRequestHandlerOptions<R>) => Layer.Layer<never, ConfigError.ConfigError \| ServerCannotListenError, R>` | — | The one layer this mechanism mounts: the server that answers your operations. |
399
+
400
+ ### Failures
401
+
402
+ | Name | Signature or type | Default | What it is |
403
+ | --- | --- | --- | --- |
404
+ | <span id="graphql-OperationFailure-failure">`OperationFailure`</span> | `type` | — | Everything a resolver may fail with, as one closed set: not found, rejected, or unavailable. |
405
+ | <span id="graphql-OperationRejectedError-failure">`OperationRejectedError`</span> | `Data.TaggedError<{ readonly rule: string; readonly reason: string; readonly detail: string }>` | — | A resolver's rule rejected the operation, and `reason` names the cause it recognized. |
406
+ | <span id="graphql-OperationsUnavailableError-failure">`OperationsUnavailableError`</span> | `Data.TaggedError<{ readonly operation: string; readonly cause: unknown }>` | — | A resolver's own dependency did not answer; `cause` carries the port's own failure. |
407
+ | <span id="graphql-ServerCannotListenError-failure">`ServerCannotListenError`</span> | `Data.TaggedError<{ readonly port: number; readonly refusal: Refusal; readonly cause: unknown }>` | — | The socket never opened. |
408
+ | <span id="graphql-SubjectNotFoundError-failure">`SubjectNotFoundError`</span> | `Data.TaggedError<{ readonly subject: string; readonly id: string }>` | — | One of exactly three operation failure classes below — the closed set a resolver maps to. |
409
+
410
+ ### Environment variables
411
+
412
+ | Name | Signature or type | Default | What it is |
413
+ | --- | --- | --- | --- |
414
+ | <span id="graphql-GRAPHQL-PORT-environment-variable">`GRAPHQL_PORT`</span> | `falls back` | `4000` | The port the GraphQL endpoint and the readiness probes listen on. |
415
+ | <span id="graphql-GRAPHIQL-ENABLED-environment-variable">`GRAPHIQL_ENABLED`</span> | `falls back` | `true` | Whether the GraphiQL editor page is served on the same endpoint. |
416
+
417
+ ## integration
418
+
419
+ Import from `@satorio/machinery/integration` — [the whole page](../mechanisms/integration.mdx).
420
+
421
+ ### Values
422
+
423
+ | Name | Signature or type | Default | What it is |
424
+ | --- | --- | --- | --- |
425
+ | <span id="integration-DEFAULT-TIMEOUT-MILLIS-value">`DEFAULT_TIMEOUT_MILLIS`</span> | `const` | — | How long one call may take when nobody names a number. |
426
+ | <span id="integration-defaultExternalRetrySchedule-value">`defaultExternalRetrySchedule`</span> | `Schedule.Schedule<unknown, unknown>` | — | How a call waits and tries again: growing pauses, jittered, on a short budget. |
427
+ | <span id="integration-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
428
+ | <span id="integration-ExternalServiceSettings-value">`ExternalServiceSettings`</span> | `interface` | — | What a client needs before it can call: the address every request goes under, and how long one call may take. |
429
+
430
+ ### Procedures
431
+
432
+ | Name | Signature or type | Default | What it is |
433
+ | --- | --- | --- | --- |
434
+ | <span id="integration-baseUrlVariable-procedure">`baseUrlVariable`</span> | `(variablePrefix: string) => string` | — | Builds the environment variable name from the prefix the application gives at mount time. |
435
+ | <span id="integration-externalHttpClientUnavailableWithoutConfiguration-procedure">`externalHttpClientUnavailableWithoutConfiguration`</span> | `(service: string, refusal: Refusal) => ExternalHttpClientShape` | — | The client that stands in when nobody set the address, and fails every call loudly. |
436
+ | <span id="integration-externalServiceSettings-procedure">`externalServiceSettings`</span> | `(variablePrefix: string) => Config.Config<ExternalServiceSettings>` | — | Reads every variable of `ENVIRONMENT` under one prefix. |
437
+ | <span id="integration-makeExternalHttpClient-procedure">`makeExternalHttpClient`</span> | `(service: string, settings: ExternalServiceSettings) => Effect.Effect<ExternalHttpClientShape, never, HttpClient.HttpClient>` | — | A ready-to-use client, with its transport already captured. |
438
+ | <span id="integration-timeoutVariable-procedure">`timeoutVariable`</span> | `(variablePrefix: string) => string` | — | Builds the timeout variable's name from the same prefix, so each external service in one process keeps its own patience. |
439
+
440
+ ### Adapters
441
+
442
+ | Name | Signature or type | Default | What it is |
443
+ | --- | --- | --- | --- |
444
+ | <span id="integration-externalHttpClientFromEnvironmentLive-adapter">`externalHttpClientFromEnvironmentLive`</span> | `(service: string, variablePrefix: string, transport: Layer.Layer<HttpClient.HttpClient> = FetchHttpClient.layer) => Layer.Layer<ExternalHttpClient, ConfigError.ConfigError>` | — | A client built from the environment variables under one prefix. |
445
+ | <span id="integration-externalHttpClientLive-adapter">`externalHttpClientLive`</span> | `(service: string, variablePrefix: string) => Layer.Layer<ExternalHttpClient, ConfigError.ConfigError>` | — | One external service on the real fetch transport, reading the variables its prefix names. |
446
+
447
+ ### Environment variables
448
+
449
+ | Name | Signature or type | Default | What it is |
450
+ | --- | --- | --- | --- |
451
+ | <span id="integration-PREFIX-BASE-URL-environment-variable">`<PREFIX>_BASE_URL`</span> | `refuses` | — | The address every call to this external service goes under. |
452
+ | <span id="integration-PREFIX-TIMEOUT-MILLIS-environment-variable">`<PREFIX>_TIMEOUT_MILLIS`</span> | `falls back` | `3000` | How many milliseconds one call may take before it counts as a network failure. |
453
+
454
+ ## postgres
455
+
456
+ Import from `@satorio/machinery/postgres` — [the whole page](../mechanisms/postgres.mdx).
457
+
458
+ ### Values
459
+
460
+ | Name | Signature or type | Default | What it is |
461
+ | --- | --- | --- | --- |
462
+ | <span id="postgres-AdvisoryLock-value">`AdvisoryLock`</span> | `interface` | — | A lock somebody else may already hold: its name, the attempt to take it, and the release that follows. |
463
+ | <span id="postgres-DEFAULT-APPLICATION-NAME-value">`DEFAULT_APPLICATION_NAME`</span> | `const` | — | The name this service shows under in the database's own list of connections when nobody names it. |
464
+ | <span id="postgres-DEFAULT-AUTH-MODE-value">`DEFAULT_AUTH_MODE`</span> | `'iam' \| 'password'` | — | How a service proves who it is when nothing says otherwise. |
465
+ | <span id="postgres-DEFAULT-POSTGRES-PORT-value">`DEFAULT_POSTGRES_PORT`</span> | `const` | — | The port a Postgres server listens on when nobody says otherwise. |
466
+ | <span id="postgres-DEFAULT-POSTGRES-SCHEMA-value">`DEFAULT_POSTGRES_SCHEMA`</span> | `const` | — | The schema every statement runs against when nobody names one. |
467
+ | <span id="postgres-DEFAULT-POSTGRES-SSL-MODE-value">`DEFAULT_POSTGRES_SSL_MODE`</span> | `PostgresSslMode` | — | How a connection is encrypted when nobody says otherwise: the chain is verified, so the safe choice is the one you get by saying nothing. |
468
+ | <span id="postgres-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
469
+ | <span id="postgres-MACHINERY-MIGRATIONS-DIRECTORY-value">`MACHINERY_MIGRATIONS_DIRECTORY`</span> | `const` | — | Directory holding the machinery's shared migrations: the processed-event registry and the outbox. |
470
+ | <span id="postgres-MIGRATION-LOCK-NAME-value">`MIGRATION_LOCK_NAME`</span> | `const` | — | The name every migration lock is built from, so one reader finds them all. |
471
+ | <span id="postgres-POSTGRES-SSL-MODES-value">`POSTGRES_SSL_MODES`</span> | `const` | — | Every way a connection can be encrypted and verified, from no encryption at all to a fully verified chain. |
472
+ | <span id="postgres-PostgresAuthentication-value">`PostgresAuthentication`</span> | `type` | — | The two ways to prove to the database who you are: a short-lived IAM token or a password. |
473
+ | <span id="postgres-PostgresConnectionSettings-value">`PostgresConnectionSettings`</span> | `interface` | — | Everything one connection needs, read in one go: where the server is, who connects, and how the connection is proven and encrypted. |
474
+ | <span id="postgres-postgresConnectionSettings-value">`postgresConnectionSettings`</span> | `Config.Config<PostgresConnectionSettings>` | — | Every variable of `ENVIRONMENT`, read in one go. |
475
+ | <span id="postgres-PostgresPorts-value">`PostgresPorts`</span> | `type` | — | The ports this mechanism implements, named together as one type. |
476
+ | <span id="postgres-PostgresSslMode-value">`PostgresSslMode`</span> | `(typeof POSTGRES_SSL_MODES)[number]` | — | One of the ways a connection can be encrypted and verified. |
477
+ | <span id="postgres-READINESS-QUERY-DEADLINE-MILLIS-value">`READINESS_QUERY_DEADLINE_MILLIS`</span> | `const` | — | How long the probe waits for its query before it reports "down". |
478
+ | <span id="postgres-READINESS-REASON-WHEN-THE-DATABASE-STAYS-SILENT-value">`READINESS_REASON_WHEN_THE_DATABASE_STAYS_SILENT`</span> | `const` | — | Reason reported when the readiness query answers with a failure. |
479
+ | <span id="postgres-READINESS-REASON-WHEN-THE-QUERY-TIMES-OUT-value">`READINESS_REASON_WHEN_THE_QUERY_TIMES_OUT`</span> | `const` | — | Reason reported when the readiness query times out. |
480
+
481
+ ### Procedures
482
+
483
+ | Name | Signature or type | Default | What it is |
484
+ | --- | --- | --- | --- |
485
+ | <span id="postgres-applyMigrations-procedure">`applyMigrations`</span> | `(directories: readonly string[] = [MACHINERY_MIGRATIONS_DIRECTORY])` | — | Applies pending migrations from the given directories, the machinery's own directory first, then the caller's. |
486
+ | <span id="postgres-configProviderPreferring-procedure">`configProviderPreferring`</span> | `(primary: ConfigProvider.ConfigProvider, fallbackKey: string, fallbackValue: string) => ConfigProvider.ConfigProvider` | — | Builds a config provider that reads from `primary`, falling back to one fixed value when `primary` has no such key. |
487
+ | <span id="postgres-firstRow-procedure">`firstRow`</span> | `<A>(rows: readonly A[]) => Option.Option<A>` | — | Returns the first row, or `Option.none()` for an empty result. |
488
+ | <span id="postgres-holdingAdvisoryLock-procedure">`holdingAdvisoryLock`</span> | `<ELock, RLock, ScheduleOut, RSchedule>(lock: AdvisoryLock<ELock, RLock>, retryWhileBusy: Schedule.Schedule<ScheduleOut, unknown, RSchedule>)` | — | Runs an effect while holding the lock, waiting on the given schedule while somebody else holds it, and letting go however the effect ends. |
489
+ | <span id="postgres-isUniqueViolation-procedure">`isUniqueViolation`</span> | `(error: SqlError) => boolean` | — | Whether this driver failure is a duplicate key rather than anything else the database could refuse. |
490
+ | <span id="postgres-jsonbValue-procedure">`jsonbValue`</span> | `(sql: SqlClient.SqlClient, value: unknown) => Fragment` | — | Hands a value to a `jsonb` column as JSON, whatever its shape. |
491
+ | <span id="postgres-migrationLockNameFor-procedure">`migrationLockNameFor`</span> | `(schema: string) => string` | — | The lock one schema's migrations take, so two services migrating two schemas never wait on each other. |
492
+ | <span id="postgres-onUniqueViolation-procedure">`onUniqueViolation`</span> | `<Conflict, Unavailable>(operation: string, branches: { readonly unique: () => Conflict; readonly unavailable: ( operation: string, ) => (cause: unknown) => Unavailable })` | — | Splits a write path at the database boundary: a unique violation becomes a domain conflict, any other SqlError becomes "store unavailable". |
493
+ | <span id="postgres-postgresAdvisoryLock-procedure">`postgresAdvisoryLock`</span> | `(name: string) => AdvisoryLock<SqlError.SqlError, SqlClient.SqlClient>` | — | A named advisory lock on the connection's own database. |
494
+ | <span id="postgres-readinessProbeAsking-procedure">`readinessProbeAsking`</span> | `(aQueryTheDatabaseMustAnswer: Effect.Effect<unknown, SqlError>)` | — | Builds a probe around one query the database must answer, with a deadline over it so an unreachable database reports "down" instead of hanging. |
495
+ | <span id="postgres-reportApplied-procedure">`reportApplied`</span> | `(applied: ReadonlyArray<readonly [number, string]>) => Effect.Effect<void>` | — | Says in one line what the run applied, or that the database was already current. |
496
+ | <span id="postgres-schemaDefaultingTo-procedure">`schemaDefaultingTo`</span> | `(schema: string) => ConfigProvider.ConfigProvider` | — | Default schema for one service when `PGSCHEMA` isn't set. |
497
+
498
+ ### Adapters
499
+
500
+ | Name | Signature or type | Default | What it is |
501
+ | --- | --- | --- | --- |
502
+ | <span id="postgres-MigrationPgClientLive-adapter">`MigrationPgClientLive`</span> | `Layer.Layer<PgClient.PgClient \| SqlClient.SqlClient, ConfigError \| PlatformError \| SqlError, FileSystem.FileSystem>` | — | The client the migration runner uses: one connection, under its own name. |
503
+ | <span id="postgres-PgDocumentNumberCounterLive-adapter">`PgDocumentNumberCounterLive`</span> | `Layer.Layer<DocumentNumberCounter, never, PgClient.PgClient>` | — | The document number counter on a real `document_number_counter` table. |
504
+ | <span id="postgres-PgIntegrationEventOutboxLive-adapter">`PgIntegrationEventOutboxLive`</span> | `Layer.Layer<IntegrationEventOutbox, never, PgClient.PgClient>` | — | The outbox on a real `integration_event_outbox` table. |
505
+ | <span id="postgres-PgProcessedEventRegistryLive-adapter">`PgProcessedEventRegistryLive`</span> | `Layer.Layer<ProcessedEventRegistry, never, PgClient.PgClient>` | — | The exactly-once claim on a real `processed_event` table. |
506
+ | <span id="postgres-PgReadinessProbeLive-adapter">`PgReadinessProbeLive`</span> | `Layer.Layer<ReadinessProbe, never, SqlClient.SqlClient>` | — | The readiness probe on one `SELECT 1` against the service's own pool. |
507
+ | <span id="postgres-PgTransactionBoundaryLive-adapter">`PgTransactionBoundaryLive`</span> | `Layer.Layer<TransactionBoundary, never, SqlClient.SqlClient>` | — | The transaction boundary on a real Postgres transaction. |
508
+ | <span id="postgres-PostgresClientLive-adapter">`PostgresClientLive`</span> | `Layer.Layer<PgClient.PgClient \| SqlClient.SqlClient, ConfigError \| PlatformError \| SqlError, FileSystem.FileSystem>` | — | The `@effect/sql-pg` client every other layer here builds on, opened from the environment `settings.ts` names. |
509
+ | <span id="postgres-PostgresPortsLive-adapter">`PostgresPortsLive`</span> | `Layer.Layer<PostgresPorts \| PgClient.PgClient \| SqlClient.SqlClient, ConfigError \| PlatformError \| SqlError, FileSystem.FileSystem>` | — | Every port this mechanism implements, on one client, for a service that supplies its own `FileSystem`. |
510
+ | <span id="postgres-PostgresPortsOnBunLive-adapter">`PostgresPortsOnBunLive`</span> | `Layer.Layer<PostgresPorts \| PgClient.PgClient \| SqlClient.SqlClient, ConfigError \| PlatformError \| SqlError>` | — | The same bundle on Bun's own file system, which is the whole Postgres side of the machinery in one layer. |
511
+
512
+ ### Failures
513
+
514
+ | Name | Signature or type | Default | What it is |
515
+ | --- | --- | --- | --- |
516
+ | <span id="postgres-MigrationLockBusyError-failure">`MigrationLockBusyError`</span> | `Data.TaggedError<{ readonly lockName: string }>` | — | A second process already holds the migration lock and did not let go within the retry window. |
517
+
518
+ ### Environment variables
519
+
520
+ | Name | Signature or type | Default | What it is |
521
+ | --- | --- | --- | --- |
522
+ | <span id="postgres-PGHOST-environment-variable">`PGHOST`</span> | `refuses` | — | The host this service opens its connection pool against. |
523
+ | <span id="postgres-PGPORT-environment-variable">`PGPORT`</span> | `falls back` | `5432` | The TCP port the database listens on. |
524
+ | <span id="postgres-PGUSER-environment-variable">`PGUSER`</span> | `refuses` | — | The Postgres role this service connects as. |
525
+ | <span id="postgres-PGDATABASE-environment-variable">`PGDATABASE`</span> | `refuses` | — | The database this service reads and writes. |
526
+ | <span id="postgres-PGSCHEMA-environment-variable">`PGSCHEMA`</span> | `falls back` | `app` | The schema every statement runs against, set as the connection's search_path. |
527
+ | <span id="postgres-PGAPPNAME-environment-variable">`PGAPPNAME`</span> | `falls back` | `machinery` | The name this service shows under in pg_stat_activity. |
528
+ | <span id="postgres-PGSSLMODE-environment-variable">`PGSSLMODE`</span> | `falls back` | `verify-full` | How the connection is encrypted and verified, one of disable, allow, prefer, require, verify-ca, verify-full. |
529
+ | <span id="postgres-PGSSLROOTCERT-environment-variable">`PGSSLROOTCERT`</span> | `handed on` | — | The path to a certificate authority file the database chain is verified against. |
530
+ | <span id="postgres-AUTH-MODE-environment-variable">`AUTH_MODE`</span> | `falls back` | `password` | Which of the two ways this service proves who it is, iam or password. |
531
+ | <span id="postgres-PGPASSWORD-environment-variable">`PGPASSWORD`</span> | `refuses` | — | The database password, read under the default password mode. |
532
+ | <span id="postgres-AWS-REGION-environment-variable">`AWS_REGION`</span> | `handed on` | — | The region the IAM token signer signs against, read under AUTH_MODE=iam. |
533
+
534
+ ## publishing
535
+
536
+ Import from `@satorio/machinery/publishing` — [the whole page](../mechanisms/publishing.mdx).
537
+
538
+ ### Values
539
+
540
+ | Name | Signature or type | Default | What it is |
541
+ | --- | --- | --- | --- |
542
+ | <span id="publishing-DEFAULT-EVENT-CHANNEL-value">`DEFAULT_EVENT_CHANNEL`</span> | `const` | — | The log channel the stdout publisher writes its events under when nobody names one. |
543
+ | <span id="publishing-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
544
+ | <span id="publishing-SnsPublisherSettings-value">`SnsPublisherSettings`</span> | `interface` | — | What the SNS publisher needs before it can send: one topic, and the two variables the AWS SDK reads for itself when nobody names them. |
545
+
546
+ ### Procedures
547
+
548
+ | Name | Signature or type | Default | What it is |
549
+ | --- | --- | --- | --- |
550
+ | <span id="publishing-snsMessageBodyOf-procedure">`snsMessageBodyOf`</span> | `(message: OutboxMessage) => string` | — | The message body a subscriber reads: the same envelope as the stdout line, minus the channel — here the topic itself plays that role. |
551
+ | <span id="publishing-snsPublisherSettings-procedure">`snsPublisherSettings`</span> | `(variablePrefix: string) => Config.Config<SnsPublisherSettings>` | — | Reads every variable the SNS publisher needs under one prefix. |
552
+ | <span id="publishing-stdoutLineOf-procedure">`stdoutLineOf`</span> | `(channel: string, message: OutboxMessage) => string` | — | The simplest publisher: an event travels as one JSON line on stdout, where a log collector picks it up. |
553
+ | <span id="publishing-topicArnVariable-procedure">`topicArnVariable`</span> | `(variablePrefix: string) => string` | — | Builds the environment variable name from the prefix the application gives at mount time. |
554
+
555
+ ### Adapters
556
+
557
+ | Name | Signature or type | Default | What it is |
558
+ | --- | --- | --- | --- |
559
+ | <span id="publishing-snsEventPublisherLive-adapter">`snsEventPublisherLive`</span> | `(variablePrefix: string) => Layer.Layer<EventPublisher, ConfigError.ConfigError>` | — | The SNS publisher on the real AWS SDK transport, reading the variables this prefix names. |
560
+ | <span id="publishing-StdoutEventPublisherLive-adapter">`StdoutEventPublisherLive`</span> | `Layer.Layer<EventPublisher>` | — | The stdout publisher, mounted: one JSON line per event under the channel `EVENT_CHANNEL` names. |
561
+
562
+ ### Environment variables
563
+
564
+ | Name | Signature or type | Default | What it is |
565
+ | --- | --- | --- | --- |
566
+ | <span id="publishing-PREFIX-TOPIC-ARN-environment-variable">`<PREFIX>_TOPIC_ARN`</span> | `refuses` | — | The SNS topic this publisher sends events to. |
567
+ | <span id="publishing-EVENT-CHANNEL-environment-variable">`EVENT_CHANNEL`</span> | `falls back` | `machinery-integration-events` | The word a log collector filters the stdout publisher's lines by. |
568
+ | <span id="publishing-AWS-REGION-environment-variable">`AWS_REGION`</span> | `handed on` | — | The region the SNS client talks to. |
569
+ | <span id="publishing-AWS-ENDPOINT-URL-environment-variable">`AWS_ENDPOINT_URL`</span> | `handed on` | — | A local stand to talk to instead of real SNS, such as localstack. |
570
+
571
+ ## queue
572
+
573
+ Import from `@satorio/machinery/queue` — [the whole page](../mechanisms/queue.mdx).
574
+
575
+ ### Values
576
+
577
+ | Name | Signature or type | Default | What it is |
578
+ | --- | --- | --- | --- |
579
+ | <span id="queue-defaultQueueRetrySchedule-value">`defaultQueueRetrySchedule`</span> | `QueueRetrySchedule` | — | The waiting a consumer keeps when a service names no schedule of its own: growing pauses, jittered, and a limit on how often it tries. |
580
+ | <span id="queue-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
581
+ | <span id="queue-EventDefinitionRegistry-value">`EventDefinitionRegistry`</span> | `interface` | — | What a service's own list of event definitions offers: whether an event type is known, and the definition behind it. |
582
+ | <span id="queue-IncomingQueueMessage-value">`IncomingQueueMessage`</span> | `interface` | — | One message as a handler meets it: the envelope's own fields, and the decoded event itself. |
583
+ | <span id="queue-PayloadDecoder-value">`PayloadDecoder`</span> | `type` | — | What turns a stored payload of some version into the event a handler works with. |
584
+ | <span id="queue-QueueConsumerSettings-value">`QueueConsumerSettings`</span> | `interface` | — | What a consumer needs before it can receive a single message. |
585
+ | <span id="queue-QueueMessageBody-value">`QueueMessageBody`</span> | `const` | — | The envelope as it travels: the JSON text on the wire, read and written through one schema. |
586
+ | <span id="queue-QueueMessageConsumerOptions-value">`QueueMessageConsumerOptions`</span> | `interface` | — | What a consumer needs to turn a queue message into work. |
587
+ | <span id="queue-QueueMessageOutcome-value">`QueueMessageOutcome`</span> | `type` | — | The fate of one message has exactly three endings: acknowledged, left for redelivery, or refused permanently. |
588
+ | <span id="queue-QueueProducerSettings-value">`QueueProducerSettings`</span> | `interface` | — | What a producer needs before it can send: the queue, and the same two variables the SDK decides for itself. |
589
+ | <span id="queue-QueueRetrySchedule-value">`QueueRetrySchedule`</span> | `type` | — | How a consumer waits and tries again while the queue itself does not answer. |
590
+ | <span id="queue-RedeliveryReason-value">`RedeliveryReason`</span> | `type` | — | Why a message goes back on the queue: it never decoded, or the handler rejected it. |
591
+ | <span id="queue-SchemaVersion-value">`SchemaVersion`</span> | `const` | — | The version a stored payload was shaped by: a whole number above zero, and never anything else. |
592
+ | <span id="queue-SQS-DEFAULT-VISIBILITY-TIMEOUT-SECONDS-value">`SQS_DEFAULT_VISIBILITY_TIMEOUT_SECONDS`</span> | `const` | — | How long a received message stays hidden while a handler works on it, when nobody names a number. |
593
+ | <span id="queue-StoredEventEnvelope-value">`StoredEventEnvelope`</span> | `const` | — | The shared queue contract every message travels in. |
594
+
595
+ ### Procedures
596
+
597
+ | Name | Signature or type | Default | What it is |
598
+ | --- | --- | --- | --- |
599
+ | <span id="queue-consumeQueueMessages-procedure">`consumeQueueMessages`</span> | `<A, E, R>(options: QueueMessageConsumerOptions<A, E, R>) => Stream.Stream<QueueMessageOutcome, QueueMessageSourceUnavailableError, R \| QueueMessageSource>` | — | Reads messages off the queue and hands each one to the handler, answering with the fate of every message it took. |
600
+ | <span id="queue-decodeQueueMessageBody-procedure">`decodeQueueMessageBody`</span> | `(body: string) => Effect.Effect<StoredEventEnvelope, QueueMessageNotDecodableError>` | — | Reads a message body into an envelope, or refuses at the envelope stage and says what it could not read. |
601
+ | <span id="queue-eventDefinitionRegistry-procedure">`eventDefinitionRegistry`</span> | `<S extends Schema.Schema.AnyNoContext>(definitions: readonly VersionedEventDefinition<S>[]) => EventDefinitionRegistry<S>` | — | Builds a registry of known event definitions. |
602
+ | <span id="queue-handlerRejectedMessage-procedure">`handlerRejectedMessage`</span> | `(error: unknown) => RedeliveryReason` | — | The reason for a message the handler itself rejected. |
603
+ | <span id="queue-messageAcknowledged-procedure">`messageAcknowledged`</span> | `(messageId: string) => QueueMessageOutcome` | — | The fate of a message the handler took, so the queue may drop it. |
604
+ | <span id="queue-messageLeftForRedelivery-procedure">`messageLeftForRedelivery`</span> | `(messageId: string, reason: RedeliveryReason) => QueueMessageOutcome` | — | The fate of a message that goes back on the queue, with the reason it did. |
605
+ | <span id="queue-messageNotDecodable-procedure">`messageNotDecodable`</span> | `(error: QueueMessageNotDecodableError) => RedeliveryReason` | — | The reason for a message that never decoded. |
606
+ | <span id="queue-messageRefusedPermanently-procedure">`messageRefusedPermanently`</span> | `(messageId: string, eventId: string, refusal: unknown) => QueueMessageOutcome` | — | The fate of a message no retry can help, so the platform's own redrive takes it from here. |
607
+ | <span id="queue-payloadDecoderFor-procedure">`payloadDecoderFor`</span> | `<S extends Schema.Schema.AnyNoContext>(definition: VersionedEventDefinition<S>) => PayloadDecoder<Schema.Schema.Type<S>>` | — | Builds the payload decoder for one event definition, climbing a stored payload up to the version this code knows. |
608
+ | <span id="queue-queueConsumerSettings-procedure">`queueConsumerSettings`</span> | `(variablePrefix: string) => Config.Config<QueueConsumerSettings>` | — | Reads every variable a consumer needs under one prefix. |
609
+ | <span id="queue-queueMessageBodyOf-procedure">`queueMessageBodyOf`</span> | `(envelope: { readonly eventId: string; readonly eventType: string; readonly schemaVersion: number; readonly occurredAtIso: string; readonly payload: { readonly [key: string]: unknown } }) => string` | — | Builds the same envelope contract, but for sending: the producer sets exactly the fields the consumer expects to read. |
610
+ | <span id="queue-queueProducerSettings-procedure">`queueProducerSettings`</span> | `(variablePrefix: string) => Config.Config<QueueProducerSettings>` | — | Reads every variable a producer needs under one prefix. |
611
+ | <span id="queue-queueReadinessCheck-procedure">`queueReadinessCheck`</span> | `(variablePrefix: string) => Effect.Effect<Option.Option<Effect.Effect<void, QueueMessageSourceUnavailableError>>, ConfigError.ConfigError>` | — | The readiness check for a queue, absent when no queue is mounted at all. |
612
+ | <span id="queue-queueUrlVariable-procedure">`queueUrlVariable`</span> | `(variablePrefix: string) => string` | — | Builds the environment variable name from the prefix the application gives at mount time. |
613
+
614
+ ### Adapters
615
+
616
+ | Name | Signature or type | Default | What it is |
617
+ | --- | --- | --- | --- |
618
+ | <span id="queue-sqsQueueMessageProducerLive-adapter">`sqsQueueMessageProducerLive`</span> | `(variablePrefix: string) => Layer.Layer<QueueMessageProducer, ConfigError.ConfigError>` | — | The message producer on the real AWS SDK transport, reading the variables this prefix names. |
619
+ | <span id="queue-sqsQueueMessageSourceLive-adapter">`sqsQueueMessageSourceLive`</span> | `(variablePrefix: string) => Layer.Layer<QueueMessageSource, ConfigError.ConfigError>` | — | The message source on the real AWS SDK transport, reading the variables this prefix names. |
620
+
621
+ ### Failures
622
+
623
+ | Name | Signature or type | Default | What it is |
624
+ | --- | --- | --- | --- |
625
+ | <span id="queue-QueueMessageNotDecodableError-failure">`QueueMessageNotDecodableError`</span> | `Data.TaggedError<{ readonly stage: QueueMessageDecodingStage; readonly cause: unknown }>` | — | A message whose text this service cannot turn into an event. |
626
+ | <span id="queue-UnknownEventTypeError-failure">`UnknownEventTypeError`</span> | `Data.TaggedError<{ readonly eventType: string }>` | — | A message naming an event type this service never registered. |
627
+
628
+ ### Environment variables
629
+
630
+ | Name | Signature or type | Default | What it is |
631
+ | --- | --- | --- | --- |
632
+ | <span id="queue-PREFIX-QUEUE-URL-environment-variable">`<PREFIX>_QUEUE_URL`</span> | `refuses` | — | The queue a consumer receives from and a producer sends to. |
633
+ | <span id="queue-PREFIX-MAX-MESSAGES-PER-RECEIVE-environment-variable">`<PREFIX>_MAX_MESSAGES_PER_RECEIVE`</span> | `falls back` | `10` | How many messages one receive call asks for. |
634
+ | <span id="queue-PREFIX-WAIT-TIME-SECONDS-environment-variable">`<PREFIX>_WAIT_TIME_SECONDS`</span> | `falls back` | `20` | How many seconds a receive call waits for a message before it comes back empty. |
635
+ | <span id="queue-PREFIX-VISIBILITY-TIMEOUT-SECONDS-environment-variable">`<PREFIX>_VISIBILITY_TIMEOUT_SECONDS`</span> | `falls back` | `60` | How many seconds a received message stays hidden from other consumers. |
636
+ | <span id="queue-AWS-REGION-environment-variable">`AWS_REGION`</span> | `handed on` | — | The region the SQS client talks to. |
637
+ | <span id="queue-AWS-ENDPOINT-URL-environment-variable">`AWS_ENDPOINT_URL`</span> | `handed on` | — | A local stand to talk to instead of real SQS, such as localstack. |
638
+
639
+ ## storage
640
+
641
+ Import from `@satorio/machinery/storage` — [the whole page](../mechanisms/storage.mdx).
642
+
643
+ ### Values
644
+
645
+ | Name | Signature or type | Default | What it is |
646
+ | --- | --- | --- | --- |
647
+ | <span id="storage-BlobStoreSettings-value">`BlobStoreSettings`</span> | `interface` | — | What the store needs before it can talk to the object store. |
648
+ | <span id="storage-ClosableS3Transport-value">`ClosableS3Transport`</span> | `interface` | — | A transport that also closes, so the client behind it is released when the scope around it ends. |
649
+ | <span id="storage-DEFAULT-CONTENT-TYPE-value">`DEFAULT_CONTENT_TYPE`</span> | `const` | — | What an object is read as when the store hands back no content type of its own: plain bytes. |
650
+ | <span id="storage-ENVIRONMENT-value">`ENVIRONMENT`</span> | `readonly EnvironmentEntry[]` | — | Every variable this adapter reads, and the one state each of them stands in. |
651
+ | <span id="storage-S3FetchedObject-value">`S3FetchedObject`</span> | `interface` | — | One object as the store hands it back: its bytes, and the content type and metadata it carries when it carries any. |
652
+ | <span id="storage-S3KeyRequest-value">`S3KeyRequest`</span> | `interface` | — | One object named: the bucket it sits in and the key it sits under. |
653
+ | <span id="storage-S3ObjectTransport-value">`S3ObjectTransport`</span> | `interface` | — | The narrow slice of the object store a blob store calls: put, get, check, delete, and nothing else. |
654
+ | <span id="storage-S3PutRequest-value">`S3PutRequest`</span> | `interface` | — | The narrowest slice of the SDK the store uses: put, get, check existence, delete. |
655
+
656
+ ### Procedures
657
+
658
+ | Name | Signature or type | Default | What it is |
659
+ | --- | --- | --- | --- |
660
+ | <span id="storage-blobStoreSettings-procedure">`blobStoreSettings`</span> | `(variablePrefix: string) => Config.Config<BlobStoreSettings>` | — | Reads every variable of `ENVIRONMENT` under one prefix. |
661
+ | <span id="storage-blobStoreUnavailableWithoutConfiguration-procedure">`blobStoreUnavailableWithoutConfiguration`</span> | `(refusal: Refusal) => BlobStoreShape` | — | Without a bucket set, the store does not fail service startup: it mounts a stub that fails every operation loudly. |
662
+ | <span id="storage-bucketVariable-procedure">`bucketVariable`</span> | `(variablePrefix: string) => string` | — | Builds the environment variable name from the prefix the application gives at mount time. |
663
+ | <span id="storage-makeS3BlobStore-procedure">`makeS3BlobStore`</span> | `(transport: S3ObjectTransport, settings: BlobStoreSettings) => BlobStoreShape` | — | Builds the blob store over one transport and one bucket, turning the store's own way of signalling a missing key into an absent value. |
664
+ | <span id="storage-openS3Transport-procedure">`openS3Transport`</span> | `(settings: BlobStoreSettings) => ClosableS3Transport` | — | Opens the real object-store client against the settings handed in, and is the one place that client is constructed. |
665
+ | <span id="storage-scopedS3Transport-procedure">`scopedS3Transport`</span> | `(openTransport: () => ClosableS3Transport) => Effect.Effect<S3ObjectTransport, never, Scope.Scope>` | — | Opens a transport that closes with the scope around it, so no client outlives the work that opened it. |
666
+ | <span id="storage-signalsAbsentKey-procedure">`signalsAbsentKey`</span> | `(error: unknown) => boolean` | — | S3 signals "no such key" as an ERROR, not an empty response: `GetObject` throws `NoSuchKey`, `HeadObject` throws `NotFound`. |
667
+
668
+ ### Adapters
669
+
670
+ | Name | Signature or type | Default | What it is |
671
+ | --- | --- | --- | --- |
672
+ | <span id="storage-blobStoreFromEnvironmentLive-adapter">`blobStoreFromEnvironmentLive`</span> | `(variablePrefix: string, openTransport: (settings: BlobStoreSettings) => ClosableS3Transport) => Layer.Layer<BlobStore, ConfigError.ConfigError>` | — | A blob store built from environment variables with the given prefix. |
673
+ | <span id="storage-s3BlobStoreLive-adapter">`s3BlobStoreLive`</span> | `(variablePrefix: string) => Layer.Layer<BlobStore, ConfigError.ConfigError>` | — | The blob store on the real AWS SDK transport, reading the variables this prefix names. |
674
+
675
+ ### Environment variables
676
+
677
+ | Name | Signature or type | Default | What it is |
678
+ | --- | --- | --- | --- |
679
+ | <span id="storage-PREFIX-BUCKET-environment-variable">`<PREFIX>_BUCKET`</span> | `refuses` | — | The bucket this store puts objects into and reads them back from. |
680
+ | <span id="storage-AWS-REGION-environment-variable">`AWS_REGION`</span> | `handed on` | — | The region the S3 client talks to. |
681
+ | <span id="storage-AWS-ENDPOINT-URL-environment-variable">`AWS_ENDPOINT_URL`</span> | `handed on` | — | A local stand to talk to instead of real S3, such as localstack. |
682
+
683
+ ## testing
684
+
685
+ Import from `@satorio/machinery/testing` — [the whole page](../mechanisms/testing.mdx).
686
+
687
+ ### Values
688
+
689
+ | Name | Signature or type | Default | What it is |
690
+ | --- | --- | --- | --- |
691
+ | <span id="testing-AnswersByPath-value">`AnswersByPath`</span> | `Readonly<Record<string, unknown>>` | — | What an in-memory client answers with: one already-decoded body per path. |
692
+ | <span id="testing-BlobsByKey-value">`BlobsByKey`</span> | `ReadonlyMap<string, StoredBlob>` | — | What an in-memory blob store holds: every blob it was given, by key. |
693
+ | <span id="testing-DispatchedMessageIds-value">`DispatchedMessageIds`</span> | `ReadonlySet<string>` | — | What an in-memory outbox holds on the read side: the ids a relay has already marked as sent. |
694
+ | <span id="testing-DocumentCountsByClientAndMonth-value">`DocumentCountsByClientAndMonth`</span> | `ReadonlyMap<string, number>` | — | What an in-memory counter holds: how many documents each client has been sent in each reporting month, keyed by the two together. |
695
+ | <span id="testing-InMemoryBlobStoreLive-value">`InMemoryBlobStoreLive`</span> | `const` | — | The in-memory blob store, mounted. |
696
+ | <span id="testing-InMemoryDocumentNumberCounterLive-value">`InMemoryDocumentNumberCounterLive`</span> | `const` | — | The in-memory counter, mounted. |
697
+ | <span id="testing-InMemoryEventPublisherLive-value">`InMemoryEventPublisherLive`</span> | `const` | — | The in-memory publisher, mounted. |
698
+ | <span id="testing-InMemoryIntegrationEventOutboxLive-value">`InMemoryIntegrationEventOutboxLive`</span> | `const` | — | The in-memory outbox, mounted. |
699
+ | <span id="testing-InMemoryProcessedEventRegistryLive-value">`InMemoryProcessedEventRegistryLive`</span> | `const` | — | The in-memory registry, mounted. |
700
+ | <span id="testing-InMemoryQueueMessageProducerLive-value">`InMemoryQueueMessageProducerLive`</span> | `const` | — | The in-memory producer, mounted. |
701
+ | <span id="testing-InMemoryQueueMessageSourceLive-value">`InMemoryQueueMessageSourceLive`</span> | `const` | — | The in-memory message source, mounted. |
702
+ | <span id="testing-makeInMemoryBlobStore-value">`makeInMemoryBlobStore`</span> | `const` | — | An in-memory blob store over a `Ref` of its own, empty at the start. |
703
+ | <span id="testing-makeInMemoryDocumentNumberCounter-value">`makeInMemoryDocumentNumberCounter`</span> | `const` | — | An in-memory counter over a `Ref` of its own, with every month at zero. |
704
+ | <span id="testing-makeInMemoryEventPublisher-value">`makeInMemoryEventPublisher`</span> | `const` | — | An in-memory publisher over a `Ref` of its own, empty at the start. |
705
+ | <span id="testing-makeInMemoryIntegrationEventOutbox-value">`makeInMemoryIntegrationEventOutbox`</span> | `const` | — | An in-memory outbox over `Ref`s of its own, empty at the start. |
706
+ | <span id="testing-makeInMemoryProcessedEventRegistry-value">`makeInMemoryProcessedEventRegistry`</span> | `const` | — | An in-memory registry over a `Ref` of its own, empty at the start. |
707
+ | <span id="testing-makeInMemoryQueueMessageProducer-value">`makeInMemoryQueueMessageProducer`</span> | `const` | — | An in-memory producer over a `Ref` of its own, whose messages nobody receives. |
708
+ | <span id="testing-makeInMemoryQueueMessageSource-value">`makeInMemoryQueueMessageSource`</span> | `const` | — | An in-memory message source over a `Ref` of its own, empty at the start. |
709
+ | <span id="testing-nowAsDateTime-value">`nowAsDateTime`</span> | `Effect.Effect<DateTime.Utc>` | — | The moment the clock reads now, as a moment on the world's clock. |
710
+ | <span id="testing-nowAsIsoString-value">`nowAsIsoString`</span> | `Effect.Effect<string>` | — | The moment the clock reads now, written the way it travels the wire. |
711
+ | <span id="testing-PendingQueueMessages-value">`PendingQueueMessages`</span> | `readonly RawQueueMessage[]` | — | What an in-memory queue holds: the messages waiting to be received, in the order they were put there. |
712
+ | <span id="testing-ProcessedEventsById-value">`ProcessedEventsById`</span> | `ReadonlyMap<string, DateTime.Utc>` | — | What an in-memory registry holds: the moment each event id was first claimed. |
713
+ | <span id="testing-PublishedMessages-value">`PublishedMessages`</span> | `readonly OutboxMessage[]` | — | What an in-memory publisher holds: every message it was handed, in the order the batches arrived. |
714
+ | <span id="testing-QueuedOutboxMessages-value">`QueuedOutboxMessages`</span> | `readonly OutboxMessage[]` | — | What an in-memory outbox holds on the write side: every message enqueued, in the order it arrived. |
715
+ | <span id="testing-QuietReporter-value">`QuietReporter`</span> | `class` | — | A test-runner reporter that prints one summary line for a whole run: how many files, how many tests, how long it took. |
716
+ | <span id="testing-Scenario-value">`Scenario`</span> | `interface` | — | A story told as data: the steps a world walks through, and the numbers that world ends on. |
717
+ | <span id="testing-ScenarioPlayback-value">`ScenarioPlayback`</span> | `interface` | — | What one run of a scenario leaves behind: the label of every step, and the snapshot the run ended on. |
718
+ | <span id="testing-ScenarioService-value">`ScenarioService`</span> | `interface` | — | What a service gives the scenario player: how to run a step, and how to snapshot what followed. |
719
+ | <span id="testing-ScenarioStep-value">`ScenarioStep`</span> | `interface` | — | One step in a scenario. |
720
+ | <span id="testing-SUITES-THAT-START-A-STAND-value">`SUITES_THAT_START_A_STAND`</span> | `readonly string[]` | — | The suites that start a live stand, by the file name A11 gives them. |
721
+ | <span id="testing-TransactionalState-value">`TransactionalState`</span> | `interface` | — | One participant in an in-memory transaction: it can capture its own state now and hand back the effect that puts it back. |
722
+
723
+ ### Procedures
724
+
725
+ | Name | Signature or type | Default | What it is |
726
+ | --- | --- | --- | --- |
727
+ | <span id="testing-advanceBy-procedure">`advanceBy`</span> | `(duration: Duration.DurationInput) => Effect.Effect<void>` | — | Moves the controlled test clock on by the span handed in, so a test reaches a later moment without waiting for it. |
728
+ | <span id="testing-atTheMoment-procedure">`atTheMoment`</span> | `(isoTimestamp: string)` | — | Runs the given work "at" the given moment: every clock read inside it sees `isoTimestamp`. |
729
+ | <span id="testing-clockPinnedAt-procedure">`clockPinnedAt`</span> | `(at: DateTime.Utc) => Clock.Clock` | — | Builds a Clock pinned to one moment: every time read inside returns that moment, while `sleep` still waits on the real clock. |
730
+ | <span id="testing-contextOf-procedure">`contextOf`</span> | `<Command, Snapshot, Context>(scenario: Scenario<Command, Snapshot, Context>) => Context` | — | Reads the cross-cutting data of a scenario that declares some. |
731
+ | <span id="testing-distinctMomentsIn-procedure">`distinctMomentsIn`</span> | `(table: string, column: string) => Effect.Effect<readonly string[], never, SqlClient.SqlClient>` | — | Reads the distinct moments in one timestamp column, as sorted ISO strings in the same format `momentsOfSteps` returns for a scenario. |
732
+ | <span id="testing-emptiedTables-procedure">`emptiedTables`</span> | `(tables: readonly string[]) => Effect.Effect<void, never, SqlClient.SqlClient>` | — | Empties the given tables on the live stand so a scenario starts from zero, the way a freshly reset database does for the seeder. |
733
+ | <span id="testing-ensureStepsAreInOrder-procedure">`ensureStepsAreInOrder`</span> | `<C, S, X>(scenario: Scenario<C, S, X>) => Effect.Effect<void>` | — | Fails loudly when a scenario's steps are not in strictly increasing time order — that is a broken scenario, not a run outcome. |
734
+ | <span id="testing-firstPassLabelsOf-procedure">`firstPassLabelsOf`</span> | `<C, S, X>(scenario: Scenario<C, S, X>) => readonly string[]` | — | The labels a scenario expects the first time it runs, in order. |
735
+ | <span id="testing-labelOf-procedure">`labelOf`</span> | `<R>(program: Effect.Effect<string, unknown, R>) => Effect.Effect<string, never, R>` | — | Runs one step and labels it: what it returned, or the name of the failure it met. |
736
+ | <span id="testing-labelOfFailure-procedure">`labelOfFailure`</span> | `(cause: Cause.Cause<unknown>) => string` | — | Labels a failure, so a scenario reads the same on every run. |
737
+ | <span id="testing-makeInMemoryBlobStoreWith-procedure">`makeInMemoryBlobStoreWith`</span> | `(blobs: Ref.Ref<BlobsByKey>) => BlobStoreShape` | — | An in-memory blob store over a `Ref` you keep, so a test can seed it before the run and read it after. |
738
+ | <span id="testing-makeInMemoryDocumentNumberCounterWith-procedure">`makeInMemoryDocumentNumberCounterWith`</span> | `(counts: Ref.Ref<DocumentCountsByClientAndMonth>) => DocumentNumberCounterShape` | — | An in-memory counter over a reference you keep, so a test can seed it and read it back. |
739
+ | <span id="testing-makeInMemoryEventPublisherWith-procedure">`makeInMemoryEventPublisherWith`</span> | `(published: Ref.Ref<PublishedMessages>) => EventPublisherShape` | — | An in-memory publisher over a `Ref` you keep, so a test reads what was published after the run. |
740
+ | <span id="testing-makeInMemoryExternalHttpClient-procedure">`makeInMemoryExternalHttpClient`</span> | `(answers: AnswersByPath) => Effect.Effect<ExternalHttpClientShape>` | — | An in-memory client over a `Ref` of its own, seeded with the answers you hand it. |
741
+ | <span id="testing-makeInMemoryExternalHttpClientWith-procedure">`makeInMemoryExternalHttpClientWith`</span> | `(answers: Ref.Ref<AnswersByPath>) => ExternalHttpClientShape` | — | An in-memory client over a `Ref` you keep, so a test rewrites what the service answers between two calls of the same scenario. |
742
+ | <span id="testing-makeInMemoryIntegrationEventOutboxWith-procedure">`makeInMemoryIntegrationEventOutboxWith`</span> | `(queued: Ref.Ref<QueuedOutboxMessages>, dispatched: Ref.Ref<DispatchedMessageIds>) => IntegrationEventOutboxShape` | — | An in-memory outbox over two `Ref`s you keep, so a test can seed what is waiting and read back what the relay dispatched. |
743
+ | <span id="testing-makeInMemoryProcessedEventRegistryWith-procedure">`makeInMemoryProcessedEventRegistryWith`</span> | `(processed: Ref.Ref<ProcessedEventsById>) => ProcessedEventRegistryShape` | — | An in-memory registry over a `Ref` you keep, so a test can seed what was already claimed and read back what the run added. |
744
+ | <span id="testing-makeInMemoryQueueMessageProducerWith-procedure">`makeInMemoryQueueMessageProducerWith`</span> | `(pending: Ref.Ref<PendingQueueMessages>) => QueueMessageProducerShape` | — | An in-memory producer over the same reference an in-memory source reads. |
745
+ | <span id="testing-makeInMemoryQueueMessageSourceWith-procedure">`makeInMemoryQueueMessageSourceWith`</span> | `(pending: Ref.Ref<PendingQueueMessages>) => QueueMessageSourceShape` | — | An in-memory message source over a `Ref` you keep, so a test seeds the queue before the run and reads what is left after it. |
746
+ | <span id="testing-makeInMemoryTransactionBoundary-procedure">`makeInMemoryTransactionBoundary`</span> | `(participants: readonly TransactionalState[]) => TransactionBoundaryShape` | — | Builds an in-memory transaction boundary: it captures each participant's state on entry and restores it if the work fails. |
747
+ | <span id="testing-makeScriptedMessageSource-procedure">`makeScriptedMessageSource`</span> | `(script: readonly (readonly RawQueueMessage[])[]) => Effect.Effect<ScriptedQueue>` | — | Builds the scripted source and the reader for what it acknowledged. |
748
+ | <span id="testing-messageOf-procedure">`messageOf`</span> | `(messageId: string, body: string) => RawQueueMessage` | — | One raw message, built the way a queue hands it over: an id, the receipt an acknowledgement quotes, and the body. |
749
+ | <span id="testing-momentsOfSteps-procedure">`momentsOfSteps`</span> | `<C, S, X>(scenario: Scenario<C, S, X>, chosen: (step: ScenarioStep<C>) => boolean) => readonly string[]` | — | Returns the moments of the chosen steps as ISO strings, in the format a database round-trip returns them. |
750
+ | <span id="testing-mutationSettings-procedure">`mutationSettings`</span> | `(options: MutationSettingsOptions) => MutationSettings` | — | Everything a mutation run needs, with the waits bounded and the live stands kept out. |
751
+ | <span id="testing-playScenario-procedure">`playScenario`</span> | `<C, S, R, X>(scenario: Scenario<C, S, X>, service: ScenarioService<C, S, R, X>) => Effect.Effect<ScenarioPlayback<S>, never, R>` | — | Plays a scenario: each step runs at its own moment, and the snapshot is taken at the last step's moment. |
752
+ | <span id="testing-quietReporters-procedure">`quietReporters`</span> | `(options: QuietReporterOptions & { readonly verbose?: boolean } = {}) => ('default' \| QuietReporter)[]` | — | The `reporters` a test-runner configuration takes. |
753
+ | <span id="testing-replayLabelsOf-procedure">`replayLabelsOf`</span> | `<C, S, X>(scenario: Scenario<C, S, X>) => readonly string[]` | — | The labels a scenario expects when the same steps run a second time, in order. |
754
+ | <span id="testing-setNowTo-procedure">`setNowTo`</span> | `(isoTimestamp: string) => Effect.Effect<void>` | — | Sets the controlled test clock to the given ISO moment. |
755
+ | <span id="testing-stateOfRef-procedure">`stateOfRef`</span> | `<A>(ref: Ref.Ref<A>) => TransactionalState` | — | Makes a `Ref` a participant, so an in-memory boundary can put it back where it was when the work fails. |
756
+ | <span id="testing-typedFailureOf-procedure">`typedFailureOf`</span> | `<A, E>(effect: Effect.Effect<A, E>) => Effect.Effect<E>` | — | Extracts a use case's typed failure (Fail) through `Effect.exit` and `Cause`, rather than by matching an error message string. |
757
+ | <span id="testing-verboseOutputWanted-procedure">`verboseOutputWanted`</span> | `(environment: Readonly<Record<string, string \| undefined>> = process.env) => boolean` | — | Whether the runner should print everything. |
758
+
759
+ ### Adapters
760
+
761
+ | Name | Signature or type | Default | What it is |
762
+ | --- | --- | --- | --- |
763
+ | <span id="testing-BlobStoreUnavailableLive-adapter">`BlobStoreUnavailableLive`</span> | `Layer.Layer<BlobStore>` | — | A blob store that answers nothing: every operation fails with `BlobStoreUnavailableError`. |
764
+ | <span id="testing-DocumentNumberCounterUnavailableLive-adapter">`DocumentNumberCounterUnavailableLive`</span> | `Layer.Layer<DocumentNumberCounter>` | — | A counter that counts nothing: every request comes back as a refusal. |
765
+ | <span id="testing-EventPublisherUnavailableLive-adapter">`EventPublisherUnavailableLive`</span> | `Layer.Layer<EventPublisher>` | — | A publisher that takes nothing: every publish fails with `EventPublisherUnavailableError`. |
766
+ | <span id="testing-ExternalHttpClientUnavailableLive-adapter">`ExternalHttpClientUnavailableLive`</span> | `Layer.Layer<ExternalHttpClient>` | — | A client that reaches nothing: every call fails with `ExternalServiceUnavailableError`. |
767
+ | <span id="testing-inMemoryExternalHttpClientLive-adapter">`inMemoryExternalHttpClientLive`</span> | `(answers: AnswersByPath) => Layer.Layer<ExternalHttpClient>` | — | The in-memory client, mounted, answering the paths you seeded it with. |
768
+ | <span id="testing-InMemoryReadinessProbeLive-adapter">`InMemoryReadinessProbeLive`</span> | `Layer.Layer<ReadinessProbe>` | — | The in-memory probe, mounted. |
769
+ | <span id="testing-inMemoryTransactionBoundaryLive-adapter">`inMemoryTransactionBoundaryLive`</span> | `(participants: readonly TransactionalState[]) => Layer.Layer<TransactionBoundary>` | — | The in-memory transaction boundary, mounted over the participants you name. |
770
+ | <span id="testing-IntegrationEventOutboxUnavailableLive-adapter">`IntegrationEventOutboxUnavailableLive`</span> | `Layer.Layer<IntegrationEventOutbox>` | — | An outbox that accepts nothing: `enqueue` refuses, so a use case's write and its message go down together. |
771
+ | <span id="testing-IntegrationEventOutboxUnreadableLive-adapter">`IntegrationEventOutboxUnreadableLive`</span> | `Layer.Layer<IntegrationEventOutbox>` | — | An outbox that takes messages and then refuses to hand them back: `pending` fails while `enqueue` succeeds. |
772
+ | <span id="testing-ProcessedEventRegistryUnavailableLive-adapter">`ProcessedEventRegistryUnavailableLive`</span> | `Layer.Layer<ProcessedEventRegistry>` | — | A registry that claims nothing: every claim comes back as a refusal. |
773
+ | <span id="testing-QueueMessageProducerUnavailableLive-adapter">`QueueMessageProducerUnavailableLive`</span> | `Layer.Layer<QueueMessageProducer>` | — | A producer that answers nothing: every send fails with `QueueMessageProducerUnavailableError`. |
774
+ | <span id="testing-QueueMessageSourceUnavailableLive-adapter">`QueueMessageSourceUnavailableLive`</span> | `Layer.Layer<QueueMessageSource>` | — | A message source that answers nothing: every operation fails with `QueueMessageSourceUnavailableError`. |
775
+ | <span id="testing-ReadinessProbeUnavailableLive-adapter">`ReadinessProbeUnavailableLive`</span> | `Layer.Layer<ReadinessProbe>` | — | A probe whose database never answers. |
776
+ | <span id="testing-scriptedQueueMessageSourceLive-adapter">`scriptedQueueMessageSourceLive`</span> | `(script: readonly (readonly RawQueueMessage[])[]) => Layer.Layer<QueueMessageSource>` | — | The scripted source, mounted: each `receive` answers with the next batch of the script. |
777
+ | <span id="testing-TransactionBoundaryUnavailableLive-adapter">`TransactionBoundaryUnavailableLive`</span> | `Layer.Layer<TransactionBoundary>` | — | A transaction boundary that opens nothing: the work never runs and the caller reads the refusal. |
778
+
779
+ ## vitest
780
+
781
+ Import from `@satorio/machinery/vitest` — [the whole page](../mechanisms/vitest.mdx).
782
+
783
+ ### Values
784
+
785
+ | Name | Signature or type | Default | What it is |
786
+ | --- | --- | --- | --- |
787
+ | <span id="vitest-AwsStand-value">`AwsStand`</span> | `interface` | — | The address and the region of the live AWS stand a suite talks to. |
788
+ | <span id="vitest-FILES-THAT-FORK-A-FIBER-AND-ADJUST-TEST-CLOCK-value">`FILES_THAT_FORK_A_FIBER_AND_ADJUST_TEST_CLOCK`</span> | `readonly string[]` | — | The test files that need their own fresh module state, because they fork a fiber and move the clock. |
789
+ | <span id="vitest-LOCALSTACK-REGION-value">`LOCALSTACK_REGION`</span> | `const` | — | The one region every client and resource in a suite agrees on. |
790
+ | <span id="vitest-PortContractTester-value">`PortContractTester`</span> | `type` | — | The subset of vitest test methods a port contract needs from its tester. |
791
+ | <span id="vitest-POSTGRES-IMAGE-value">`POSTGRES_IMAGE`</span> | `const` | — | The Postgres image every live-stand test starts through testcontainers. |
792
+ | <span id="vitest-ReaderPortUnderTest-value">`ReaderPortUnderTest`</span> | `interface` | — | What a reader port's own test hands the contract. |
793
+ | <span id="vitest-RecordedStubRequest-value">`RecordedStubRequest`</span> | `interface` | — | One request the stub server received, as a test reads it back: the method and the path. |
794
+ | <span id="vitest-StubResponse-value">`StubResponse`</span> | `interface` | — | One answer the stub server gives: the status, the body and content type where there is one, and the delay before it answers. |
795
+ | <span id="vitest-StubRoute-value">`StubRoute`</span> | `interface` | — | One route the stub server serves: the method, the path, and the answers it gives in turn. |
796
+
797
+ ### Procedures
798
+
799
+ | Name | Signature or type | Default | What it is |
800
+ | --- | --- | --- | --- |
801
+ | <span id="vitest-blobStoreContract-procedure">`blobStoreContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<BlobStore>, unavailable?: Layer.Layer<BlobStore>) => void` | — | One contract, every blob store. |
802
+ | <span id="vitest-documentNumberCounterContract-procedure">`documentNumberCounterContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<DocumentNumberCounter>, unavailable?: Layer.Layer<DocumentNumberCounter>) => void` | — | One contract, every counter implementation. |
803
+ | <span id="vitest-eventPublisherContract-procedure">`eventPublisherContract`</span> | `(it: PortContractTester, implementationName: string, publisher: PublisherUnderTest, unavailable?: Layer.Layer<EventPublisher>) => void` | — | One contract, every event publisher. |
804
+ | <span id="vitest-externalHttpClientContract-procedure">`externalHttpClientContract`</span> | `(it: PortContractTester, implementationName: string, service: ExternalServiceUnderTest, unavailable?: Layer.Layer<ExternalHttpClient>) => void` | — | One contract, every external HTTP client. |
805
+ | <span id="vitest-integrationEventOutboxContract-procedure">`integrationEventOutboxContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<IntegrationEventOutbox>, unavailable?: Layer.Layer<IntegrationEventOutbox>) => void` | — | One contract, every integration event outbox. |
806
+ | <span id="vitest-onLocalstack-procedure">`onLocalstack`</span> | `(options: LocalstackSuiteOptions, subject: string, checks: SuiteChecks) => void` | — | Runs a suite against a real AWS stand (localstack) for `subject`. |
807
+ | <span id="vitest-onPostgres-procedure">`onPostgres`</span> | `(options: PostgresSuiteOptions, subject: string, checks: SuiteChecks) => void` | — | Runs a suite against a real Postgres — the container, or an externally configured database when `PGHOST` is set. |
808
+ | <span id="vitest-onPostgresContainer-procedure">`onPostgresContainer`</span> | `(options: PostgresSuiteOptions, subject: string, checks: SuiteChecks) => void` | — | Runs a suite against a container-only Postgres, ignoring any `PG*` environment variables. |
809
+ | <span id="vitest-outboxEvent-procedure">`outboxEvent`</span> | `(messageId: string, payload: { readonly [key: string]: unknown }) => OutboxMessage` | — | One message, built the way an outbox hands it over. |
810
+ | <span id="vitest-outboxMessage-procedure">`outboxMessage`</span> | `(messageId: string) => OutboxMessage` | — | One outbox message a contract enqueues and reads back, so every implementation is asked the same question. |
811
+ | <span id="vitest-processedEventRegistryContract-procedure">`processedEventRegistryContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<ProcessedEventRegistry>, unavailable?: Layer.Layer<ProcessedEventRegistry>) => void` | — | One contract, every processed event registry. |
812
+ | <span id="vitest-queueMessageProducerContract-procedure">`queueMessageProducerContract`</span> | `(it: PortContractTester, implementationName: string, producer: ProducerUnderTest, unavailable?: Layer.Layer<QueueMessageProducer>) => void` | — | One contract, every message producer. |
813
+ | <span id="vitest-queueMessageSourceContract-procedure">`queueMessageSourceContract`</span> | `(it: PortContractTester, implementationName: string, queue: QueueUnderTest, unavailable?: Layer.Layer<QueueMessageSource>) => void` | — | One contract, every message source. |
814
+ | <span id="vitest-readerPortContract-procedure">`readerPortContract`</span> | `<Subject, Value>(it: PortContractTester, port: ReaderPortUnderTest<Subject, Value>) => void` | — | One contract for a port that only reads. |
815
+ | <span id="vitest-readinessProbeContract-procedure">`readinessProbeContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<ReadinessProbe>, unavailable?: Layer.Layer<ReadinessProbe>) => void` | — | One contract, every readiness probe. |
816
+ | <span id="vitest-repoCommittableFiles-procedure">`repoCommittableFiles`</span> | `(root: string = repoRoot()) => readonly string[]` | — | Every file git would commit as it stands under `root`. |
817
+ | <span id="vitest-repoFilesUnder-procedure">`repoFilesUnder`</span> | `(root: string, directories: readonly string[], extension: string) => readonly string[]` | — | Lists files with `extension` recursively under `directories`, relative to `root`. |
818
+ | <span id="vitest-repoRoot-procedure">`repoRoot`</span> | `(cwd: string = process.cwd()) => string` | — | Root of the git repository that contains `cwd` (`process.cwd()` by default). |
819
+ | <span id="vitest-scopedStubServer-procedure">`scopedStubServer`</span> | `(routes: readonly StubRoute[]) => Effect.Effect<StubServerShape, never, Scope.Scope>` | — | Runs the stub server for the lifetime of a scope. |
820
+ | <span id="vitest-settingsContract-procedure">`settingsContract`</span> | `<A>(mechanism: string, environment: readonly EnvironmentEntry[], settings: Config.Config<A>, variablePrefix = '') => void` | — | One contract, every adapter that names variables. |
821
+ | <span id="vitest-storedBlob-procedure">`storedBlob`</span> | `(text: string) => StoredBlob` | — | One blob a contract stores and reads back, so every implementation is asked the same question. |
822
+ | <span id="vitest-transactionBoundaryContract-procedure">`transactionBoundaryContract`</span> | `(it: PortContractTester, implementationName: string, layer: Layer.Layer<TransactionBoundary>, unavailable?: Layer.Layer<TransactionBoundary>) => void` | — | One contract, every transaction boundary. |
823
+ | <span id="vitest-truncateTables-procedure">`truncateTables`</span> | `(tableNames: readonly string[]) => Effect.Effect<void, SqlError, SqlClient.SqlClient>` | — | Empties the named tables in one query, for a test that needs a familiar initial state. |
824
+
825
+ ### Adapters
826
+
827
+ | Name | Signature or type | Default | What it is |
828
+ | --- | --- | --- | --- |
829
+ | <span id="vitest-postgresInContainerLive-adapter">`postgresInContainerLive`</span> | `(options: PostgresSuiteOptions) => Layer.Layer<never>` | — | Builds the Postgres layer for a suite from a fresh container only, ignoring any `PG*` environment variables. |
830
+ | <span id="vitest-PostgresPortsUnderTestLive-adapter">`PostgresPortsUnderTestLive`</span> | `Layer.Layer<PostgresPorts \| PgClient.PgClient \| SqlClient.SqlClient>` | — | The Postgres mechanism's own ports, on the suite's database. |
831
+ | <span id="vitest-postgresUnderTestLive-adapter">`postgresUnderTestLive`</span> | `(options: PostgresSuiteOptions) => Layer.Layer<never>` | — | The Postgres layer a suite runs on: the configured database when the environment names one, a fresh container when it does not, migrated either way. |
832
+
833
+ ### Guards
834
+
835
+ | Name | Signature or type | Default | What it is |
836
+ | --- | --- | --- | --- |
837
+ | <span id="vitest-oneEffectInstanceGuard-guard">`oneEffectInstanceGuard`</span> | `(options: SingleEffectInstanceOptions = {}) => void` | — | Registers a vitest suite that fails when a tree holds more than one copy of Effect. |
838
+ | <span id="vitest-oneFastCheckInstanceGuard-guard">`oneFastCheckInstanceGuard`</span> | `() => void` | — | Registers a vitest suite that fails when the property library resolves to two module instances. |
839
+ | <span id="vitest-testclockForkIsolationGuard-guard">`testclockForkIsolationGuard`</span> | `(knownIsolatedFiles: readonly string[], options: TestclockForkIsolationOptions) => void` | — | Registers a vitest suite that fails when a test moves the clock in a forked fiber outside its own list. |
840
+
841
+ ## Recap
842
+
843
+ You now have one place that names everything this package hands you, and one sentence beside each name. It comes out of the source, so when the source moves this page moves with it. Come back whenever you know what you want and not what it goes by.