@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,26 @@
1
+ import { Context, type Effect } from 'effect';
2
+ declare const QueueMessageProducerUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "QueueMessageProducerUnavailableError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * The queue producer did not answer; `operation` names the call and `cause`
7
+ * carries the driver's own error.
8
+ */
9
+ export declare class QueueMessageProducerUnavailableError extends QueueMessageProducerUnavailableError_base<{
10
+ readonly operation: string;
11
+ readonly cause: unknown;
12
+ }> {
13
+ }
14
+ /**
15
+ * What a producer offers: one call that puts a message body onto the queue.
16
+ */
17
+ export interface QueueMessageProducerShape {
18
+ readonly send: (body: string) => Effect.Effect<void, QueueMessageProducerUnavailableError>;
19
+ }
20
+ declare const QueueMessageProducer_base: Context.TagClass<QueueMessageProducer, "QueueMessageProducer", QueueMessageProducerShape>;
21
+ /**
22
+ * The port a use case asks for when it sends a message to a queue.
23
+ */
24
+ export declare class QueueMessageProducer extends QueueMessageProducer_base {
25
+ }
26
+ export {};
@@ -0,0 +1,12 @@
1
+ import { Context, Data } from 'effect';
2
+ /**
3
+ * The queue producer did not answer; `operation` names the call and `cause`
4
+ * carries the driver's own error.
5
+ */
6
+ export class QueueMessageProducerUnavailableError extends Data.TaggedError('QueueMessageProducerUnavailableError') {
7
+ }
8
+ /**
9
+ * The port a use case asks for when it sends a message to a queue.
10
+ */
11
+ export class QueueMessageProducer extends Context.Tag('QueueMessageProducer')() {
12
+ }
@@ -0,0 +1,39 @@
1
+ import { Context, type Effect } from 'effect';
2
+ /**
3
+ * One message as the queue hands it over: its own id, the receipt an
4
+ * acknowledgement quotes, and the body, still text.
5
+ */
6
+ export interface RawQueueMessage {
7
+ readonly messageId: string;
8
+ readonly receiptHandle: string;
9
+ readonly body: string;
10
+ }
11
+ declare const QueueMessageSourceUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
12
+ readonly _tag: "QueueMessageSourceUnavailableError";
13
+ } & Readonly<A>;
14
+ /**
15
+ * The queue source did not answer; `operation` names the call and `cause`
16
+ * carries the driver's own error.
17
+ */
18
+ export declare class QueueMessageSourceUnavailableError extends QueueMessageSourceUnavailableError_base<{
19
+ readonly operation: string;
20
+ readonly cause: unknown;
21
+ }> {
22
+ }
23
+ /**
24
+ * A source of queue messages: it receives a batch and acknowledges what was
25
+ * taken. The app never knows whether SQS, a test stub, or another queue
26
+ * stands behind it.
27
+ */
28
+ export interface QueueMessageSourceShape {
29
+ readonly receive: Effect.Effect<readonly RawQueueMessage[], QueueMessageSourceUnavailableError>;
30
+ readonly acknowledge: (receiptHandle: string) => Effect.Effect<void, QueueMessageSourceUnavailableError>;
31
+ }
32
+ declare const QueueMessageSource_base: Context.TagClass<QueueMessageSource, "QueueMessageSource", QueueMessageSourceShape>;
33
+ /**
34
+ * The port a consumer asks for when it receives messages from a queue and
35
+ * acknowledges what it took.
36
+ */
37
+ export declare class QueueMessageSource extends QueueMessageSource_base {
38
+ }
39
+ export {};
@@ -0,0 +1,13 @@
1
+ import { Context, Data } from 'effect';
2
+ /**
3
+ * The queue source did not answer; `operation` names the call and `cause`
4
+ * carries the driver's own error.
5
+ */
6
+ export class QueueMessageSourceUnavailableError extends Data.TaggedError('QueueMessageSourceUnavailableError') {
7
+ }
8
+ /**
9
+ * The port a consumer asks for when it receives messages from a queue and
10
+ * acknowledges what it took.
11
+ */
12
+ export class QueueMessageSource extends Context.Tag('QueueMessageSource')() {
13
+ }
@@ -0,0 +1,27 @@
1
+ import { Context, type Effect } from 'effect';
2
+ declare const DatabaseDidNotAnswerError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "DatabaseDidNotAnswerError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * The readiness check against the database did not come back; `reason` says
7
+ * what stopped it.
8
+ */
9
+ export declare class DatabaseDidNotAnswerError extends DatabaseDidNotAnswerError_base<{
10
+ readonly reason: string;
11
+ }> {
12
+ }
13
+ /**
14
+ * What a readiness probe offers: one check that the database answers, so the
15
+ * endpoint reports a dependency rather than a guess.
16
+ */
17
+ export interface ReadinessProbeShape {
18
+ readonly verifyDatabaseAnswers: Effect.Effect<void, DatabaseDidNotAnswerError>;
19
+ }
20
+ declare const ReadinessProbe_base: Context.TagClass<ReadinessProbe, "ReadinessProbe", ReadinessProbeShape>;
21
+ /**
22
+ * The port the readiness endpoint asks for when it has to say whether this
23
+ * service can take traffic.
24
+ */
25
+ export declare class ReadinessProbe extends ReadinessProbe_base {
26
+ }
27
+ export {};
@@ -0,0 +1,13 @@
1
+ import { Context, Data } from 'effect';
2
+ /**
3
+ * The readiness check against the database did not come back; `reason` says
4
+ * what stopped it.
5
+ */
6
+ export class DatabaseDidNotAnswerError extends Data.TaggedError('DatabaseDidNotAnswerError') {
7
+ }
8
+ /**
9
+ * The port the readiness endpoint asks for when it has to say whether this
10
+ * service can take traffic.
11
+ */
12
+ export class ReadinessProbe extends Context.Tag('ReadinessProbe')() {
13
+ }
@@ -0,0 +1,28 @@
1
+ import { Context, type Effect } from 'effect';
2
+ declare const TransactionBoundaryUnavailableError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
3
+ readonly _tag: "TransactionBoundaryUnavailableError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * The transaction driver did not answer; `operation` names the call and
7
+ * `cause` carries the driver's own error.
8
+ */
9
+ export declare class TransactionBoundaryUnavailableError extends TransactionBoundaryUnavailableError_base<{
10
+ readonly operation: string;
11
+ readonly cause: unknown;
12
+ }> {
13
+ }
14
+ /**
15
+ * What a transaction boundary offers: one call that runs work inside a
16
+ * transaction, and rolls the whole of it back when the work fails.
17
+ */
18
+ export interface TransactionBoundaryShape {
19
+ readonly inTransaction: <A, E, R>(work: Effect.Effect<A, E, R>) => Effect.Effect<A, E | TransactionBoundaryUnavailableError, R>;
20
+ }
21
+ declare const TransactionBoundary_base: Context.TagClass<TransactionBoundary, "TransactionBoundary", TransactionBoundaryShape>;
22
+ /**
23
+ * The port a use case asks for when its writes must land together or not at
24
+ * all.
25
+ */
26
+ export declare class TransactionBoundary extends TransactionBoundary_base {
27
+ }
28
+ export {};
@@ -0,0 +1,13 @@
1
+ import { Context, Data } from 'effect';
2
+ /**
3
+ * The transaction driver did not answer; `operation` names the call and
4
+ * `cause` carries the driver's own error.
5
+ */
6
+ export class TransactionBoundaryUnavailableError extends Data.TaggedError('TransactionBoundaryUnavailableError') {
7
+ }
8
+ /**
9
+ * The port a use case asks for when its writes must land together or not at
10
+ * all.
11
+ */
12
+ export class TransactionBoundary extends Context.Tag('TransactionBoundary')() {
13
+ }
@@ -0,0 +1,51 @@
1
+ import type { ConnectionOptions } from 'node:tls';
2
+ import { FileSystem } from '@effect/platform';
3
+ import type { PlatformError } from '@effect/platform/Error';
4
+ import { SqlError } from '@effect/sql/SqlError';
5
+ import { Effect, Option, type Scope } from 'effect';
6
+ import { Pool, type PoolConfig } from 'pg';
7
+ import type { PostgresConnectionSettings } from './settings.js';
8
+ /**
9
+ * Reads what the driver needs to encrypt the connection: `false` to talk
10
+ * in the clear, otherwise whether the chain must verify and, when a root
11
+ * certificate is named, the certificate itself.
12
+ *
13
+ * @internal
14
+ */
15
+ export declare const sslOptionsFor: (settings: PostgresConnectionSettings) => Effect.Effect<boolean | ConnectionOptions, PlatformError, FileSystem.FileSystem>;
16
+ /**
17
+ * Opens the channel a connection asks a fresh IAM token from. It holds
18
+ * nothing to release — signing a token is arithmetic over credentials,
19
+ * not a socket — so it has no scoped twin, and the region stays optional
20
+ * because the AWS SDK finds its own when nobody names one.
21
+ *
22
+ * @internal
23
+ */
24
+ export declare const openIamTokenTransport: (settings: PostgresConnectionSettings, region: Option.Option<string>) => (() => Promise<string>);
25
+ /**
26
+ * Builds the pool options for one service connection: the address, the
27
+ * schema as `search_path`, the name `pg_stat_activity` shows, and
28
+ * whichever of the two ways of proving who you are is in force.
29
+ *
30
+ * @internal
31
+ */
32
+ export declare const poolOptionsFor: (settings: PostgresConnectionSettings, ssl: boolean | ConnectionOptions) => PoolConfig;
33
+ /**
34
+ * Opens the connection pool. This is the one place in this mechanism
35
+ * where the `pg` driver is constructed, so every path to a live socket
36
+ * goes through `scopedPostgresTransport` and closes with its scope.
37
+ *
38
+ * @internal
39
+ */
40
+ export declare const openPostgresTransport: (options: PoolConfig) => Pool;
41
+ /**
42
+ * Builds an effect that acquires a Postgres connection pool and releases it
43
+ * when its scope closes. Pass a function that builds `PoolConfig` from
44
+ * settings and SSL options, plus the message to use if the pool fails to
45
+ * open; call the result with settings and SSL options to run it. One shape
46
+ * serves both the service and the migration runner — `optionsFor` and the
47
+ * failure message are the only two parts that vary between them.
48
+ *
49
+ * @internal
50
+ */
51
+ export declare const scopedPostgresTransport: (optionsFor: (settings: PostgresConnectionSettings, ssl: boolean | ConnectionOptions) => PoolConfig, poolCreationFailureMessage: string) => (settings: PostgresConnectionSettings, ssl: boolean | ConnectionOptions) => Effect.Effect<Pool, SqlError, Scope.Scope>;
@@ -0,0 +1,81 @@
1
+ import { Signer } from '@aws-sdk/rds-signer';
2
+ import { FileSystem } from '@effect/platform';
3
+ import { SqlError } from '@effect/sql/SqlError';
4
+ import { Effect, Match, Option, Redacted } from 'effect';
5
+ import { Pool } from 'pg';
6
+ const encryptionIsDisabled = (sslMode) => sslMode === 'disable';
7
+ const certificateChainMustBeVerified = (sslMode) => sslMode === 'verify-ca' || sslMode === 'verify-full';
8
+ /**
9
+ * Reads what the driver needs to encrypt the connection: `false` to talk
10
+ * in the clear, otherwise whether the chain must verify and, when a root
11
+ * certificate is named, the certificate itself.
12
+ *
13
+ * @internal
14
+ */
15
+ export const sslOptionsFor = (settings) => Effect.gen(function* () {
16
+ if (encryptionIsDisabled(settings.sslMode))
17
+ return false;
18
+ const rejectUnauthorized = certificateChainMustBeVerified(settings.sslMode);
19
+ if (Option.isNone(settings.sslRootCertificatePath))
20
+ return { rejectUnauthorized };
21
+ const fileSystem = yield* FileSystem.FileSystem;
22
+ const ca = yield* fileSystem.readFileString(settings.sslRootCertificatePath.value);
23
+ return { rejectUnauthorized, ca };
24
+ });
25
+ /**
26
+ * Opens the channel a connection asks a fresh IAM token from. It holds
27
+ * nothing to release — signing a token is arithmetic over credentials,
28
+ * not a socket — so it has no scoped twin, and the region stays optional
29
+ * because the AWS SDK finds its own when nobody names one.
30
+ *
31
+ * @internal
32
+ */
33
+ export const openIamTokenTransport = (settings, region) => {
34
+ const signer = new Signer({
35
+ hostname: settings.host,
36
+ port: settings.port,
37
+ username: settings.user,
38
+ ...(Option.isSome(region) ? { region: region.value } : {}),
39
+ });
40
+ return () => signer.getAuthToken();
41
+ };
42
+ const passwordFor = (settings) => Match.value(settings.authentication).pipe(Match.tag('AwsIamAuthentication', ({ region }) => openIamTokenTransport(settings, region)), Match.tag('PasswordAuthentication', ({ password }) => Redacted.value(password)), Match.exhaustive);
43
+ /**
44
+ * Builds the pool options for one service connection: the address, the
45
+ * schema as `search_path`, the name `pg_stat_activity` shows, and
46
+ * whichever of the two ways of proving who you are is in force.
47
+ *
48
+ * @internal
49
+ */
50
+ export const poolOptionsFor = (settings, ssl) => ({
51
+ host: settings.host,
52
+ port: settings.port,
53
+ user: settings.user,
54
+ database: settings.database,
55
+ options: `-c search_path=${settings.schema}`,
56
+ application_name: settings.applicationName,
57
+ ssl,
58
+ password: passwordFor(settings),
59
+ });
60
+ /**
61
+ * Opens the connection pool. This is the one place in this mechanism
62
+ * where the `pg` driver is constructed, so every path to a live socket
63
+ * goes through `scopedPostgresTransport` and closes with its scope.
64
+ *
65
+ * @internal
66
+ */
67
+ export const openPostgresTransport = (options) => new Pool(options);
68
+ /**
69
+ * Builds an effect that acquires a Postgres connection pool and releases it
70
+ * when its scope closes. Pass a function that builds `PoolConfig` from
71
+ * settings and SSL options, plus the message to use if the pool fails to
72
+ * open; call the result with settings and SSL options to run it. One shape
73
+ * serves both the service and the migration runner — `optionsFor` and the
74
+ * failure message are the only two parts that vary between them.
75
+ *
76
+ * @internal
77
+ */
78
+ export const scopedPostgresTransport = (optionsFor, poolCreationFailureMessage) => (settings, ssl) => Effect.acquireRelease(Effect.try({
79
+ try: () => openPostgresTransport(optionsFor(settings, ssl)),
80
+ catch: (cause) => new SqlError({ cause, message: poolCreationFailureMessage }),
81
+ }), (pool) => Effect.promise(() => pool.end()).pipe(Effect.orDie));
@@ -0,0 +1,14 @@
1
+ import { PgClient } from '@effect/sql-pg';
2
+ import { DocumentNumberCounterUnavailableError } from '@satorio/machinery/ports';
3
+ import { Effect } from 'effect';
4
+ /**
5
+ * Builds the counter on the service's own pool. One statement takes the
6
+ * next count and reads it back, so two callers asking for the same
7
+ * client and month at the same instant queue behind one row rather than
8
+ * both reading the same number.
9
+ *
10
+ * @internal
11
+ */
12
+ export declare const makePgDocumentNumberCounter: Effect.Effect<{
13
+ nextCount: (input: import("@satorio/machinery/ports").DocumentNumberCountInput) => Effect.Effect<number, DocumentNumberCounterUnavailableError>;
14
+ }, never, PgClient.PgClient>;
@@ -0,0 +1,27 @@
1
+ import { PgClient } from '@effect/sql-pg';
2
+ import { DocumentNumberCounterUnavailableError, portUnavailable, } from '@satorio/machinery/ports';
3
+ import { Effect } from 'effect';
4
+ /**
5
+ * Builds the counter on the service's own pool. One statement takes the
6
+ * next count and reads it back, so two callers asking for the same
7
+ * client and month at the same instant queue behind one row rather than
8
+ * both reading the same number.
9
+ *
10
+ * @internal
11
+ */
12
+ export const makePgDocumentNumberCounter = Effect.gen(function* () {
13
+ const sql = yield* PgClient.PgClient;
14
+ const unavailable = portUnavailable(DocumentNumberCounterUnavailableError);
15
+ const nextCount = (input) => Effect.gen(function* () {
16
+ const rows = yield* sql `
17
+ INSERT INTO document_number_counter
18
+ (client_code, reporting_month, issued)
19
+ VALUES (${input.clientCode}::text, ${input.reportingMonth}::text, 1)
20
+ ON CONFLICT (client_code, reporting_month) DO UPDATE
21
+ SET issued = document_number_counter.issued + 1
22
+ RETURNING issued
23
+ `;
24
+ return rows[0]?.issued ?? 0;
25
+ }).pipe(Effect.catchTag('SqlError', unavailable('nextCount')));
26
+ return { nextCount };
27
+ });
@@ -0,0 +1,28 @@
1
+ declare const MigrationLockBusyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
2
+ readonly _tag: "MigrationLockBusyError";
3
+ } & Readonly<A>;
4
+ /**
5
+ * A second process already holds the migration lock and did not let go
6
+ * within the retry window. Nothing was applied; the run is safe to
7
+ * repeat once the other process finishes.
8
+ */
9
+ export declare class MigrationLockBusyError extends MigrationLockBusyError_base<{
10
+ readonly lockName: string;
11
+ }> {
12
+ }
13
+ declare const ClaimRaceWindowMissedError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
14
+ readonly _tag: "ClaimRaceWindowMissedError";
15
+ } & Readonly<A>;
16
+ /**
17
+ * The claim statement took the lock and read who won it in one go, and
18
+ * the read saw neither. That happens when a competing claim has won but
19
+ * has not committed as of this statement's own snapshot. The registry
20
+ * retries a fixed number of times and never lets this failure out.
21
+ *
22
+ * @internal
23
+ */
24
+ export declare class ClaimRaceWindowMissedError extends ClaimRaceWindowMissedError_base<{
25
+ readonly eventId: string;
26
+ }> {
27
+ }
28
+ export {};
@@ -0,0 +1,18 @@
1
+ import { Data } from 'effect';
2
+ /**
3
+ * A second process already holds the migration lock and did not let go
4
+ * within the retry window. Nothing was applied; the run is safe to
5
+ * repeat once the other process finishes.
6
+ */
7
+ export class MigrationLockBusyError extends Data.TaggedError('MigrationLockBusyError') {
8
+ }
9
+ /**
10
+ * The claim statement took the lock and read who won it in one go, and
11
+ * the read saw neither. That happens when a competing claim has won but
12
+ * has not committed as of this statement's own snapshot. The registry
13
+ * retries a fixed number of times and never lets this failure out.
14
+ *
15
+ * @internal
16
+ */
17
+ export class ClaimRaceWindowMissedError extends Data.TaggedError('ClaimRaceWindowMissedError') {
18
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Public entry to the postgres mechanism: every port this machinery defines,
3
+ * bound to a real database. It gives you every port this machinery defines,
4
+ * bound to a real database — the transaction boundary, the exactly-once claim,
5
+ * the outbox, the document number counter and the readiness probe — with the
6
+ * connection read from the environment, a migration runner that holds an
7
+ * advisory lock, and the helpers a store reaches for when a SQL failure has to
8
+ * become a domain failure or a JSON document has to reach a `jsonb` column.
9
+ */
10
+ export { MigrationLockBusyError } from './failures.js';
11
+ export { jsonbValue } from './jsonb-value.js';
12
+ export { MigrationPgClientLive, PgDocumentNumberCounterLive, PgIntegrationEventOutboxLive, PgProcessedEventRegistryLive, PgReadinessProbeLive, PgTransactionBoundaryLive, PostgresClientLive, type PostgresPorts, PostgresPortsLive, PostgresPortsOnBunLive, } from './layer.js';
13
+ export { type AdvisoryLock, holdingAdvisoryLock, postgresAdvisoryLock, } from './migrations/advisory-lock.js';
14
+ export { applyMigrations, MACHINERY_MIGRATIONS_DIRECTORY, MIGRATION_LOCK_NAME, migrationLockNameFor, reportApplied, } from './migrations/runner.js';
15
+ export { READINESS_QUERY_DEADLINE_MILLIS, READINESS_REASON_WHEN_THE_DATABASE_STAYS_SILENT, READINESS_REASON_WHEN_THE_QUERY_TIMES_OUT, readinessProbeAsking, } from './readiness-probe.js';
16
+ export { configProviderPreferring, DEFAULT_APPLICATION_NAME, DEFAULT_AUTH_MODE, DEFAULT_POSTGRES_PORT, DEFAULT_POSTGRES_SCHEMA, DEFAULT_POSTGRES_SSL_MODE, ENVIRONMENT, POSTGRES_SSL_MODES, type PostgresAuthentication, type PostgresConnectionSettings, type PostgresSslMode, postgresConnectionSettings, schemaDefaultingTo, } from './settings.js';
17
+ export { isUniqueViolation } from './sql-failure.js';
18
+ export { firstRow, onUniqueViolation } from './store-failure.js';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Public entry to the postgres mechanism: every port this machinery defines,
3
+ * bound to a real database. It gives you every port this machinery defines,
4
+ * bound to a real database — the transaction boundary, the exactly-once claim,
5
+ * the outbox, the document number counter and the readiness probe — with the
6
+ * connection read from the environment, a migration runner that holds an
7
+ * advisory lock, and the helpers a store reaches for when a SQL failure has to
8
+ * become a domain failure or a JSON document has to reach a `jsonb` column.
9
+ */
10
+ export { MigrationLockBusyError } from './failures.js';
11
+ export { jsonbValue } from './jsonb-value.js';
12
+ export { MigrationPgClientLive, PgDocumentNumberCounterLive, PgIntegrationEventOutboxLive, PgProcessedEventRegistryLive, PgReadinessProbeLive, PgTransactionBoundaryLive, PostgresClientLive, PostgresPortsLive, PostgresPortsOnBunLive, } from './layer.js';
13
+ export { holdingAdvisoryLock, postgresAdvisoryLock, } from './migrations/advisory-lock.js';
14
+ export { applyMigrations, MACHINERY_MIGRATIONS_DIRECTORY, MIGRATION_LOCK_NAME, migrationLockNameFor, reportApplied, } from './migrations/runner.js';
15
+ export { READINESS_QUERY_DEADLINE_MILLIS, READINESS_REASON_WHEN_THE_DATABASE_STAYS_SILENT, READINESS_REASON_WHEN_THE_QUERY_TIMES_OUT, readinessProbeAsking, } from './readiness-probe.js';
16
+ export { configProviderPreferring, DEFAULT_APPLICATION_NAME, DEFAULT_AUTH_MODE, DEFAULT_POSTGRES_PORT, DEFAULT_POSTGRES_SCHEMA, DEFAULT_POSTGRES_SSL_MODE, ENVIRONMENT, POSTGRES_SSL_MODES, postgresConnectionSettings, schemaDefaultingTo, } from './settings.js';
17
+ export { isUniqueViolation } from './sql-failure.js';
18
+ export { firstRow, onUniqueViolation } from './store-failure.js';
@@ -0,0 +1,15 @@
1
+ import { PgClient } from '@effect/sql-pg';
2
+ import { IntegrationEventOutboxUnavailableError, type OutboxMessage } from '@satorio/machinery/ports';
3
+ import { Effect } from 'effect';
4
+ /**
5
+ * Builds the outbox on the service's own pool: an insert that ignores a
6
+ * repeat, a read of what is still undelivered, and a stamp that marks a
7
+ * batch handed on.
8
+ *
9
+ * @internal
10
+ */
11
+ export declare const makePgIntegrationEventOutbox: Effect.Effect<{
12
+ enqueue: (messages: readonly OutboxMessage[]) => Effect.Effect<void, IntegrationEventOutboxUnavailableError>;
13
+ pending: (limit: number) => Effect.Effect<readonly OutboxMessage[], IntegrationEventOutboxUnavailableError>;
14
+ markDispatched: (messageIds: readonly string[]) => Effect.Effect<void, IntegrationEventOutboxUnavailableError>;
15
+ }, never, PgClient.PgClient>;
@@ -0,0 +1,60 @@
1
+ import { PgClient } from '@effect/sql-pg';
2
+ import { IntegrationEventOutboxUnavailableError, portUnavailable, } from '@satorio/machinery/ports';
3
+ import { DateTime, Effect } from 'effect';
4
+ import { jsonbValue } from './jsonb-value.js';
5
+ const outboxMessageOf = (row) => ({
6
+ messageId: row.messageId,
7
+ eventType: row.eventType,
8
+ schemaVersion: row.schemaVersion,
9
+ occurredAt: DateTime.unsafeMake(row.occurredAt),
10
+ payload: row.payload,
11
+ });
12
+ /**
13
+ * Builds the outbox on the service's own pool: an insert that ignores a
14
+ * repeat, a read of what is still undelivered, and a stamp that marks a
15
+ * batch handed on.
16
+ *
17
+ * @internal
18
+ */
19
+ export const makePgIntegrationEventOutbox = Effect.gen(function* () {
20
+ const sql = yield* PgClient.PgClient;
21
+ const unavailable = portUnavailable(IntegrationEventOutboxUnavailableError);
22
+ const enqueue = (messages) => Effect.forEach(messages, (message) => sql `
23
+ INSERT INTO integration_event_outbox
24
+ (message_id, event_type, schema_version, occurred_at, payload)
25
+ VALUES
26
+ (${message.messageId}::text,
27
+ ${message.eventType}::text,
28
+ ${message.schemaVersion}::integer,
29
+ ${DateTime.toDate(message.occurredAt)}::timestamptz,
30
+ ${jsonbValue(sql, message.payload)})
31
+ ON CONFLICT (message_id) DO NOTHING
32
+ `, { discard: true }).pipe(Effect.catchTag('SqlError', unavailable('enqueue')));
33
+ const pending = (limit) => sql `
34
+ SELECT message_id AS "messageId",
35
+ event_type AS "eventType",
36
+ schema_version AS "schemaVersion",
37
+ occurred_at AS "occurredAt",
38
+ payload
39
+ FROM integration_event_outbox
40
+ WHERE dispatched_at IS NULL
41
+ ORDER BY sequence_number ASC
42
+ LIMIT ${limit}::integer
43
+ `.pipe(Effect.map((rows) => rows.map(outboxMessageOf)), Effect.catchTag('SqlError', unavailable('pending')));
44
+ const markDispatched = (messageIds) => Effect.gen(function* () {
45
+ if (messageIds.length === 0)
46
+ return;
47
+ const dispatchedAt = yield* DateTime.now;
48
+ yield* sql `
49
+ UPDATE integration_event_outbox
50
+ SET dispatched_at = ${DateTime.toDate(dispatchedAt)}::timestamptz
51
+ WHERE message_id IN ${sql.in(messageIds)}
52
+ AND dispatched_at IS NULL
53
+ `;
54
+ }).pipe(Effect.catchTag('SqlError', unavailable('markDispatched')));
55
+ return {
56
+ enqueue,
57
+ pending,
58
+ markDispatched,
59
+ };
60
+ });
@@ -0,0 +1,10 @@
1
+ import type { SqlClient } from '@effect/sql';
2
+ import type { Fragment } from '@effect/sql/Statement';
3
+ /**
4
+ * Hands a value to a `jsonb` column as JSON, whatever its shape. Write
5
+ * it wherever a query holds a JSON parameter, and the parameter travels
6
+ * as text the database casts, so an array stays an array instead of
7
+ * becoming the driver's own array literal. A value the encoder cannot
8
+ * write at all, `undefined` among them, lands as JSON null.
9
+ */
10
+ export declare const jsonbValue: (sql: SqlClient.SqlClient, value: unknown) => Fragment;
@@ -0,0 +1,9 @@
1
+ const jsonTextOf = (value) => JSON.stringify(value) ?? 'null';
2
+ /**
3
+ * Hands a value to a `jsonb` column as JSON, whatever its shape. Write
4
+ * it wherever a query holds a JSON parameter, and the parameter travels
5
+ * as text the database casts, so an array stays an array instead of
6
+ * becoming the driver's own array literal. A value the encoder cannot
7
+ * write at all, `undefined` among them, lands as JSON null.
8
+ */
9
+ export const jsonbValue = (sql, value) => sql `${jsonTextOf(value)}::jsonb`;
@@ -0,0 +1,57 @@
1
+ import type { FileSystem } from '@effect/platform';
2
+ import type { PlatformError } from '@effect/platform/Error';
3
+ import { SqlClient } from '@effect/sql';
4
+ import type { SqlError } from '@effect/sql/SqlError';
5
+ import { PgClient } from '@effect/sql-pg';
6
+ import { DocumentNumberCounter, IntegrationEventOutbox, ProcessedEventRegistry, ReadinessProbe, TransactionBoundary } from '@satorio/machinery/ports';
7
+ import { Layer } from 'effect';
8
+ import type { ConfigError } from 'effect/ConfigError';
9
+ /**
10
+ * The `@effect/sql-pg` client every other layer here builds on, opened
11
+ * from the environment `settings.ts` names.
12
+ */
13
+ export declare const PostgresClientLive: Layer.Layer<PgClient.PgClient | SqlClient.SqlClient, ConfigError | PlatformError | SqlError, FileSystem.FileSystem>;
14
+ /**
15
+ * The client the migration runner uses: one connection, under its own name.
16
+ *
17
+ * The same client for the migration runner: one connection, and its own name
18
+ * in `pg_stat_activity`, so a long migration is easy to spot next to the
19
+ * service's own pool.
20
+ */
21
+ export declare const MigrationPgClientLive: Layer.Layer<PgClient.PgClient | SqlClient.SqlClient, ConfigError | PlatformError | SqlError, FileSystem.FileSystem>;
22
+ /**
23
+ * The transaction boundary on a real Postgres transaction.
24
+ */
25
+ export declare const PgTransactionBoundaryLive: Layer.Layer<TransactionBoundary, never, SqlClient.SqlClient>;
26
+ /**
27
+ * The exactly-once claim on a real `processed_event` table.
28
+ */
29
+ export declare const PgProcessedEventRegistryLive: Layer.Layer<ProcessedEventRegistry, never, PgClient.PgClient>;
30
+ /**
31
+ * The document number counter on a real `document_number_counter` table.
32
+ */
33
+ export declare const PgDocumentNumberCounterLive: Layer.Layer<DocumentNumberCounter, never, PgClient.PgClient>;
34
+ /**
35
+ * The outbox on a real `integration_event_outbox` table.
36
+ */
37
+ export declare const PgIntegrationEventOutboxLive: Layer.Layer<IntegrationEventOutbox, never, PgClient.PgClient>;
38
+ /**
39
+ * The readiness probe on one `SELECT 1` against the service's own pool.
40
+ */
41
+ export declare const PgReadinessProbeLive: Layer.Layer<ReadinessProbe, never, SqlClient.SqlClient>;
42
+ /**
43
+ * The ports this mechanism implements, named together as one type. Your
44
+ * service adds its own stores alongside these in the composition root, on
45
+ * the same database client.
46
+ */
47
+ export type PostgresPorts = ProcessedEventRegistry | IntegrationEventOutbox | DocumentNumberCounter | TransactionBoundary | ReadinessProbe;
48
+ /**
49
+ * Every port this mechanism implements, on one client, for a service
50
+ * that supplies its own `FileSystem`.
51
+ */
52
+ export declare const PostgresPortsLive: Layer.Layer<PostgresPorts | PgClient.PgClient | SqlClient.SqlClient, ConfigError | PlatformError | SqlError, FileSystem.FileSystem>;
53
+ /**
54
+ * The same bundle on Bun's own file system, which is the whole Postgres
55
+ * side of the machinery in one layer.
56
+ */
57
+ export declare const PostgresPortsOnBunLive: Layer.Layer<PostgresPorts | PgClient.PgClient | SqlClient.SqlClient, ConfigError | PlatformError | SqlError>;