@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,29 @@
1
+ package: @satorio/machinery
2
+ version: 0.2.1
3
+ mechanism:
4
+ mechanism: workflow
5
+ import: @satorio/machinery/workflow
6
+ kind: foundation
7
+ page: mechanisms/workflow
8
+ what: "Public entry to the workflow mechanism: the combinators a use case composes its own beat from."
9
+ whatUk: "Публічний вхід до механізму workflow: комбінатори, з яких процедура складає власний такт."
10
+ rows[19]{name,kind,signature,fallback,caption,captionUk,anchor}:
11
+ ClaimOnce,value,type,"","The exactly-once claim: shared ground for every use case that takes an event or command once.","Резервація рівно один раз: спільний ґрунт для кожної процедури, яка бере подію або команду один раз.",workflow-ClaimOnce-value
12
+ DEFAULT_PUBLISH_PENDING_EVENTS_SETTINGS,value,PublishPendingEventsSettings,"",The pace the relay keeps when a service names none of its own.,"Темп, який тримає трансмітер вихідних подій, коли сервіс не називає власного.",workflow-DEFAULT-PUBLISH-PENDING-EVENTS-SETTINGS-value
13
+ OnClaimMatchers,value,interface,"","The two branches `onClaim` takes: what to do when the event was already claimed, and what to do when this run claims it.","Дві гілки, які бере `onClaim`: що робити, коли подію вже зарезервовано, і що робити, коли її резервує цей прогін.",workflow-OnClaimMatchers-value
14
+ PublishPendingEventsSettings,value,interface,"","How the relay paces itself: how many messages one beat takes, and how long it waits between beats.","Як трансмітер вихідних подій задає собі темп: скільки повідомлень бере один такт і скільки він чекає між тактами.",workflow-PublishPendingEventsSettings-value
15
+ UpcastStep,value,interface,"","One lift, from the version it names to the next one up.","Один підйом, від названої версії до наступної вгору.",workflow-UpcastStep-value
16
+ VersionedEventDefinition,value,interface,"",An event stored yesterday is read by today's code.,"Подію, збережену вчора, читає сьогоднішній код.",workflow-VersionedEventDefinition-value
17
+ claimAsProcessedAt,procedure,"(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.","Резервує з `processedAt`, поданим викликачем, — для обробника, який уже прочитав годинник і мусить зберегти саме ту мить.",workflow-claimAsProcessedAt-procedure
18
+ claimAsProcessedNow,procedure,"(idempotencyKey: string) => ClaimOnce","","Claims with the current time, for a caller that only needs the claim.","Резервує з поточним часом — для викликача, якому потрібна лише резервація.",workflow-claimAsProcessedNow-procedure
19
+ decodeStoredPayload,procedure,"<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.,Підіймає збережений payload до поточної версії і декодує його поточною схемою.,workflow-decodeStoredPayload-procedure
20
+ keepPublishingPendingEvents,procedure,"(settings: PublishPendingEventsSettings = DEFAULT_PUBLISH_PENDING_EVENTS_SETTINGS) => Effect.Effect<never, never, IntegrationEventOutbox | EventPublisher>","",Runs the outbox relay for as long as the service lives.,"Крутить трансмітер вихідних подій стільки, скільки живе сервіс.",workflow-keepPublishingPendingEvents-procedure
21
+ onClaim,procedure,"<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.","Розгалужується на стані резервації: `AlreadyProcessed` іде одним шляхом, `ClaimAccepted` — іншим.",workflow-onClaim-procedure
22
+ publishOneBatch,procedure,"(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.","Один такт трансмітера вихідних подій: узяти пачку недоставлених повідомлень, віддати її публікаторові, тоді позначити її відправленою.",workflow-publishOneBatch-procedure
23
+ transactionally,procedure,"<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.","Загортає роботу в межу транзакції: дістає `TransactionBoundary` з контексту і проганяє роботу крізь неї.",workflow-transactionally-procedure
24
+ upcastToCurrentVersion,procedure,"<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.","Підіймає збережений payload від версії, якою його записали, до версії, яку читає цей код, по одному кроку на версію, по порядку.",workflow-upcastToCurrentVersion-procedure
25
+ MissingUpcastStepError,failure,"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.","Одна версія між збереженим payload і поточною не має кроку підйому, тож підйом не доходить до кінця.",workflow-MissingUpcastStepError-failure
26
+ PublishPendingEventsFailure,failure,type,"","What one beat of the relay can meet: the outbox did not answer, or the publisher did not.","Що може зустріти один такт трансмітера: буфер трансмітера не відповів або публікатор не відповів.",workflow-PublishPendingEventsFailure-failure
27
+ SchemaVersionFromTheFutureError,failure,"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.,"Збережений payload каже, що його записала новіша версія цього коду, ніж та, що його читає.",workflow-SchemaVersionFromTheFutureError-failure
28
+ UpcastStepFailedError,failure,"Data.TaggedError<{ readonly eventType: string; readonly fromVersion: number; readonly cause: unknown }>","",An upcast step threw while lifting the payload one version up.,"Крок підйому кинув помилку, поки підіймав payload на версію вгору.",workflow-UpcastStepFailedError-failure
29
+ VersionedPayloadFailure,failure,type,"",Every way reading a stored payload can refuse.,"Кожен спосіб, яким читання збереженого payload може відмовити.",workflow-VersionedPayloadFailure-failure
@@ -0,0 +1,45 @@
1
+ /**
2
+ * What one run of the command comes back with: the whole of what it
3
+ * prints, and the code it leaves behind. A refusal and an answer travel
4
+ * in the same shape, so the runner never decides for itself which of the
5
+ * two it is holding.
6
+ *
7
+ * @internal
8
+ */
9
+ export interface CommandAnswer {
10
+ readonly text: string;
11
+ readonly code: number;
12
+ }
13
+ /**
14
+ * The three lines a refusal is written in here: what happened, why that
15
+ * stops this command, and what to do about it.
16
+ *
17
+ * @internal
18
+ */
19
+ export declare const refusalOf: (happened: string, matters: string, todo: string) => string;
20
+ /**
21
+ * Every command this runner answers, one line each, in the order a
22
+ * caller meets them.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare const USAGE: string;
27
+ /**
28
+ * One run of the command, against the dictionary directory this package
29
+ * ships at `root`. It prints a file that already exists rather than
30
+ * building one, so it asks for no test runner, no compiler and no
31
+ * network — an agent gets the same answer from a node_modules directory
32
+ * as a reader gets from the repository.
33
+ *
34
+ * @internal
35
+ */
36
+ export declare const runMachinery: (argv: readonly string[], root: string) => CommandAnswer;
37
+ /**
38
+ * Whether a write failed because the reader on the other end of the pipe
39
+ * closed it. A caller who pipes an answer into `head` closes it on
40
+ * purpose, and a runner that dies with a stack trace over that reports a
41
+ * fault that never happened.
42
+ *
43
+ * @internal
44
+ */
45
+ export declare const isBrokenPipe: (error: unknown) => boolean;
@@ -0,0 +1,113 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * The three lines a refusal is written in here: what happened, why that
5
+ * stops this command, and what to do about it.
6
+ *
7
+ * @internal
8
+ */
9
+ export const refusalOf = (happened, matters, todo) => [
10
+ `what happened: ${happened}`,
11
+ `why this matters: ${matters}`,
12
+ `what to do: ${todo}`,
13
+ ].join('\n');
14
+ /**
15
+ * Every command this runner answers, one line each, in the order a
16
+ * caller meets them.
17
+ *
18
+ * @internal
19
+ */
20
+ export const USAGE = [
21
+ 'satorio-machinery surface [mechanism] [--json|--toon]',
22
+ 'satorio-machinery mechanisms [--json|--toon]',
23
+ 'satorio-machinery reference [--uk]',
24
+ ].join('\n');
25
+ const missingFileRefusal = (path) => refusalOf(`this install carries no ${path}, so there is nothing to print.`, 'the dictionary is what an agent reads instead of the source. An ' +
26
+ 'empty answer reads like a package with nothing in it, which is a ' +
27
+ 'worse lie than a refusal.', 'reinstall @satorio/machinery from a version that ships its ' +
28
+ 'dictionary, or read the same thing in the repository with ' +
29
+ 'bun run surface.');
30
+ const unknownMechanismRefusal = (wanted, known) => refusalOf(`this package has no mechanism called "${wanted}", so there is no ` +
31
+ 'card to hand you.', 'a card is what an agent reads before it writes a line against a ' +
32
+ 'mechanism. A silent empty answer would read as a mechanism with ' +
33
+ 'nothing in it.', `ask for one of ${known.join(', ')}, or run satorio-machinery ` +
34
+ 'mechanisms to read the index first.');
35
+ const unknownCommandRefusal = (wanted) => refusalOf(wanted === ''
36
+ ? 'this command was run with nothing to do.'
37
+ : `"${wanted}" is not a command this runner answers.`, 'a runner that guesses what you meant prints something you did not ' +
38
+ 'ask for, and an agent believes it.', `run one of these instead:\n${USAGE}`);
39
+ const twoFormsRefusal = () => refusalOf('both --json and --toon were asked for in one run.', 'the two forms say the same thing in different shapes, so a run that ' +
40
+ 'takes both has to pick one behind your back.', 'ask for one of them, or neither: the tabular form is what you get ' +
41
+ 'when you say nothing, because it is the cheaper one to read.');
42
+ const fileText = (root, path) => {
43
+ try {
44
+ return readFileSync(join(root, path), 'utf8');
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ };
50
+ const mechanismNames = (root) => {
51
+ const text = fileText(root, 'index.json');
52
+ if (text === null)
53
+ return null;
54
+ const index = JSON.parse(text);
55
+ return (index.index ?? []).map((entry) => entry.mechanism);
56
+ };
57
+ const shippedFile = (root, path) => {
58
+ const text = fileText(root, path);
59
+ if (text === null)
60
+ return { text: missingFileRefusal(path), code: 1 };
61
+ return { text: text.replace(/\n$/, ''), code: 0 };
62
+ };
63
+ const surfaceAnswer = (root, wanted, extension) => {
64
+ if (wanted === undefined)
65
+ return shippedFile(root, `all.${extension}`);
66
+ const known = mechanismNames(root);
67
+ if (known === null)
68
+ return { text: missingFileRefusal('index.json'), code: 1 };
69
+ if (!known.includes(wanted)) {
70
+ return { text: unknownMechanismRefusal(wanted, known), code: 1 };
71
+ }
72
+ return shippedFile(root, `${wanted}.${extension}`);
73
+ };
74
+ /**
75
+ * One run of the command, against the dictionary directory this package
76
+ * ships at `root`. It prints a file that already exists rather than
77
+ * building one, so it asks for no test runner, no compiler and no
78
+ * network — an agent gets the same answer from a node_modules directory
79
+ * as a reader gets from the repository.
80
+ *
81
+ * @internal
82
+ */
83
+ export const runMachinery = (argv, root) => {
84
+ const words = argv.filter((argument) => !argument.startsWith('--'));
85
+ const flags = argv.filter((argument) => argument.startsWith('--'));
86
+ if (flags.includes('--help') || words[0] === 'help') {
87
+ return { text: USAGE, code: 0 };
88
+ }
89
+ if (flags.includes('--json') && flags.includes('--toon')) {
90
+ return { text: twoFormsRefusal(), code: 1 };
91
+ }
92
+ const extension = flags.includes('--json') ? 'json' : 'toon';
93
+ if (words[0] === 'surface')
94
+ return surfaceAnswer(root, words[1], extension);
95
+ if (words[0] === 'mechanisms') {
96
+ return shippedFile(root, `index.${extension}`);
97
+ }
98
+ if (words[0] === 'reference') {
99
+ return shippedFile(root, flags.includes('--uk') ? 'reference/uk/api.mdx' : 'reference/api.mdx');
100
+ }
101
+ return { text: unknownCommandRefusal(words[0] ?? ''), code: 1 };
102
+ };
103
+ /**
104
+ * Whether a write failed because the reader on the other end of the pipe
105
+ * closed it. A caller who pipes an answer into `head` closes it on
106
+ * purpose, and a runner that dies with a stack trace over that reports a
107
+ * fault that never happened.
108
+ *
109
+ * @internal
110
+ */
111
+ export const isBrokenPipe = (error) => typeof error === 'object' &&
112
+ error !== null &&
113
+ error.code === 'EPIPE';
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { isBrokenPipe, runMachinery } from './bin/command.js';
5
+ const dictionaryRoot = join(fileURLToPath(new URL('.', import.meta.url)), '..', 'dictionary');
6
+ const answer = runMachinery(process.argv.slice(2), dictionaryRoot);
7
+ process.stdout.on('error', (error) => {
8
+ process.exitCode = isBrokenPipe(error) ? answer.code : 1;
9
+ });
10
+ process.stdout.write(`${answer.text}\n`);
11
+ process.exitCode = answer.code;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Use as the replacer argument to `JSON.stringify`. It turns bigint into a
3
+ * decimal string, so the exact integer survives instead of being silently
4
+ * rounded by a floating-point number.
5
+ */
6
+ export declare const bigIntsAsDecimalStrings: (_key: string, value: unknown) => unknown;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Use as the replacer argument to `JSON.stringify`. It turns bigint into a
3
+ * decimal string, so the exact integer survives instead of being silently
4
+ * rounded by a floating-point number.
5
+ */
6
+ export const bigIntsAsDecimalStrings = (_key, value) => (typeof value === 'bigint' ? value.toString(10) : value);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Turns an array of string literals into a closed set: the values, a union
3
+ * type of their members, and an `is` guard, all from one source. The guard
4
+ * can never drift from the list it guards.
5
+ */
6
+ export interface ClosedSet<T extends readonly string[]> {
7
+ readonly values: T;
8
+ readonly is: (value: string) => value is T[number];
9
+ }
10
+ /**
11
+ * Builds a closed set from an array of string literals, so the guard and the
12
+ * list it guards come from one source.
13
+ */
14
+ export declare const closedSet: <const T extends readonly string[]>(values: T) => ClosedSet<T>;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Builds a closed set from an array of string literals, so the guard and the
3
+ * list it guards come from one source.
4
+ */
5
+ export const closedSet = (values) => ({
6
+ values,
7
+ is: (value) => values.includes(value),
8
+ });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Base class for domain errors. It sets `error.name` to the subclass's own
3
+ * class name via `new.target`, so a subclass never repeats
4
+ * `this.name = '...'`. Pass the message through `super(...)`.
5
+ */
6
+ export declare class DomainError extends Error {
7
+ constructor(message: string);
8
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Base class for domain errors. It sets `error.name` to the subclass's own
3
+ * class name via `new.target`, so a subclass never repeats
4
+ * `this.name = '...'`. Pass the message through `super(...)`.
5
+ */
6
+ export class DomainError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = new.target.name;
10
+ }
11
+ }
@@ -0,0 +1,124 @@
1
+ import { Config, ConfigError, Option, Redacted } from 'effect';
2
+ /**
3
+ * A refusal in the three parts a reader needs: what happened, why this
4
+ * mechanism cannot go on without it, and what to do next. All three
5
+ * fields are required, so a one-line refusal cannot be expressed here.
6
+ */
7
+ export interface Refusal {
8
+ readonly what: string;
9
+ readonly why: string;
10
+ readonly whatToDo: string;
11
+ }
12
+ /**
13
+ * Sews a refusal into the one line an operator reads in a log or a
14
+ * startup failure.
15
+ */
16
+ export declare const refusalText: (refusal: Refusal) => string;
17
+ /**
18
+ * The one failure a refusing variable raises, with its three parts sewn into a
19
+ * single line.
20
+ *
21
+ * The failure a reader meets when one named variable refuses: the three parts,
22
+ * sewn into the one line, against the name of the variable that asked for
23
+ * them. A mechanism that chooses between two variables builds its own refusal
24
+ * from here rather than writing a second `ConfigError` of its own.
25
+ */
26
+ export declare const refusalFor: (name: string, refusal: Refusal) => ConfigError.ConfigError;
27
+ /**
28
+ * Reads a variable that a mechanism cannot work without, and refuses in
29
+ * three parts when it is missing or blank. The reading goes through
30
+ * `Config.option` on purpose: `Config.validate` fires only on a value
31
+ * that is present and invalid, so a variable nobody set comes back as
32
+ * `MissingData` with the runtime's own wording and the three parts
33
+ * written here never reach the newcomer who simply forgot to set it.
34
+ */
35
+ export declare const requiredText: (name: string, refusal: Refusal) => Config.Config<string>;
36
+ /**
37
+ * Reads a secret a mechanism cannot work without, and refuses in the same
38
+ * three parts when it is missing or blank. The value comes back redacted,
39
+ * so it never reaches a log line by accident.
40
+ */
41
+ export declare const requiredSecret: (name: string, refusal: Refusal) => Config.Config<Redacted.Redacted>;
42
+ /**
43
+ * Reads a whole number inside a range, and refuses in three parts when it is
44
+ * not one.
45
+ *
46
+ * Reads a whole number a mechanism cannot work without, and refuses in the
47
+ * same three parts when it is missing, blank, not a whole number, or outside
48
+ * the range the mechanism can act on. `lowest` and `highest` are both
49
+ * inclusive.
50
+ */
51
+ export declare const wholeNumberWithin: (name: string, lowest: number, highest: number, refusal: Refusal) => Config.Config<number>;
52
+ /**
53
+ * Reads a whole number a mechanism is happy to do without, and falls
54
+ * back to the value it names when nobody set the variable. A value that
55
+ * *is* set still has to be a whole number inside the range, and refuses
56
+ * in the same three parts when it is not: a fallback covers the operator
57
+ * who left the variable alone, never the one who typed something the
58
+ * mechanism cannot act on.
59
+ */
60
+ export declare const wholeNumberFallingBackTo: (name: string, lowest: number, highest: number, fallback: number, refusal: Refusal) => Config.Config<number>;
61
+ /**
62
+ * Reads a variable that is legitimately optional with no default,
63
+ * because somebody outside this process decides it. The answer is
64
+ * `Option.none` when the variable is unset or blank, so a caller reads
65
+ * one absence rather than two.
66
+ */
67
+ export declare const optionalText: (name: string) => Config.Config<Option.Option<string>>;
68
+ /**
69
+ * Reads a secret that is legitimately optional, and hands back
70
+ * `Option.none` when it is unset or blank. The value stays redacted the
71
+ * whole way, so a mechanism that chooses between two ways of proving who
72
+ * it is can ask whether the secret is there without ever holding it in
73
+ * the clear.
74
+ */
75
+ export declare const optionalSecret: (name: string) => Config.Config<Option.Option<Redacted.Redacted>>;
76
+ /**
77
+ * Which of three states a variable stands in. There is no fourth state
78
+ * and no silence: a variable either has a safe fallback, refuses without
79
+ * one, or is handed on to somebody outside this process.
80
+ */
81
+ export type EnvironmentState = {
82
+ readonly state: 'fallsBackTo';
83
+ readonly value: string;
84
+ } | {
85
+ readonly state: 'refuses';
86
+ readonly refusal: Refusal;
87
+ } | {
88
+ readonly state: 'handedOn';
89
+ readonly consequence: string;
90
+ };
91
+ /**
92
+ * The variable is safe to omit, and this is what happens instead.
93
+ */
94
+ export declare const fallsBackTo: (value: string) => EnvironmentState;
95
+ /**
96
+ * The mechanism cannot work without the variable, and this is the
97
+ * three-part text a reader meets when it is missing.
98
+ */
99
+ export declare const refuses: (refusal: Refusal) => EnvironmentState;
100
+ /**
101
+ * The variable is legitimately optional with no default, because
102
+ * somebody else decides it, and this is what follows from leaving it
103
+ * unset.
104
+ */
105
+ export declare const handedOn: (consequence: string) => EnvironmentState;
106
+ /**
107
+ * One variable a mechanism reads, and the one state it stands in.
108
+ *
109
+ * One variable a mechanism reads: its name — whole, or the suffix an
110
+ * application prefixes at mount time — what it is for, and the one state it
111
+ * stands in. A mechanism's `ENVIRONMENT` is the list of these, and it is the
112
+ * only place a variable name is written.
113
+ */
114
+ export interface EnvironmentEntry {
115
+ readonly name: string;
116
+ readonly prefixed?: boolean;
117
+ readonly what: string;
118
+ readonly state: EnvironmentState;
119
+ }
120
+ /**
121
+ * The name an operator sets, with `<PREFIX>` standing in front of a
122
+ * suffix the application chooses at mount time.
123
+ */
124
+ export declare const variableNameOf: (entry: EnvironmentEntry) => string;
@@ -0,0 +1,115 @@
1
+ import { Config, ConfigError, Either, Option, Redacted } from 'effect';
2
+ /**
3
+ * Sews a refusal into the one line an operator reads in a log or a
4
+ * startup failure.
5
+ */
6
+ export const refusalText = (refusal) => `${refusal.what} ${refusal.why} ${refusal.whatToDo}`;
7
+ /**
8
+ * The one failure a refusing variable raises, with its three parts sewn into a
9
+ * single line.
10
+ *
11
+ * The failure a reader meets when one named variable refuses: the three parts,
12
+ * sewn into the one line, against the name of the variable that asked for
13
+ * them. A mechanism that chooses between two variables builds its own refusal
14
+ * from here rather than writing a second `ConfigError` of its own.
15
+ */
16
+ export const refusalFor = (name, refusal) => ConfigError.InvalidData([name], refusalText(refusal));
17
+ const invalid = (name, refusal) => Either.left(refusalFor(name, refusal));
18
+ const blank = (value) => value.trim().length === 0;
19
+ /**
20
+ * Reads a variable that a mechanism cannot work without, and refuses in
21
+ * three parts when it is missing or blank. The reading goes through
22
+ * `Config.option` on purpose: `Config.validate` fires only on a value
23
+ * that is present and invalid, so a variable nobody set comes back as
24
+ * `MissingData` with the runtime's own wording and the three parts
25
+ * written here never reach the newcomer who simply forgot to set it.
26
+ */
27
+ export const requiredText = (name, refusal) => Config.option(Config.string(name)).pipe(Config.mapOrFail((held) => Option.match(held, {
28
+ onNone: () => invalid(name, refusal),
29
+ onSome: (value) => blank(value) ? invalid(name, refusal) : Either.right(value.trim()),
30
+ })));
31
+ /**
32
+ * Reads a secret a mechanism cannot work without, and refuses in the same
33
+ * three parts when it is missing or blank. The value comes back redacted,
34
+ * so it never reaches a log line by accident.
35
+ */
36
+ export const requiredSecret = (name, refusal) => Config.option(Config.redacted(name)).pipe(Config.mapOrFail((held) => Option.match(held, {
37
+ onNone: () => invalid(name, refusal),
38
+ onSome: (secret) => blank(Redacted.value(secret))
39
+ ? invalid(name, refusal)
40
+ : Either.right(secret),
41
+ })));
42
+ const wholeNumberIn = (name, text, lowest, highest, refusal) => {
43
+ const value = Number(text);
44
+ return Number.isInteger(value) && value >= lowest && value <= highest
45
+ ? Either.right(value)
46
+ : invalid(name, refusal);
47
+ };
48
+ /**
49
+ * Reads a whole number inside a range, and refuses in three parts when it is
50
+ * not one.
51
+ *
52
+ * Reads a whole number a mechanism cannot work without, and refuses in the
53
+ * same three parts when it is missing, blank, not a whole number, or outside
54
+ * the range the mechanism can act on. `lowest` and `highest` are both
55
+ * inclusive.
56
+ */
57
+ export const wholeNumberWithin = (name, lowest, highest, refusal) => requiredText(name, refusal).pipe(Config.mapOrFail((text) => wholeNumberIn(name, text, lowest, highest, refusal)));
58
+ /**
59
+ * Reads a whole number a mechanism is happy to do without, and falls
60
+ * back to the value it names when nobody set the variable. A value that
61
+ * *is* set still has to be a whole number inside the range, and refuses
62
+ * in the same three parts when it is not: a fallback covers the operator
63
+ * who left the variable alone, never the one who typed something the
64
+ * mechanism cannot act on.
65
+ */
66
+ export const wholeNumberFallingBackTo = (name, lowest, highest, fallback, refusal) => Config.option(Config.string(name)).pipe(Config.mapOrFail((held) => Option.match(held, {
67
+ onNone: () => Either.right(fallback),
68
+ onSome: (text) => blank(text)
69
+ ? Either.right(fallback)
70
+ : wholeNumberIn(name, text.trim(), lowest, highest, refusal),
71
+ })));
72
+ /**
73
+ * Reads a variable that is legitimately optional with no default,
74
+ * because somebody outside this process decides it. The answer is
75
+ * `Option.none` when the variable is unset or blank, so a caller reads
76
+ * one absence rather than two.
77
+ */
78
+ export const optionalText = (name) => Config.option(Config.string(name)).pipe(Config.map(Option.flatMap((value) => blank(value) ? Option.none() : Option.some(value.trim()))));
79
+ /**
80
+ * Reads a secret that is legitimately optional, and hands back
81
+ * `Option.none` when it is unset or blank. The value stays redacted the
82
+ * whole way, so a mechanism that chooses between two ways of proving who
83
+ * it is can ask whether the secret is there without ever holding it in
84
+ * the clear.
85
+ */
86
+ export const optionalSecret = (name) => Config.option(Config.redacted(name)).pipe(Config.map(Option.flatMap((secret) => blank(Redacted.value(secret)) ? Option.none() : Option.some(secret))));
87
+ /**
88
+ * The variable is safe to omit, and this is what happens instead.
89
+ */
90
+ export const fallsBackTo = (value) => ({
91
+ state: 'fallsBackTo',
92
+ value,
93
+ });
94
+ /**
95
+ * The mechanism cannot work without the variable, and this is the
96
+ * three-part text a reader meets when it is missing.
97
+ */
98
+ export const refuses = (refusal) => ({
99
+ state: 'refuses',
100
+ refusal,
101
+ });
102
+ /**
103
+ * The variable is legitimately optional with no default, because
104
+ * somebody else decides it, and this is what follows from leaving it
105
+ * unset.
106
+ */
107
+ export const handedOn = (consequence) => ({
108
+ state: 'handedOn',
109
+ consequence,
110
+ });
111
+ /**
112
+ * The name an operator sets, with `<PREFIX>` standing in front of a
113
+ * suffix the application chooses at mount time.
114
+ */
115
+ export const variableNameOf = (entry) => entry.prefixed === true ? `<PREFIX>${entry.name}` : entry.name;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public entry to the core mechanism: the few pieces every other mechanism
3
+ * leans on, and which lean on nothing themselves. It gives you the pieces
4
+ * every other mechanism leans on and which lean on nothing themselves — a safe
5
+ * unique id, a closed set of allowed values, exact bigints on the wire, the
6
+ * base domain error, and the three-part refusal an adapter uses to say what a
7
+ * variable is for and what to do when it is missing.
8
+ */
9
+ export { bigIntsAsDecimalStrings } from './bigint-json.js';
10
+ export { type ClosedSet, closedSet } from './closed-set.js';
11
+ export { DomainError } from './domain-error.js';
12
+ export { type EnvironmentEntry, type EnvironmentState, fallsBackTo, handedOn, optionalSecret, optionalText, type Refusal, refusalFor, refusalText, refuses, requiredSecret, requiredText, variableNameOf, wholeNumberFallingBackTo, wholeNumberWithin, } from './environment.js';
13
+ export { isUlid, NotAUlidError, type Ulid, ulid } from './ulid.js';
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public entry to the core mechanism: the few pieces every other mechanism
3
+ * leans on, and which lean on nothing themselves. It gives you the pieces
4
+ * every other mechanism leans on and which lean on nothing themselves — a safe
5
+ * unique id, a closed set of allowed values, exact bigints on the wire, the
6
+ * base domain error, and the three-part refusal an adapter uses to say what a
7
+ * variable is for and what to do when it is missing.
8
+ */
9
+ export { bigIntsAsDecimalStrings } from './bigint-json.js';
10
+ export { closedSet } from './closed-set.js';
11
+ export { DomainError } from './domain-error.js';
12
+ export { fallsBackTo, handedOn, optionalSecret, optionalText, refusalFor, refusalText, refuses, requiredSecret, requiredText, variableNameOf, wholeNumberFallingBackTo, wholeNumberWithin, } from './environment.js';
13
+ export { isUlid, NotAUlidError, ulid } from './ulid.js';
@@ -0,0 +1,27 @@
1
+ import { DomainError } from './domain-error.js';
2
+ declare const ulidBrand: unique symbol;
3
+ /**
4
+ * A ULID: the identifier a machine mints for a record, sortable by the moment
5
+ * it was minted, and a plain string everywhere it travels.
6
+ */
7
+ export type Ulid = string & {
8
+ readonly [ulidBrand]: 'Ulid';
9
+ };
10
+ /**
11
+ * Whether a string is a ULID, as a type guard, so a caller narrows the type
12
+ * without raising anything.
13
+ */
14
+ export declare const isUlid: (value: string) => value is Ulid;
15
+ /**
16
+ * What a caller meets when a string that is not a ULID reaches `ulid`; the
17
+ * message quotes the exact value received.
18
+ */
19
+ export declare class NotAUlidError extends DomainError {
20
+ constructor(value: string);
21
+ }
22
+ /**
23
+ * Reads a string as a ULID and throws `NotAUlidError` when it is not one, so a
24
+ * raw string comes through one door.
25
+ */
26
+ export declare const ulid: (raw: string) => Ulid;
27
+ export {};
@@ -0,0 +1,27 @@
1
+ import { DomainError } from './domain-error.js';
2
+ const TWENTY_SIX_UPPERCASE_CROCKFORD_SYMBOLS_STARTING_BELOW_EIGHT = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
3
+ /**
4
+ * Whether a string is a ULID, as a type guard, so a caller narrows the type
5
+ * without raising anything.
6
+ */
7
+ export const isUlid = (value) => TWENTY_SIX_UPPERCASE_CROCKFORD_SYMBOLS_STARTING_BELOW_EIGHT.test(value);
8
+ /**
9
+ * What a caller meets when a string that is not a ULID reaches `ulid`; the
10
+ * message quotes the exact value received.
11
+ */
12
+ export class NotAUlidError extends DomainError {
13
+ constructor(value) {
14
+ super(`A ULID is 26 Crockford Base32 characters in upper case: the first ` +
15
+ `character is 0-7, and the rest exclude I, L, O, and U. ` +
16
+ `Received ${JSON.stringify(value)}.`);
17
+ }
18
+ }
19
+ /**
20
+ * Reads a string as a ULID and throws `NotAUlidError` when it is not one, so a
21
+ * raw string comes through one door.
22
+ */
23
+ export const ulid = (raw) => {
24
+ if (!isUlid(raw))
25
+ throw new NotAUlidError(raw);
26
+ return raw;
27
+ };
@@ -0,0 +1,36 @@
1
+ import '@pothos/plugin-directives';
2
+ import '@pothos/plugin-sub-graph';
3
+ import { hasResolvableKey } from '@pothos/plugin-federation';
4
+ /**
5
+ * The two variations of one schema: `Public` (external) and `Internal`
6
+ * (admin and service operations). Federation (`@key` + `resolveReference`)
7
+ * turns each variation into a subgraph for the gateway.
8
+ *
9
+ * @internal
10
+ */
11
+ export declare const SUB_GRAPH_NAMES: readonly ["Public", "Internal"];
12
+ /**
13
+ * @internal
14
+ */
15
+ export type SubGraphName = (typeof SUB_GRAPH_NAMES)[number];
16
+ /**
17
+ * The federation and subgraph settings every schema in this package
18
+ * shares, fixed here so two services cannot drift apart.
19
+ *
20
+ * @internal
21
+ */
22
+ export declare const subGraphOptions: {
23
+ defaultForTypes: ("Public" | "Internal")[];
24
+ fieldsInheritFromTypes: boolean;
25
+ explicitlyIncludeType: (type: Parameters<typeof hasResolvableKey>[0]) => boolean;
26
+ };
27
+ /**
28
+ * Returns a builder factory carrying the resolver context type. The context
29
+ * itself belongs to your service, so this returns a factory, not a ready
30
+ * instance. Every service shares the same plugins and subgraph settings,
31
+ * fixed here.
32
+ */
33
+ export declare const makeSubGraphSchemaBuilder: <Context extends object>() => PothosSchemaTypes.SchemaBuilder<PothosSchemaTypes.ExtendDefaultTypes<{
34
+ Context: Context;
35
+ SubGraphs: SubGraphName;
36
+ }>>;