@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,35 @@
1
+ import SchemaBuilder from '@pothos/core';
2
+ import '@pothos/plugin-directives';
3
+ import '@pothos/plugin-sub-graph';
4
+ import DirectivesPlugin from '@pothos/plugin-directives';
5
+ import FederationPlugin, { hasResolvableKey } from '@pothos/plugin-federation';
6
+ import SubGraphPlugin from '@pothos/plugin-sub-graph';
7
+ /**
8
+ * The two variations of one schema: `Public` (external) and `Internal`
9
+ * (admin and service operations). Federation (`@key` + `resolveReference`)
10
+ * turns each variation into a subgraph for the gateway.
11
+ *
12
+ * @internal
13
+ */
14
+ export const SUB_GRAPH_NAMES = ['Public', 'Internal'];
15
+ /**
16
+ * The federation and subgraph settings every schema in this package
17
+ * shares, fixed here so two services cannot drift apart.
18
+ *
19
+ * @internal
20
+ */
21
+ export const subGraphOptions = {
22
+ defaultForTypes: [...SUB_GRAPH_NAMES],
23
+ fieldsInheritFromTypes: true,
24
+ explicitlyIncludeType: (type) => hasResolvableKey(type),
25
+ };
26
+ /**
27
+ * Returns a builder factory carrying the resolver context type. The context
28
+ * itself belongs to your service, so this returns a factory, not a ready
29
+ * instance. Every service shares the same plugins and subgraph settings,
30
+ * fixed here.
31
+ */
32
+ export const makeSubGraphSchemaBuilder = () => new SchemaBuilder({
33
+ plugins: [DirectivesPlugin, FederationPlugin, SubGraphPlugin],
34
+ subGraphs: subGraphOptions,
35
+ });
@@ -0,0 +1,36 @@
1
+ import { type Effect, Exit, ParseResult } from 'effect';
2
+ import { GraphQLError } from 'graphql';
3
+ import type { OperationFailure } from './failures.js';
4
+ /**
5
+ * Maps a GraphQL failure to a `GraphQLError`: the same three-class operation
6
+ * failure channel, plus input decoder failures — no second catalog. Names
7
+ * and details come from the domain failure and land in `extensions.code`.
8
+ */
9
+ export declare const asGraphQLError: (failure: OperationFailure | ParseResult.ParseError) => GraphQLError;
10
+ /**
11
+ * Runs the use case's Effect program and returns its result: a success
12
+ * value, a `GraphQLError` for a typed failure, or `INTERNAL` for a defect.
13
+ */
14
+ /**
15
+ * @internal
16
+ */
17
+ export type RunOperations<R> = <A>(program: Effect.Effect<A, OperationFailure | ParseResult.ParseError, R>) => Promise<A>;
18
+ /**
19
+ * The minimal capability a resolver borrows from the runtime: run a program
20
+ * that needs `R` and return its `Exit`. Both `Runtime.runPromiseExit` and
21
+ * `ManagedRuntime.runPromiseExit` fit this shape, so production and tests
22
+ * share one code path.
23
+ */
24
+ export type RunOperationsExit<R> = <A, E>(program: Effect.Effect<A, E, R>) => Promise<Exit.Exit<A, E>>;
25
+ /**
26
+ * What a resolver reads from its context: one call that runs a use
27
+ * case's program and answers with its value or a `GraphQLError`.
28
+ */
29
+ export interface GraphQLContext<R> {
30
+ readonly runOperations: RunOperations<R>;
31
+ }
32
+ /**
33
+ * Builds that context around the runtime's own `runPromiseExit`, so a
34
+ * resolver never touches the runtime directly.
35
+ */
36
+ export declare const graphqlContextFrom: <R>(runExit: RunOperationsExit<R>) => GraphQLContext<R>;
@@ -0,0 +1,69 @@
1
+ import { Cause, Exit, Option, ParseResult } from 'effect';
2
+ import { GraphQLError } from 'graphql';
3
+ /**
4
+ * Maps a GraphQL failure to a `GraphQLError`: the same three-class operation
5
+ * failure channel, plus input decoder failures — no second catalog. Names
6
+ * and details come from the domain failure and land in `extensions.code`.
7
+ */
8
+ export const asGraphQLError = (failure) => {
9
+ switch (failure._tag) {
10
+ case 'SubjectNotFoundError':
11
+ return new GraphQLError(`${failure.subject} ${failure.id} not found`, {
12
+ extensions: {
13
+ code: 'NOT_FOUND',
14
+ reason: 'subject-not-found',
15
+ subject: failure.subject,
16
+ id: failure.id,
17
+ },
18
+ });
19
+ case 'OperationRejectedError':
20
+ return new GraphQLError(`${failure.reason}: ${failure.detail}`, {
21
+ extensions: {
22
+ code: 'REJECTED',
23
+ reason: failure.reason,
24
+ detail: failure.detail,
25
+ },
26
+ });
27
+ case 'OperationsUnavailableError':
28
+ return new GraphQLError(`Service unavailable: ${failure.operation}`, {
29
+ extensions: {
30
+ code: 'UNAVAILABLE',
31
+ reason: 'service-unavailable',
32
+ operation: failure.operation,
33
+ },
34
+ });
35
+ case 'ParseError': {
36
+ const detail = ParseResult.TreeFormatter.formatErrorSync(failure);
37
+ return new GraphQLError(`Invalid input: ${detail.split('\n')[0]}`, {
38
+ extensions: {
39
+ code: 'BAD_USER_INPUT',
40
+ reason: 'invalid-input',
41
+ detail,
42
+ },
43
+ });
44
+ }
45
+ default:
46
+ return new GraphQLError('Unknown failure', {
47
+ extensions: { code: 'INTERNAL', reason: 'internal-error' },
48
+ });
49
+ }
50
+ };
51
+ /**
52
+ * Builds that context around the runtime's own `runPromiseExit`, so a
53
+ * resolver never touches the runtime directly.
54
+ */
55
+ export const graphqlContextFrom = (runExit) => ({
56
+ runOperations: async (program) => {
57
+ const exit = await runExit(program);
58
+ if (Exit.isSuccess(exit)) {
59
+ return exit.value;
60
+ }
61
+ const failure = Cause.failureOption(exit.cause);
62
+ if (Option.isSome(failure)) {
63
+ throw asGraphQLError(failure.value);
64
+ }
65
+ throw new GraphQLError('Internal service error', {
66
+ extensions: { code: 'INTERNAL', detail: Cause.pretty(exit.cause) },
67
+ });
68
+ },
69
+ });
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The proof that every failure a service can raise is mapped at this
3
+ * boundary. Give it the union of your own failures and the union of the
4
+ * tags your resolver classifies, then assign `true` to it once, beside
5
+ * the lists. A failure nobody classified turns the type into that
6
+ * failure's own tag, so the compiler stops and names it rather than
7
+ * letting it reach a caller as `INTERNAL`.
8
+ */
9
+ export type EveryFailureIsClassified<Failures extends {
10
+ readonly _tag: string;
11
+ }, Classified extends string> = [Exclude<Failures['_tag'], Classified>] extends [never] ? true : Exclude<Failures['_tag'], Classified>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,62 @@
1
+ import type { Refusal } from '@satorio/machinery/core';
2
+ declare const SubjectNotFoundError_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: "SubjectNotFoundError";
4
+ } & Readonly<A>;
5
+ /**
6
+ * One of exactly three operation failure classes below — the closed set a
7
+ * resolver maps to. An untagged failure is a defect, not a domain error.
8
+ */
9
+ export declare class SubjectNotFoundError extends SubjectNotFoundError_base<{
10
+ readonly subject: string;
11
+ readonly id: string;
12
+ }> {
13
+ }
14
+ declare const OperationRejectedError_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 & {
15
+ readonly _tag: "OperationRejectedError";
16
+ } & Readonly<A>;
17
+ /**
18
+ * A resolver's rule rejected the operation, and `reason` names the cause it
19
+ * recognized.
20
+ *
21
+ * `reason` is the named cause from the service's shared failure taxonomy when
22
+ * a domain failure is recognized; otherwise it is the tag of the rule that
23
+ * rejected the operation.
24
+ */
25
+ export declare class OperationRejectedError extends OperationRejectedError_base<{
26
+ readonly rule: string;
27
+ readonly reason: string;
28
+ readonly detail: string;
29
+ }> {
30
+ }
31
+ declare const OperationsUnavailableError_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 & {
32
+ readonly _tag: "OperationsUnavailableError";
33
+ } & Readonly<A>;
34
+ /**
35
+ * A resolver's own dependency did not answer; `cause` carries the port's own
36
+ * failure.
37
+ */
38
+ export declare class OperationsUnavailableError extends OperationsUnavailableError_base<{
39
+ readonly operation: string;
40
+ readonly cause: unknown;
41
+ }> {
42
+ }
43
+ /**
44
+ * Everything a resolver may fail with, as one closed set: not found, rejected,
45
+ * or unavailable.
46
+ */
47
+ export type OperationFailure = SubjectNotFoundError | OperationRejectedError | OperationsUnavailableError;
48
+ declare const ServerCannotListenError_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 & {
49
+ readonly _tag: "ServerCannotListenError";
50
+ } & Readonly<A>;
51
+ /**
52
+ * The socket never opened. `port` is the port the server asked for, and
53
+ * `refusal` says in three parts which variable decides that port and how
54
+ * to hand it another one.
55
+ */
56
+ export declare class ServerCannotListenError extends ServerCannotListenError_base<{
57
+ readonly port: number;
58
+ readonly refusal: Refusal;
59
+ readonly cause: unknown;
60
+ }> {
61
+ }
62
+ export {};
@@ -0,0 +1,30 @@
1
+ import { Data } from 'effect';
2
+ /**
3
+ * One of exactly three operation failure classes below — the closed set a
4
+ * resolver maps to. An untagged failure is a defect, not a domain error.
5
+ */
6
+ export class SubjectNotFoundError extends Data.TaggedError('SubjectNotFoundError') {
7
+ }
8
+ /**
9
+ * A resolver's rule rejected the operation, and `reason` names the cause it
10
+ * recognized.
11
+ *
12
+ * `reason` is the named cause from the service's shared failure taxonomy when
13
+ * a domain failure is recognized; otherwise it is the tag of the rule that
14
+ * rejected the operation.
15
+ */
16
+ export class OperationRejectedError extends Data.TaggedError('OperationRejectedError') {
17
+ }
18
+ /**
19
+ * A resolver's own dependency did not answer; `cause` carries the port's own
20
+ * failure.
21
+ */
22
+ export class OperationsUnavailableError extends Data.TaggedError('OperationsUnavailableError') {
23
+ }
24
+ /**
25
+ * The socket never opened. `port` is the port the server asked for, and
26
+ * `refusal` says in three parts which variable decides that port and how
27
+ * to hand it another one.
28
+ */
29
+ export class ServerCannotListenError extends Data.TaggedError('ServerCannotListenError') {
30
+ }
@@ -0,0 +1,45 @@
1
+ import { type GraphQLSchema } from 'graphql';
2
+ /**
3
+ * A GraphiQL page: a title and a pre-filled document. Your service writes
4
+ * the examples, since only it knows its schema's operations; the machinery
5
+ * supplies the form, a neutral default, and a check the example still fits.
6
+ */
7
+ export interface GraphiqlPage {
8
+ readonly title: string;
9
+ readonly defaultQuery: string;
10
+ }
11
+ /**
12
+ * The page a service gets before it writes examples of its own: one
13
+ * introspection query and a note saying where to write more.
14
+ *
15
+ * @internal
16
+ */
17
+ export declare const DEFAULT_GRAPHIQL_PAGE: GraphiqlPage;
18
+ /**
19
+ * @internal
20
+ */
21
+ export interface GraphiqlExampleProblem {
22
+ readonly message: string;
23
+ }
24
+ /**
25
+ * Checks a GraphiQL page's default query against a schema. An example that
26
+ * no longer matches the schema is worse than none — it teaches the wrong
27
+ * thing. A service's test runs its page through this check on every change.
28
+ */
29
+ export declare const graphiqlExampleProblems: (schema: GraphQLSchema, page: GraphiqlPage) => readonly GraphiqlExampleProblem[];
30
+ /**
31
+ * A minimal schema the default page must stay valid against: it asks only
32
+ * for introspection, nothing more, so it fits any real schema too.
33
+ *
34
+ * @internal
35
+ */
36
+ export declare const MINIMAL_SCHEMA_FOR_DEFAULT_PAGE: GraphQLSchema;
37
+ /**
38
+ * The shape Yoga takes for its editor page.
39
+ *
40
+ * @internal
41
+ */
42
+ export declare const graphiqlOptionsFor: (page: GraphiqlPage) => {
43
+ readonly title: string;
44
+ readonly defaultQuery: string;
45
+ };
@@ -0,0 +1,56 @@
1
+ import { buildSchema, parse, validate } from 'graphql';
2
+ /**
3
+ * The page a service gets before it writes examples of its own: one
4
+ * introspection query and a note saying where to write more.
5
+ *
6
+ * @internal
7
+ */
8
+ export const DEFAULT_GRAPHIQL_PAGE = {
9
+ title: 'Machinery — Internal GraphQL',
10
+ defaultQuery: `# Place your cursor inside an operation and press ▶ to run it.
11
+ # Each field and argument description lives in the schema — see the Docs
12
+ # tab on the right.
13
+ #
14
+ # Your service supplies example operations here. Until it does,
15
+ # introspection shows the schema.
16
+
17
+ query Introspection {
18
+ __schema {
19
+ queryType {
20
+ name
21
+ }
22
+ }
23
+ }
24
+ `,
25
+ };
26
+ /**
27
+ * Checks a GraphiQL page's default query against a schema. An example that
28
+ * no longer matches the schema is worse than none — it teaches the wrong
29
+ * thing. A service's test runs its page through this check on every change.
30
+ */
31
+ export const graphiqlExampleProblems = (schema, page) => {
32
+ try {
33
+ return validate(schema, parse(page.defaultQuery)).map((error) => ({
34
+ message: error.message,
35
+ }));
36
+ }
37
+ catch (cause) {
38
+ return [{ message: cause instanceof Error ? cause.message : String(cause) }];
39
+ }
40
+ };
41
+ /**
42
+ * A minimal schema the default page must stay valid against: it asks only
43
+ * for introspection, nothing more, so it fits any real schema too.
44
+ *
45
+ * @internal
46
+ */
47
+ export const MINIMAL_SCHEMA_FOR_DEFAULT_PAGE = buildSchema('type Query { ping: String }');
48
+ /**
49
+ * The shape Yoga takes for its editor page.
50
+ *
51
+ * @internal
52
+ */
53
+ export const graphiqlOptionsFor = (page) => ({
54
+ title: page.title,
55
+ defaultQuery: page.defaultQuery,
56
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Public entry to the graphql mechanism: one server that answers your
3
+ * operations and the readiness probes beside them. It gives you one Yoga
4
+ * server on Bun that serves a federated Pothos schema and the readiness probes
5
+ * on the same port, with a resolver context that runs your use cases and turns
6
+ * their typed failures into one closed set of `GraphQLError` codes.
7
+ */
8
+ export { makeSubGraphSchemaBuilder } from './builder.js';
9
+ export { asGraphQLError, type GraphQLContext, graphqlContextFrom, type RunOperationsExit, } from './context.js';
10
+ export type { EveryFailureIsClassified } from './failure-classification.js';
11
+ export { type OperationFailure, OperationRejectedError, OperationsUnavailableError, ServerCannotListenError, SubjectNotFoundError, } from './failures.js';
12
+ export { type GraphiqlPage, graphiqlExampleProblems, } from './graphiql.js';
13
+ export { graphqlServerLive } from './layer.js';
14
+ export { makeYogaServer } from './server.js';
15
+ export { ENVIRONMENT, GRAPHQL_ENDPOINT, graphiqlEnabledFromEnvironment, graphqlPortFromEnvironment, serverCannotListen, } from './settings.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Public entry to the graphql mechanism: one server that answers your
3
+ * operations and the readiness probes beside them. It gives you one Yoga
4
+ * server on Bun that serves a federated Pothos schema and the readiness probes
5
+ * on the same port, with a resolver context that runs your use cases and turns
6
+ * their typed failures into one closed set of `GraphQLError` codes.
7
+ */
8
+ export { makeSubGraphSchemaBuilder } from './builder.js';
9
+ export { asGraphQLError, graphqlContextFrom, } from './context.js';
10
+ export { OperationRejectedError, OperationsUnavailableError, ServerCannotListenError, SubjectNotFoundError, } from './failures.js';
11
+ export { graphiqlExampleProblems, } from './graphiql.js';
12
+ export { graphqlServerLive } from './layer.js';
13
+ export { makeYogaServer } from './server.js';
14
+ export { ENVIRONMENT, GRAPHQL_ENDPOINT, graphiqlEnabledFromEnvironment, graphqlPortFromEnvironment, serverCannotListen, } from './settings.js';
@@ -0,0 +1,15 @@
1
+ import { type ConfigError, Layer } from 'effect';
2
+ import type { ServerCannotListenError } from './failures.js';
3
+ import { type GraphQLRequestHandlerOptions } from './request-handler.js';
4
+ /**
5
+ * The one layer this mechanism mounts: the server that answers your
6
+ * operations.
7
+ *
8
+ * The one layer this mechanism mounts: it opens the port, keeps `Bun.serve`
9
+ * alive for the life of the scope, and serves both GraphQL and the readiness
10
+ * probes (`/livez`, `/readyz`, `/healthz`) from one handler, so the probes
11
+ * answer on the SAME port as the schema. A port the runtime cannot open comes
12
+ * back as `ServerCannotListenError`, whose refusal names the variable that
13
+ * decides it.
14
+ */
15
+ export declare const graphqlServerLive: <R>(options: GraphQLRequestHandlerOptions<R>) => Layer.Layer<never, ConfigError.ConfigError | ServerCannotListenError, R>;
@@ -0,0 +1,23 @@
1
+ import { Effect, Layer } from 'effect';
2
+ import { graphqlRequestHandler, } from './request-handler.js';
3
+ import { graphqlPortFromEnvironment, serverCannotListen } from './settings.js';
4
+ /**
5
+ * The one layer this mechanism mounts: the server that answers your
6
+ * operations.
7
+ *
8
+ * The one layer this mechanism mounts: it opens the port, keeps `Bun.serve`
9
+ * alive for the life of the scope, and serves both GraphQL and the readiness
10
+ * probes (`/livez`, `/readyz`, `/healthz`) from one handler, so the probes
11
+ * answer on the SAME port as the schema. A port the runtime cannot open comes
12
+ * back as `ServerCannotListenError`, whose refusal names the variable that
13
+ * decides it.
14
+ */
15
+ export const graphqlServerLive = (options) => Layer.scopedDiscard(Effect.gen(function* () {
16
+ const port = yield* graphqlPortFromEnvironment;
17
+ const fetchHandler = yield* graphqlRequestHandler(options);
18
+ yield* Effect.acquireRelease(Effect.try({
19
+ try: () => Bun.serve({ port, fetch: fetchHandler }),
20
+ catch: (cause) => serverCannotListen(port, cause),
21
+ }), (server) => Effect.promise(() => server.stop(true)));
22
+ yield* Effect.logInfo(`GraphQL (Yoga) and readiness probes are listening on port ${port}`);
23
+ }));
@@ -0,0 +1,26 @@
1
+ import { type NamedHealthCheck } from '@satorio/machinery/http';
2
+ import { type ConfigError, Effect } from 'effect';
3
+ import type { GraphQLSchema } from 'graphql';
4
+ import type { GraphiqlPage } from './graphiql.js';
5
+ /**
6
+ * What a service hands this mechanism to be served: its schema, the
7
+ * readiness checks that answer beside it, and the editor page it wants a
8
+ * reader to open on.
9
+ *
10
+ * @internal
11
+ */
12
+ export interface GraphQLRequestHandlerOptions<R> {
13
+ readonly schema: GraphQLSchema;
14
+ readonly graphiqlPage?: GraphiqlPage;
15
+ readonly healthChecks: Effect.Effect<readonly NamedHealthCheck<R>[], ConfigError.ConfigError, R>;
16
+ }
17
+ /**
18
+ * One handler for one port: the readiness routes answer first, and
19
+ * everything they do not claim goes to GraphQL. It captures the Effect
20
+ * runtime carrying the service's ports, so a resolver runs a use case
21
+ * from it. Whatever opens the socket — `Bun.serve` in production, a
22
+ * plain server in a test — serves this one function.
23
+ *
24
+ * @internal
25
+ */
26
+ export declare const graphqlRequestHandler: <R>(options: GraphQLRequestHandlerOptions<R>) => Effect.Effect<(request: Request) => Promise<Response>, ConfigError.ConfigError, R>;
@@ -0,0 +1,33 @@
1
+ import { healthRoutesFetch, } from '@satorio/machinery/http';
2
+ import { Effect, Runtime } from 'effect';
3
+ import { graphqlContextFrom } from './context.js';
4
+ import { makeYogaServer } from './server.js';
5
+ import { graphiqlEnabledFromEnvironment } from './settings.js';
6
+ /**
7
+ * One handler for one port: the readiness routes answer first, and
8
+ * everything they do not claim goes to GraphQL. It captures the Effect
9
+ * runtime carrying the service's ports, so a resolver runs a use case
10
+ * from it. Whatever opens the socket — `Bun.serve` in production, a
11
+ * plain server in a test — serves this one function.
12
+ *
13
+ * @internal
14
+ */
15
+ export const graphqlRequestHandler = (options) => Effect.gen(function* () {
16
+ const graphiqlEnabled = yield* graphiqlEnabledFromEnvironment;
17
+ const healthChecks = yield* options.healthChecks;
18
+ const runtime = yield* Effect.runtime();
19
+ const runCheck = Runtime.runPromiseExit(runtime);
20
+ const yoga = makeYogaServer({
21
+ schema: options.schema,
22
+ ...(options.graphiqlPage === undefined
23
+ ? {}
24
+ : { graphiqlPage: options.graphiqlPage }),
25
+ context: graphqlContextFrom(runCheck),
26
+ graphiqlEnabled,
27
+ });
28
+ const health = healthRoutesFetch({ runCheck, checks: healthChecks });
29
+ return async (request) => {
30
+ const healthResponse = await health(request);
31
+ return healthResponse ?? (await yoga.fetch(request));
32
+ };
33
+ });
@@ -0,0 +1,19 @@
1
+ import type { GraphQLSchema } from 'graphql';
2
+ import { type YogaServerInstance } from 'graphql-yoga';
3
+ import type { GraphQLContext } from './context.js';
4
+ import { type GraphiqlPage } from './graphiql.js';
5
+ /**
6
+ * @internal
7
+ */
8
+ export interface GraphQLServerOptions<R> {
9
+ readonly schema: GraphQLSchema;
10
+ readonly graphiqlPage?: GraphiqlPage;
11
+ readonly context: GraphQLContext<R>;
12
+ readonly graphiqlEnabled?: boolean;
13
+ }
14
+ /**
15
+ * Builds a Yoga GraphQL server for Bun. The `graphiqlEnabled` flag only
16
+ * turns off the editor page; the endpoint itself keeps answering either
17
+ * way.
18
+ */
19
+ export declare const makeYogaServer: <R>(options: GraphQLServerOptions<R>) => YogaServerInstance<Record<string, never>, GraphQLContext<R>>;
@@ -0,0 +1,16 @@
1
+ import { createYoga } from 'graphql-yoga';
2
+ import { DEFAULT_GRAPHIQL_PAGE, graphiqlOptionsFor, } from './graphiql.js';
3
+ import { GRAPHIQL_ENABLED_BY_DEFAULT, GRAPHQL_ENDPOINT } from './settings.js';
4
+ /**
5
+ * Builds a Yoga GraphQL server for Bun. The `graphiqlEnabled` flag only
6
+ * turns off the editor page; the endpoint itself keeps answering either
7
+ * way.
8
+ */
9
+ export const makeYogaServer = (options) => createYoga({
10
+ schema: options.schema,
11
+ context: () => options.context,
12
+ graphqlEndpoint: GRAPHQL_ENDPOINT,
13
+ graphiql: (options.graphiqlEnabled ?? GRAPHIQL_ENABLED_BY_DEFAULT)
14
+ ? graphiqlOptionsFor(options.graphiqlPage ?? DEFAULT_GRAPHIQL_PAGE)
15
+ : false,
16
+ });
@@ -0,0 +1,55 @@
1
+ import { type EnvironmentEntry, type Refusal } from '@satorio/machinery/core';
2
+ import { Config } from 'effect';
3
+ import { ServerCannotListenError } from './failures.js';
4
+ /**
5
+ * The port the server listens on when nobody names one.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare const DEFAULT_GRAPHQL_PORT = 4000;
10
+ /**
11
+ * GraphiQL is the editor served on the same endpoint: opening `/graphql`
12
+ * in a browser loads the schema docs and examples. It defaults to on
13
+ * because the endpoint is internal; production turns it off with
14
+ * `GRAPHIQL_ENABLED=false`.
15
+ *
16
+ * @internal
17
+ */
18
+ export declare const GRAPHIQL_ENABLED_BY_DEFAULT = true;
19
+ /**
20
+ * The one path the GraphQL endpoint answers on. Readiness probes mount
21
+ * beside it, on the same port.
22
+ */
23
+ export declare const GRAPHQL_ENDPOINT = "/graphql";
24
+ /**
25
+ * The three parts a reader meets when the port is set to something the
26
+ * server cannot listen on. A port left unset takes the default and
27
+ * refuses nothing.
28
+ *
29
+ * @internal
30
+ */
31
+ export declare const portRefusal: Refusal;
32
+ /**
33
+ * Every variable this adapter reads, and the one state each of them
34
+ * stands in. Neither is prefixed: one process serves one schema, so
35
+ * these two names are whole.
36
+ */
37
+ export declare const ENVIRONMENT: readonly EnvironmentEntry[];
38
+ /**
39
+ * The port to listen on. Unset, it falls back to the default; set to
40
+ * anything outside the range a TCP port can take, it refuses in three
41
+ * parts.
42
+ */
43
+ export declare const graphqlPortFromEnvironment: Config.Config<number>;
44
+ /**
45
+ * Whether to serve the editor page. The endpoint itself answers either
46
+ * way; only the page in a browser goes away.
47
+ */
48
+ export declare const graphiqlEnabledFromEnvironment: Config.Config<boolean>;
49
+ /**
50
+ * Turns whatever the runtime threw while opening the socket into the
51
+ * named failure a caller reads. The text names the variable that decides
52
+ * the port and the port it asked for, because the runtime's own message
53
+ * names neither.
54
+ */
55
+ export declare const serverCannotListen: (port: number, cause: unknown) => ServerCannotListenError;
@@ -0,0 +1,82 @@
1
+ import { fallsBackTo, wholeNumberFallingBackTo, } from '@satorio/machinery/core';
2
+ import { Config } from 'effect';
3
+ import { ServerCannotListenError } from './failures.js';
4
+ const PORT = 'GRAPHQL_PORT';
5
+ const GRAPHIQL_ENABLED = 'GRAPHIQL_ENABLED';
6
+ const LOWEST_PORT = 1;
7
+ const HIGHEST_PORT = 65_535;
8
+ /**
9
+ * The port the server listens on when nobody names one.
10
+ *
11
+ * @internal
12
+ */
13
+ export const DEFAULT_GRAPHQL_PORT = 4000;
14
+ /**
15
+ * GraphiQL is the editor served on the same endpoint: opening `/graphql`
16
+ * in a browser loads the schema docs and examples. It defaults to on
17
+ * because the endpoint is internal; production turns it off with
18
+ * `GRAPHIQL_ENABLED=false`.
19
+ *
20
+ * @internal
21
+ */
22
+ export const GRAPHIQL_ENABLED_BY_DEFAULT = true;
23
+ /**
24
+ * The one path the GraphQL endpoint answers on. Readiness probes mount
25
+ * beside it, on the same port.
26
+ */
27
+ export const GRAPHQL_ENDPOINT = '/graphql';
28
+ /**
29
+ * The three parts a reader meets when the port is set to something the
30
+ * server cannot listen on. A port left unset takes the default and
31
+ * refuses nothing.
32
+ *
33
+ * @internal
34
+ */
35
+ export const portRefusal = {
36
+ what: `${PORT} is set to something this server cannot listen on.`,
37
+ why: `A TCP port is a whole number from ${LOWEST_PORT} to ${HIGHEST_PORT}, and nothing else can be opened.`,
38
+ whatToDo: `Set ${PORT} to a whole number in that range, or leave it unset and take the ${DEFAULT_GRAPHQL_PORT} default.`,
39
+ };
40
+ /**
41
+ * Every variable this adapter reads, and the one state each of them
42
+ * stands in. Neither is prefixed: one process serves one schema, so
43
+ * these two names are whole.
44
+ */
45
+ export const ENVIRONMENT = [
46
+ {
47
+ name: PORT,
48
+ what: 'The port the GraphQL endpoint and the readiness probes listen on.',
49
+ state: fallsBackTo(String(DEFAULT_GRAPHQL_PORT)),
50
+ },
51
+ {
52
+ name: GRAPHIQL_ENABLED,
53
+ what: 'Whether the GraphiQL editor page is served on the same endpoint.',
54
+ state: fallsBackTo(String(GRAPHIQL_ENABLED_BY_DEFAULT)),
55
+ },
56
+ ];
57
+ /**
58
+ * The port to listen on. Unset, it falls back to the default; set to
59
+ * anything outside the range a TCP port can take, it refuses in three
60
+ * parts.
61
+ */
62
+ export const graphqlPortFromEnvironment = wholeNumberFallingBackTo(PORT, LOWEST_PORT, HIGHEST_PORT, DEFAULT_GRAPHQL_PORT, portRefusal);
63
+ /**
64
+ * Whether to serve the editor page. The endpoint itself answers either
65
+ * way; only the page in a browser goes away.
66
+ */
67
+ export const graphiqlEnabledFromEnvironment = Config.boolean(GRAPHIQL_ENABLED).pipe(Config.withDefault(GRAPHIQL_ENABLED_BY_DEFAULT));
68
+ /**
69
+ * Turns whatever the runtime threw while opening the socket into the
70
+ * named failure a caller reads. The text names the variable that decides
71
+ * the port and the port it asked for, because the runtime's own message
72
+ * names neither.
73
+ */
74
+ export const serverCannotListen = (port, cause) => new ServerCannotListenError({
75
+ port,
76
+ cause,
77
+ refusal: {
78
+ what: `This service could not open port ${port}.`,
79
+ why: `${PORT} decides which port the GraphQL endpoint and the readiness probes listen on, and it takes ${DEFAULT_GRAPHQL_PORT} when nobody names one. A port another process already holds refuses the socket.`,
80
+ whatToDo: `Free port ${port}, or set ${PORT} to a port nothing else holds, then start the service again.`,
81
+ },
82
+ });