@voyant-travel/db 0.108.0

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 (336) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +60 -0
  3. package/dist/aggregate-snapshots.d.ts +66 -0
  4. package/dist/aggregate-snapshots.d.ts.map +1 -0
  5. package/dist/aggregate-snapshots.js +110 -0
  6. package/dist/aggregate-snapshots.js.map +1 -0
  7. package/dist/columns/collection.d.ts +37 -0
  8. package/dist/columns/collection.d.ts.map +1 -0
  9. package/dist/columns/collection.js +44 -0
  10. package/dist/columns/collection.js.map +1 -0
  11. package/dist/columns/cruise.d.ts +26 -0
  12. package/dist/columns/cruise.d.ts.map +1 -0
  13. package/dist/columns/cruise.js +31 -0
  14. package/dist/columns/cruise.js.map +1 -0
  15. package/dist/columns/departure-sub-tables.d.ts +179 -0
  16. package/dist/columns/departure-sub-tables.d.ts.map +1 -0
  17. package/dist/columns/departure-sub-tables.js +214 -0
  18. package/dist/columns/departure-sub-tables.js.map +1 -0
  19. package/dist/columns/departure.d.ts +20 -0
  20. package/dist/columns/departure.d.ts.map +1 -0
  21. package/dist/columns/departure.js +23 -0
  22. package/dist/columns/departure.js.map +1 -0
  23. package/dist/columns/destinations.d.ts +21 -0
  24. package/dist/columns/destinations.d.ts.map +1 -0
  25. package/dist/columns/destinations.js +24 -0
  26. package/dist/columns/destinations.js.map +1 -0
  27. package/dist/columns/index.d.ts +31 -0
  28. package/dist/columns/index.d.ts.map +1 -0
  29. package/dist/columns/index.js +57 -0
  30. package/dist/columns/index.js.map +1 -0
  31. package/dist/columns/itinerary-sub-tables.d.ts +177 -0
  32. package/dist/columns/itinerary-sub-tables.d.ts.map +1 -0
  33. package/dist/columns/itinerary-sub-tables.js +122 -0
  34. package/dist/columns/itinerary-sub-tables.js.map +1 -0
  35. package/dist/columns/itinerary.d.ts +17 -0
  36. package/dist/columns/itinerary.d.ts.map +1 -0
  37. package/dist/columns/itinerary.js +20 -0
  38. package/dist/columns/itinerary.js.map +1 -0
  39. package/dist/columns/lodging.d.ts +143 -0
  40. package/dist/columns/lodging.d.ts.map +1 -0
  41. package/dist/columns/lodging.js +164 -0
  42. package/dist/columns/lodging.js.map +1 -0
  43. package/dist/columns/offers.d.ts +31 -0
  44. package/dist/columns/offers.d.ts.map +1 -0
  45. package/dist/columns/offers.js +43 -0
  46. package/dist/columns/offers.js.map +1 -0
  47. package/dist/columns/pricing.d.ts +60 -0
  48. package/dist/columns/pricing.d.ts.map +1 -0
  49. package/dist/columns/pricing.js +71 -0
  50. package/dist/columns/pricing.js.map +1 -0
  51. package/dist/columns/product-accommodation.d.ts +99 -0
  52. package/dist/columns/product-accommodation.d.ts.map +1 -0
  53. package/dist/columns/product-accommodation.js +65 -0
  54. package/dist/columns/product-accommodation.js.map +1 -0
  55. package/dist/columns/product-addons.d.ts +18 -0
  56. package/dist/columns/product-addons.d.ts.map +1 -0
  57. package/dist/columns/product-addons.js +21 -0
  58. package/dist/columns/product-addons.js.map +1 -0
  59. package/dist/columns/product-availability-states.d.ts +65 -0
  60. package/dist/columns/product-availability-states.d.ts.map +1 -0
  61. package/dist/columns/product-availability-states.js +81 -0
  62. package/dist/columns/product-availability-states.js.map +1 -0
  63. package/dist/columns/product-availability.d.ts +21 -0
  64. package/dist/columns/product-availability.d.ts.map +1 -0
  65. package/dist/columns/product-availability.js +24 -0
  66. package/dist/columns/product-availability.js.map +1 -0
  67. package/dist/columns/product-booking-rules.d.ts +45 -0
  68. package/dist/columns/product-booking-rules.d.ts.map +1 -0
  69. package/dist/columns/product-booking-rules.js +55 -0
  70. package/dist/columns/product-booking-rules.js.map +1 -0
  71. package/dist/columns/product-category-assignments.d.ts +17 -0
  72. package/dist/columns/product-category-assignments.d.ts.map +1 -0
  73. package/dist/columns/product-category-assignments.js +20 -0
  74. package/dist/columns/product-category-assignments.js.map +1 -0
  75. package/dist/columns/product-extensions.d.ts +24 -0
  76. package/dist/columns/product-extensions.d.ts.map +1 -0
  77. package/dist/columns/product-extensions.js +27 -0
  78. package/dist/columns/product-extensions.js.map +1 -0
  79. package/dist/columns/product-media.d.ts +19 -0
  80. package/dist/columns/product-media.d.ts.map +1 -0
  81. package/dist/columns/product-media.js +22 -0
  82. package/dist/columns/product-media.js.map +1 -0
  83. package/dist/columns/product-overrides.d.ts +19 -0
  84. package/dist/columns/product-overrides.d.ts.map +1 -0
  85. package/dist/columns/product-overrides.js +22 -0
  86. package/dist/columns/product-overrides.js.map +1 -0
  87. package/dist/columns/product-preferences.d.ts +51 -0
  88. package/dist/columns/product-preferences.d.ts.map +1 -0
  89. package/dist/columns/product-preferences.js +59 -0
  90. package/dist/columns/product-preferences.js.map +1 -0
  91. package/dist/columns/product-publish-settings.d.ts +18 -0
  92. package/dist/columns/product-publish-settings.d.ts.map +1 -0
  93. package/dist/columns/product-publish-settings.js +21 -0
  94. package/dist/columns/product-publish-settings.js.map +1 -0
  95. package/dist/columns/product-rate-plans.d.ts +28 -0
  96. package/dist/columns/product-rate-plans.d.ts.map +1 -0
  97. package/dist/columns/product-rate-plans.js +33 -0
  98. package/dist/columns/product-rate-plans.js.map +1 -0
  99. package/dist/columns/product-translations.d.ts +24 -0
  100. package/dist/columns/product-translations.d.ts.map +1 -0
  101. package/dist/columns/product-translations.js +27 -0
  102. package/dist/columns/product-translations.js.map +1 -0
  103. package/dist/columns/product-versions.d.ts +19 -0
  104. package/dist/columns/product-versions.d.ts.map +1 -0
  105. package/dist/columns/product-versions.js +22 -0
  106. package/dist/columns/product-versions.js.map +1 -0
  107. package/dist/columns/product-visibility.d.ts +16 -0
  108. package/dist/columns/product-visibility.d.ts.map +1 -0
  109. package/dist/columns/product-visibility.js +19 -0
  110. package/dist/columns/product-visibility.js.map +1 -0
  111. package/dist/columns/product.d.ts +56 -0
  112. package/dist/columns/product.d.ts.map +1 -0
  113. package/dist/columns/product.js +44 -0
  114. package/dist/columns/product.js.map +1 -0
  115. package/dist/columns/room.d.ts +117 -0
  116. package/dist/columns/room.d.ts.map +1 -0
  117. package/dist/columns/room.js +86 -0
  118. package/dist/columns/room.js.map +1 -0
  119. package/dist/columns/ship.d.ts +22 -0
  120. package/dist/columns/ship.d.ts.map +1 -0
  121. package/dist/columns/ship.js +25 -0
  122. package/dist/columns/ship.js.map +1 -0
  123. package/dist/columns/tags.d.ts +33 -0
  124. package/dist/columns/tags.d.ts.map +1 -0
  125. package/dist/columns/tags.js +38 -0
  126. package/dist/columns/tags.js.map +1 -0
  127. package/dist/columns/transport.d.ts +53 -0
  128. package/dist/columns/transport.d.ts.map +1 -0
  129. package/dist/columns/transport.js +62 -0
  130. package/dist/columns/transport.js.map +1 -0
  131. package/dist/connection-config.d.ts +101 -0
  132. package/dist/connection-config.d.ts.map +1 -0
  133. package/dist/connection-config.js +106 -0
  134. package/dist/connection-config.js.map +1 -0
  135. package/dist/crud.d.ts +87 -0
  136. package/dist/crud.d.ts.map +1 -0
  137. package/dist/crud.js +190 -0
  138. package/dist/crud.js.map +1 -0
  139. package/dist/helpers.d.ts +33 -0
  140. package/dist/helpers.d.ts.map +1 -0
  141. package/dist/helpers.js +49 -0
  142. package/dist/helpers.js.map +1 -0
  143. package/dist/index.d.ts +109 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +155 -0
  146. package/dist/index.js.map +1 -0
  147. package/dist/lib/index.d.ts +3 -0
  148. package/dist/lib/index.d.ts.map +1 -0
  149. package/dist/lib/index.js +5 -0
  150. package/dist/lib/index.js.map +1 -0
  151. package/dist/lib/typeid-column.d.ts +75 -0
  152. package/dist/lib/typeid-column.d.ts.map +1 -0
  153. package/dist/lib/typeid-column.js +92 -0
  154. package/dist/lib/typeid-column.js.map +1 -0
  155. package/dist/lib/typeid-core.d.ts +36 -0
  156. package/dist/lib/typeid-core.d.ts.map +1 -0
  157. package/dist/lib/typeid-core.js +67 -0
  158. package/dist/lib/typeid-core.js.map +1 -0
  159. package/dist/lib/typeid-prefixes.d.ts +342 -0
  160. package/dist/lib/typeid-prefixes.d.ts.map +1 -0
  161. package/dist/lib/typeid-prefixes.js +379 -0
  162. package/dist/lib/typeid-prefixes.js.map +1 -0
  163. package/dist/lib/typeid-schemas.d.ts +206 -0
  164. package/dist/lib/typeid-schemas.d.ts.map +1 -0
  165. package/dist/lib/typeid-schemas.js +207 -0
  166. package/dist/lib/typeid-schemas.js.map +1 -0
  167. package/dist/lib/typeid-zod.d.ts +16 -0
  168. package/dist/lib/typeid-zod.d.ts.map +1 -0
  169. package/dist/lib/typeid-zod.js +29 -0
  170. package/dist/lib/typeid-zod.js.map +1 -0
  171. package/dist/lib/typeid.d.ts +2 -0
  172. package/dist/lib/typeid.d.ts.map +1 -0
  173. package/dist/lib/typeid.js +6 -0
  174. package/dist/lib/typeid.js.map +1 -0
  175. package/dist/lifecycle.d.ts +24 -0
  176. package/dist/lifecycle.d.ts.map +1 -0
  177. package/dist/lifecycle.js +30 -0
  178. package/dist/lifecycle.js.map +1 -0
  179. package/dist/links.d.ts +22 -0
  180. package/dist/links.d.ts.map +1 -0
  181. package/dist/links.js +281 -0
  182. package/dist/links.js.map +1 -0
  183. package/dist/operators.d.ts +9 -0
  184. package/dist/operators.d.ts.map +1 -0
  185. package/dist/operators.js +9 -0
  186. package/dist/operators.js.map +1 -0
  187. package/dist/outbox.d.ts +87 -0
  188. package/dist/outbox.d.ts.map +1 -0
  189. package/dist/outbox.js +245 -0
  190. package/dist/outbox.js.map +1 -0
  191. package/dist/primitives/catalog-schemas.d.ts +101 -0
  192. package/dist/primitives/catalog-schemas.d.ts.map +1 -0
  193. package/dist/primitives/catalog-schemas.js +69 -0
  194. package/dist/primitives/catalog-schemas.js.map +1 -0
  195. package/dist/primitives/catalog.d.ts +47 -0
  196. package/dist/primitives/catalog.d.ts.map +1 -0
  197. package/dist/primitives/catalog.js +94 -0
  198. package/dist/primitives/catalog.js.map +1 -0
  199. package/dist/primitives/index.d.ts +4 -0
  200. package/dist/primitives/index.d.ts.map +1 -0
  201. package/dist/primitives/index.js +4 -0
  202. package/dist/primitives/index.js.map +1 -0
  203. package/dist/primitives/offers.d.ts +224 -0
  204. package/dist/primitives/offers.d.ts.map +1 -0
  205. package/dist/primitives/offers.js +132 -0
  206. package/dist/primitives/offers.js.map +1 -0
  207. package/dist/queries/index.d.ts +18 -0
  208. package/dist/queries/index.d.ts.map +1 -0
  209. package/dist/queries/index.js +30 -0
  210. package/dist/queries/index.js.map +1 -0
  211. package/dist/runtime/index.d.ts +4 -0
  212. package/dist/runtime/index.d.ts.map +1 -0
  213. package/dist/runtime/index.js +5 -0
  214. package/dist/runtime/index.js.map +1 -0
  215. package/dist/runtime/locks.d.ts +5 -0
  216. package/dist/runtime/locks.d.ts.map +1 -0
  217. package/dist/runtime/locks.js +36 -0
  218. package/dist/runtime/locks.js.map +1 -0
  219. package/dist/schema/00_ensure_schemas.d.ts +5 -0
  220. package/dist/schema/00_ensure_schemas.d.ts.map +1 -0
  221. package/dist/schema/00_ensure_schemas.js +6 -0
  222. package/dist/schema/00_ensure_schemas.js.map +1 -0
  223. package/dist/schema/aggregate-snapshots.d.ts +97 -0
  224. package/dist/schema/aggregate-snapshots.d.ts.map +1 -0
  225. package/dist/schema/aggregate-snapshots.js +27 -0
  226. package/dist/schema/aggregate-snapshots.js.map +1 -0
  227. package/dist/schema/iam/apikey.d.ts +396 -0
  228. package/dist/schema/iam/apikey.d.ts.map +1 -0
  229. package/dist/schema/iam/apikey.js +41 -0
  230. package/dist/schema/iam/apikey.js.map +1 -0
  231. package/dist/schema/iam/auth.d.ts +1026 -0
  232. package/dist/schema/iam/auth.d.ts.map +1 -0
  233. package/dist/schema/iam/auth.js +138 -0
  234. package/dist/schema/iam/auth.js.map +1 -0
  235. package/dist/schema/iam/cloud_auth.d.ts +446 -0
  236. package/dist/schema/iam/cloud_auth.d.ts.map +1 -0
  237. package/dist/schema/iam/cloud_auth.js +46 -0
  238. package/dist/schema/iam/cloud_auth.js.map +1 -0
  239. package/dist/schema/iam/index.d.ts +8 -0
  240. package/dist/schema/iam/index.d.ts.map +1 -0
  241. package/dist/schema/iam/index.js +8 -0
  242. package/dist/schema/iam/index.js.map +1 -0
  243. package/dist/schema/iam/invitations.d.ts +173 -0
  244. package/dist/schema/iam/invitations.d.ts.map +1 -0
  245. package/dist/schema/iam/invitations.js +27 -0
  246. package/dist/schema/iam/invitations.js.map +1 -0
  247. package/dist/schema/iam/kms.d.ts +53 -0
  248. package/dist/schema/iam/kms.d.ts.map +1 -0
  249. package/dist/schema/iam/kms.js +40 -0
  250. package/dist/schema/iam/kms.js.map +1 -0
  251. package/dist/schema/iam/roles.d.ts +12 -0
  252. package/dist/schema/iam/roles.d.ts.map +1 -0
  253. package/dist/schema/iam/roles.js +12 -0
  254. package/dist/schema/iam/roles.js.map +1 -0
  255. package/dist/schema/iam/user_profiles.d.ts +442 -0
  256. package/dist/schema/iam/user_profiles.d.ts.map +1 -0
  257. package/dist/schema/iam/user_profiles.js +125 -0
  258. package/dist/schema/iam/user_profiles.js.map +1 -0
  259. package/dist/schema/index.d.ts +5 -0
  260. package/dist/schema/index.d.ts.map +1 -0
  261. package/dist/schema/index.js +5 -0
  262. package/dist/schema/index.js.map +1 -0
  263. package/dist/schema/infra/domains.d.ts +609 -0
  264. package/dist/schema/infra/domains.d.ts.map +1 -0
  265. package/dist/schema/infra/domains.js +108 -0
  266. package/dist/schema/infra/domains.js.map +1 -0
  267. package/dist/schema/infra/email_domain_records.d.ts +255 -0
  268. package/dist/schema/infra/email_domain_records.d.ts.map +1 -0
  269. package/dist/schema/infra/email_domain_records.js +65 -0
  270. package/dist/schema/infra/email_domain_records.js.map +1 -0
  271. package/dist/schema/infra/event_outbox.d.ts +232 -0
  272. package/dist/schema/infra/event_outbox.d.ts.map +1 -0
  273. package/dist/schema/infra/event_outbox.js +59 -0
  274. package/dist/schema/infra/event_outbox.js.map +1 -0
  275. package/dist/schema/infra/idempotency_keys.d.ts +186 -0
  276. package/dist/schema/infra/idempotency_keys.d.ts.map +1 -0
  277. package/dist/schema/infra/idempotency_keys.js +40 -0
  278. package/dist/schema/infra/idempotency_keys.js.map +1 -0
  279. package/dist/schema/infra/index.d.ts +9 -0
  280. package/dist/schema/infra/index.d.ts.map +1 -0
  281. package/dist/schema/infra/index.js +10 -0
  282. package/dist/schema/infra/index.js.map +1 -0
  283. package/dist/schema/infra/public_document_delivery_grants.d.ts +356 -0
  284. package/dist/schema/infra/public_document_delivery_grants.d.ts.map +1 -0
  285. package/dist/schema/infra/public_document_delivery_grants.js +36 -0
  286. package/dist/schema/infra/public_document_delivery_grants.js.map +1 -0
  287. package/dist/schema/infra/rate_limit_buckets.d.ts +138 -0
  288. package/dist/schema/infra/rate_limit_buckets.d.ts.map +1 -0
  289. package/dist/schema/infra/rate_limit_buckets.js +52 -0
  290. package/dist/schema/infra/rate_limit_buckets.js.map +1 -0
  291. package/dist/schema/infra/webhook_deliveries.d.ts +572 -0
  292. package/dist/schema/infra/webhook_deliveries.d.ts.map +1 -0
  293. package/dist/schema/infra/webhook_deliveries.js +136 -0
  294. package/dist/schema/infra/webhook_deliveries.js.map +1 -0
  295. package/dist/schema/infra/webhook_subscriptions.d.ts +284 -0
  296. package/dist/schema/infra/webhook_subscriptions.d.ts.map +1 -0
  297. package/dist/schema/infra/webhook_subscriptions.js +64 -0
  298. package/dist/schema/infra/webhook_subscriptions.js.map +1 -0
  299. package/dist/schema/infra/write_intents.d.ts +185 -0
  300. package/dist/schema/infra/write_intents.d.ts.map +1 -0
  301. package/dist/schema/infra/write_intents.js +50 -0
  302. package/dist/schema/infra/write_intents.js.map +1 -0
  303. package/dist/schema/voyant/bookings.d.ts +2 -0
  304. package/dist/schema/voyant/bookings.d.ts.map +1 -0
  305. package/dist/schema/voyant/bookings.js +2 -0
  306. package/dist/schema/voyant/bookings.js.map +1 -0
  307. package/dist/schema/voyant/finance.d.ts +2 -0
  308. package/dist/schema/voyant/finance.d.ts.map +1 -0
  309. package/dist/schema/voyant/finance.js +2 -0
  310. package/dist/schema/voyant/finance.js.map +1 -0
  311. package/dist/test-utils.d.ts +17 -0
  312. package/dist/test-utils.d.ts.map +1 -0
  313. package/dist/test-utils.js +56 -0
  314. package/dist/test-utils.js.map +1 -0
  315. package/dist/transaction-capability.d.ts +11 -0
  316. package/dist/transaction-capability.d.ts.map +1 -0
  317. package/dist/transaction-capability.js +17 -0
  318. package/dist/transaction-capability.js.map +1 -0
  319. package/dist/transaction.d.ts +31 -0
  320. package/dist/transaction.d.ts.map +1 -0
  321. package/dist/transaction.js +72 -0
  322. package/dist/transaction.js.map +1 -0
  323. package/dist/tsconfig.tsbuildinfo +1 -0
  324. package/dist/types.d.ts +10 -0
  325. package/dist/types.d.ts.map +1 -0
  326. package/dist/types.js +2 -0
  327. package/dist/types.js.map +1 -0
  328. package/dist/utils.d.ts +2 -0
  329. package/dist/utils.d.ts.map +1 -0
  330. package/dist/utils.js +19 -0
  331. package/dist/utils.js.map +1 -0
  332. package/dist/write-intents.d.ts +51 -0
  333. package/dist/write-intents.d.ts.map +1 -0
  334. package/dist/write-intents.js +95 -0
  335. package/dist/write-intents.js.map +1 -0
  336. package/package.json +306 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Async write intents (RFC voyant#1687 Phase 3.2 — the queued write
3
+ * pipeline's result mailbox).
4
+ *
5
+ * An intent is "a write the caller asked for but didn't wait for": the
6
+ * route validates the payload, stores it here, durably emits a
7
+ * `<kind>.requested` event (transactional outbox), and answers
8
+ * **202 + a status URL**. The outbox delivers the event to the intent's
9
+ * handler — with the outbox's at-least-once retries, backoff, and
10
+ * dead-lettering — and the handler writes the outcome back onto the
11
+ * row. Under a payday spike, callers get instant 202s and the work
12
+ * drains at the outbox's controlled pace instead of thundering-herding
13
+ * the booking transaction.
14
+ *
15
+ * Dedup: `idempotency_key` is unique — a retried POST with the same key
16
+ * returns the SAME intent rather than enqueueing twice.
17
+ *
18
+ * Status semantics: `pending` until a handler settles it. Handlers
19
+ * distinguish FINAL business outcomes (capacity conflict → `failed`
20
+ * with a result payload, never retried) from infra errors (thrown →
21
+ * the outbox retries). A stale sweep fails intents whose event
22
+ * dead-lettered.
23
+ */
24
+ export declare const writeIntentsTable: Omit<import("drizzle-orm/pg-core").PgTableWithColumns<{
25
+ name: "write_intents";
26
+ schema: undefined;
27
+ columns: {
28
+ id: import("drizzle-orm/pg-core").PgColumn<{
29
+ name: string;
30
+ tableName: "write_intents";
31
+ dataType: "string";
32
+ columnType: "PgText";
33
+ data: string;
34
+ driverParam: string;
35
+ notNull: true;
36
+ hasDefault: true;
37
+ isPrimaryKey: true;
38
+ isAutoincrement: false;
39
+ hasRuntimeDefault: true;
40
+ enumValues: [string, ...string[]];
41
+ baseColumn: never;
42
+ identity: undefined;
43
+ generated: undefined;
44
+ }, {}, {}>;
45
+ kind: import("drizzle-orm/pg-core").PgColumn<{
46
+ name: "kind";
47
+ tableName: "write_intents";
48
+ dataType: "string";
49
+ columnType: "PgText";
50
+ data: string;
51
+ driverParam: string;
52
+ notNull: true;
53
+ hasDefault: false;
54
+ isPrimaryKey: false;
55
+ isAutoincrement: false;
56
+ hasRuntimeDefault: false;
57
+ enumValues: [string, ...string[]];
58
+ baseColumn: never;
59
+ identity: undefined;
60
+ generated: undefined;
61
+ }, {}, {}>;
62
+ payload: import("drizzle-orm/pg-core").PgColumn<{
63
+ name: "payload";
64
+ tableName: "write_intents";
65
+ dataType: "json";
66
+ columnType: "PgJsonb";
67
+ data: unknown;
68
+ driverParam: unknown;
69
+ notNull: true;
70
+ hasDefault: false;
71
+ isPrimaryKey: false;
72
+ isAutoincrement: false;
73
+ hasRuntimeDefault: false;
74
+ enumValues: undefined;
75
+ baseColumn: never;
76
+ identity: undefined;
77
+ generated: undefined;
78
+ }, {}, {}>;
79
+ idempotencyKey: import("drizzle-orm/pg-core").PgColumn<{
80
+ name: "idempotency_key";
81
+ tableName: "write_intents";
82
+ dataType: "string";
83
+ columnType: "PgText";
84
+ data: string;
85
+ driverParam: string;
86
+ notNull: true;
87
+ hasDefault: false;
88
+ isPrimaryKey: false;
89
+ isAutoincrement: false;
90
+ hasRuntimeDefault: false;
91
+ enumValues: [string, ...string[]];
92
+ baseColumn: never;
93
+ identity: undefined;
94
+ generated: undefined;
95
+ }, {}, {}>;
96
+ status: import("drizzle-orm/pg-core").PgColumn<{
97
+ name: "status";
98
+ tableName: "write_intents";
99
+ dataType: "string";
100
+ columnType: "PgText";
101
+ data: "failed" | "pending" | "succeeded";
102
+ driverParam: string;
103
+ notNull: true;
104
+ hasDefault: true;
105
+ isPrimaryKey: false;
106
+ isAutoincrement: false;
107
+ hasRuntimeDefault: false;
108
+ enumValues: ["pending", "succeeded", "failed"];
109
+ baseColumn: never;
110
+ identity: undefined;
111
+ generated: undefined;
112
+ }, {}, {}>;
113
+ result: import("drizzle-orm/pg-core").PgColumn<{
114
+ name: "result";
115
+ tableName: "write_intents";
116
+ dataType: "json";
117
+ columnType: "PgJsonb";
118
+ data: unknown;
119
+ driverParam: unknown;
120
+ notNull: false;
121
+ hasDefault: false;
122
+ isPrimaryKey: false;
123
+ isAutoincrement: false;
124
+ hasRuntimeDefault: false;
125
+ enumValues: undefined;
126
+ baseColumn: never;
127
+ identity: undefined;
128
+ generated: undefined;
129
+ }, {}, {}>;
130
+ error: import("drizzle-orm/pg-core").PgColumn<{
131
+ name: "error";
132
+ tableName: "write_intents";
133
+ dataType: "string";
134
+ columnType: "PgText";
135
+ data: string;
136
+ driverParam: string;
137
+ notNull: false;
138
+ hasDefault: false;
139
+ isPrimaryKey: false;
140
+ isAutoincrement: false;
141
+ hasRuntimeDefault: false;
142
+ enumValues: [string, ...string[]];
143
+ baseColumn: never;
144
+ identity: undefined;
145
+ generated: undefined;
146
+ }, {}, {}>;
147
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
148
+ name: "created_at";
149
+ tableName: "write_intents";
150
+ dataType: "date";
151
+ columnType: "PgTimestamp";
152
+ data: Date;
153
+ driverParam: string;
154
+ notNull: true;
155
+ hasDefault: true;
156
+ isPrimaryKey: false;
157
+ isAutoincrement: false;
158
+ hasRuntimeDefault: false;
159
+ enumValues: undefined;
160
+ baseColumn: never;
161
+ identity: undefined;
162
+ generated: undefined;
163
+ }, {}, {}>;
164
+ completedAt: import("drizzle-orm/pg-core").PgColumn<{
165
+ name: "completed_at";
166
+ tableName: "write_intents";
167
+ dataType: "date";
168
+ columnType: "PgTimestamp";
169
+ data: Date;
170
+ driverParam: string;
171
+ notNull: false;
172
+ hasDefault: false;
173
+ isPrimaryKey: false;
174
+ isAutoincrement: false;
175
+ hasRuntimeDefault: false;
176
+ enumValues: undefined;
177
+ baseColumn: never;
178
+ identity: undefined;
179
+ generated: undefined;
180
+ }, {}, {}>;
181
+ };
182
+ dialect: "pg";
183
+ }>, "enableRLS">;
184
+ export type WriteIntentRow = typeof writeIntentsTable.$inferSelect;
185
+ //# sourceMappingURL=write_intents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write_intents.d.ts","sourceRoot":"","sources":["../../../src/schema/infra/write_intents.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA0BjB,CAAA;AAEb,MAAM,MAAM,cAAc,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { index, jsonb, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
3
+ import { typeId } from "../../lib/index.js";
4
+ /**
5
+ * Async write intents (RFC voyant#1687 Phase 3.2 — the queued write
6
+ * pipeline's result mailbox).
7
+ *
8
+ * An intent is "a write the caller asked for but didn't wait for": the
9
+ * route validates the payload, stores it here, durably emits a
10
+ * `<kind>.requested` event (transactional outbox), and answers
11
+ * **202 + a status URL**. The outbox delivers the event to the intent's
12
+ * handler — with the outbox's at-least-once retries, backoff, and
13
+ * dead-lettering — and the handler writes the outcome back onto the
14
+ * row. Under a payday spike, callers get instant 202s and the work
15
+ * drains at the outbox's controlled pace instead of thundering-herding
16
+ * the booking transaction.
17
+ *
18
+ * Dedup: `idempotency_key` is unique — a retried POST with the same key
19
+ * returns the SAME intent rather than enqueueing twice.
20
+ *
21
+ * Status semantics: `pending` until a handler settles it. Handlers
22
+ * distinguish FINAL business outcomes (capacity conflict → `failed`
23
+ * with a result payload, never retried) from infra errors (thrown →
24
+ * the outbox retries). A stale sweep fails intents whose event
25
+ * dead-lettered.
26
+ */
27
+ export const writeIntentsTable = pgTable("write_intents", {
28
+ id: typeId("write_intents"),
29
+ /** Handler routing key, e.g. "storefront.booking.bootstrap". */
30
+ kind: text("kind").notNull(),
31
+ /** The validated request payload the handler will execute. */
32
+ payload: jsonb("payload").notNull(),
33
+ /** Client-supplied (Idempotency-Key) or generated. Unique. */
34
+ idempotencyKey: text("idempotency_key").notNull(),
35
+ status: text("status", { enum: ["pending", "succeeded", "failed"] })
36
+ .notNull()
37
+ .default("pending"),
38
+ /** Handler outcome payload (success result OR final-failure detail). */
39
+ result: jsonb("result"),
40
+ /** Infra/dead-letter error detail for failed intents. */
41
+ error: text("error"),
42
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
43
+ completedAt: timestamp("completed_at", { withTimezone: true }),
44
+ }, (table) => [
45
+ uniqueIndex("write_intents_idempotency_key_uniq").on(table.idempotencyKey),
46
+ // Stale-sweep working set; partial keeps it tiny.
47
+ // agent-quality: raw-sql reviewed -- owner: db; dynamic SQL interpolation uses Drizzle parameter binding or vetted SQL identifiers.
48
+ index("write_intents_pending_idx").on(table.createdAt).where(sql `${table.status} = 'pending'`),
49
+ ]).enableRLS();
50
+ //# sourceMappingURL=write_intents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write_intents.js","sourceRoot":"","sources":["../../../src/schema/infra/write_intents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEzF,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAA;AAE3C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CACtC,eAAe,EACf;IACE,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC;IAC3B,gEAAgE;IAChE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,8DAA8D;IAC9D,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACnC,8DAA8D;IAC9D,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC;SACjE,OAAO,EAAE;SACT,OAAO,CAAC,SAAS,CAAC;IACrB,wEAAwE;IACxE,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;IACvB,yDAAyD;IACzD,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC;IACpB,SAAS,EAAE,SAAS,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,UAAU,EAAE;IACjF,WAAW,EAAE,SAAS,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;CAC/D,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,WAAW,CAAC,oCAAoC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;IAC1E,kDAAkD;IAClD,oIAAoI;IACpI,KAAK,CAAC,2BAA2B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAA,GAAG,KAAK,CAAC,MAAM,cAAc,CAAC;CAC/F,CACF,CAAC,SAAS,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bookings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bookings.d.ts","sourceRoot":"","sources":["../../../src/schema/voyant/bookings.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bookings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bookings.js","sourceRoot":"","sources":["../../../src/schema/voyant/bookings.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=finance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finance.d.ts","sourceRoot":"","sources":["../../../src/schema/voyant/finance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=finance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finance.js","sourceRoot":"","sources":["../../../src/schema/voyant/finance.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ /**
3
+ * Creates a database client connected to the test database.
4
+ * Requires the test Postgres instance from `docker-compose.test.yml`.
5
+ *
6
+ * Always uses the Node.js adapter (postgres.js) since tests run in Node.
7
+ */
8
+ export declare function createTestDb(): PostgresJsDatabase;
9
+ /**
10
+ * Closes the shared test database client for the current process.
11
+ */
12
+ export declare function closeTestDb(): Promise<void>;
13
+ /**
14
+ * Truncates all non-system tables in the test database.
15
+ */
16
+ export declare function cleanupTestDb(db: PostgresJsDatabase): Promise<void>;
17
+ //# sourceMappingURL=test-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AA4BjE;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,kBAAkB,CAcjD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAKjD;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzE"}
@@ -0,0 +1,56 @@
1
+ import { sql } from "drizzle-orm";
2
+ import { createDbClient } from "./index.js";
3
+ const TEST_DB_PORT = process.env.TEST_DATABASE_PORT ?? "5436";
4
+ const TEST_DB_NAME = "voyant_test";
5
+ const TEST_DB_USER = "test";
6
+ const TEST_DB_PASSWORD = "test";
7
+ function buildDefaultTestDbUrl(port) {
8
+ const url = new URL("postgres://localhost");
9
+ url.port = port;
10
+ url.pathname = `/${TEST_DB_NAME}`;
11
+ url.username = TEST_DB_USER;
12
+ url.password = TEST_DB_PASSWORD;
13
+ return url.toString();
14
+ }
15
+ const TEST_DB_URL = process.env.TEST_DATABASE_URL ?? buildDefaultTestDbUrl(TEST_DB_PORT);
16
+ let testDbSingleton = null;
17
+ /**
18
+ * Creates a database client connected to the test database.
19
+ * Requires the test Postgres instance from `docker-compose.test.yml`.
20
+ *
21
+ * Always uses the Node.js adapter (postgres.js) since tests run in Node.
22
+ */
23
+ export function createTestDb() {
24
+ if (!testDbSingleton) {
25
+ testDbSingleton = createDbClient(TEST_DB_URL, {
26
+ adapter: "node",
27
+ nodeMaxConnections: 1,
28
+ // Production timeout defaults don't apply to test infrastructure:
29
+ // cleanupTestDb's TRUNCATE over the full ~350-table schema can
30
+ // exceed the 10s statement_timeout on a cold Postgres, killing
31
+ // every integration suite's setup.
32
+ timeouts: { statementMs: false, queryMs: false, connectMs: false },
33
+ });
34
+ }
35
+ return testDbSingleton;
36
+ }
37
+ /**
38
+ * Closes the shared test database client for the current process.
39
+ */
40
+ export async function closeTestDb() {
41
+ const db = testDbSingleton;
42
+ testDbSingleton = null;
43
+ await db?.$client?.end?.({ timeout: 0 });
44
+ }
45
+ /**
46
+ * Truncates all non-system tables in the test database.
47
+ */
48
+ export async function cleanupTestDb(db) {
49
+ const result = await db.execute(sql `SELECT tablename FROM pg_tables WHERE schemaname = 'public'`);
50
+ const tables = result;
51
+ if (tables.length > 0) {
52
+ const names = tables.map((r) => `"${r.tablename}"`).join(", ");
53
+ await db.execute(sql.raw(`TRUNCATE ${names} CASCADE`));
54
+ }
55
+ }
56
+ //# sourceMappingURL=test-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE3C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAA;AAC7D,MAAM,YAAY,GAAG,aAAa,CAAA;AAClC,MAAM,YAAY,GAAG,MAAM,CAAA;AAC3B,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAE/B,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAC3C,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,GAAG,CAAC,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAA;IACjC,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAA;IAC3B,GAAG,CAAC,QAAQ,GAAG,gBAAgB,CAAA;IAC/B,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAA;AACvB,CAAC;AAED,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,qBAAqB,CAAC,YAAY,CAAC,CAAA;AAQxF,IAAI,eAAe,GAAwC,IAAI,CAAA;AAE/D;;;;;GAKG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,eAAe,GAAG,cAAc,CAAC,WAAW,EAAE;YAC5C,OAAO,EAAE,MAAM;YACf,kBAAkB,EAAE,CAAC;YACrB,kEAAkE;YAClE,+DAA+D;YAC/D,+DAA+D;YAC/D,mCAAmC;YACnC,QAAQ,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE;SACnE,CAAiC,CAAA;IACpC,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,EAAE,GAAG,eAAe,CAAA;IAC1B,eAAe,GAAG,IAAI,CAAA;IAEtB,MAAM,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAAsB;IACxD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAC7B,GAAG,CAAA,6DAA6D,CACjE,CAAA;IAED,MAAM,MAAM,GAAG,MAAiC,CAAA;IAChD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9D,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,UAAU,CAAC,CAAC,CAAA;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare const VOYANT_DB_SUPPORTS_TRANSACTIONS: unique symbol;
2
+ export declare const VOYANT_DB_DISPOSE: unique symbol;
3
+ export type DbTransactionCapability = {
4
+ [VOYANT_DB_SUPPORTS_TRANSACTIONS]?: boolean;
5
+ };
6
+ export type DbDisposeCapability = {
7
+ [VOYANT_DB_DISPOSE]?: () => Promise<void>;
8
+ };
9
+ export declare function dbSupportsTransactions(db: unknown): boolean | undefined;
10
+ export declare function dbClientDispose(db: unknown): (() => Promise<void>) | undefined;
11
+ //# sourceMappingURL=transaction-capability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-capability.d.ts","sourceRoot":"","sources":["../src/transaction-capability.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,eAA+C,CAAA;AAC3F,eAAO,MAAM,iBAAiB,eAAkC,CAAA;AAEhE,MAAM,MAAM,uBAAuB,GAAG;IACpC,CAAC,+BAA+B,CAAC,CAAC,EAAE,OAAO,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1C,CAAA;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAOvE;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAO9E"}
@@ -0,0 +1,17 @@
1
+ export const VOYANT_DB_SUPPORTS_TRANSACTIONS = Symbol.for("voyant.db.supportsTransactions");
2
+ export const VOYANT_DB_DISPOSE = Symbol.for("voyant.db.dispose");
3
+ export function dbSupportsTransactions(db) {
4
+ if (!db || (typeof db !== "object" && typeof db !== "function")) {
5
+ return undefined;
6
+ }
7
+ const capability = db[VOYANT_DB_SUPPORTS_TRANSACTIONS];
8
+ return typeof capability === "boolean" ? capability : undefined;
9
+ }
10
+ export function dbClientDispose(db) {
11
+ if (!db || (typeof db !== "object" && typeof db !== "function")) {
12
+ return undefined;
13
+ }
14
+ const dispose = db[VOYANT_DB_DISPOSE];
15
+ return typeof dispose === "function" ? dispose : undefined;
16
+ }
17
+ //# sourceMappingURL=transaction-capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-capability.js","sourceRoot":"","sources":["../src/transaction-capability.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;AAUhE,MAAM,UAAU,sBAAsB,CAAC,EAAW;IAChD,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,UAAU,GAAI,EAA8B,CAAC,+BAA+B,CAAC,CAAA;IACnF,OAAO,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;AACjE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,EAAW;IACzC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,EAAE,KAAK,UAAU,CAAC,EAAE,CAAC;QAChE,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,OAAO,GAAI,EAA0B,CAAC,iBAAiB,CAAC,CAAA;IAC9D,OAAO,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5D,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Run `callback` inside a database transaction when the driver supports one,
3
+ * or invoke it directly against the same `db` handle when it doesn't.
4
+ *
5
+ * Designed for Voyant services that share code paths between drivers with
6
+ * different transaction semantics:
7
+ *
8
+ * - `postgres-js` (node) and `neon-serverless` (WebSocket): real transactions.
9
+ * The driver's `transaction(...)` method is used.
10
+ * - `neon-http` (edge): the HTTP driver tagged with
11
+ * `VOYANT_DB_SUPPORTS_TRANSACTIONS = false` by `createDbClient`. The
12
+ * callback runs directly against `db`. Writes execute as independent
13
+ * statements — atomicity is lost on this driver. Callers that need true
14
+ * atomicity must select a transaction-capable adapter at startup.
15
+ *
16
+ * Nested calls are detected via a `WeakSet`: when invoked with a `tx` handle
17
+ * that the helper already opened, the callback runs in-place against that
18
+ * same handle (no second `BEGIN`).
19
+ *
20
+ * As a defense-in-depth, if a driver's `transaction()` throws with
21
+ * "No transactions support …" *before* the callback executes (i.e. the
22
+ * capability tag is missing on an HTTP-like driver), the helper retries by
23
+ * invoking the callback directly. Errors raised *after* the callback starts
24
+ * are not retried — they propagate.
25
+ */
26
+ export declare function withOptionalTransaction<TDb, T>(db: TDb, callback: (tx: TDb) => Promise<T>): Promise<T>;
27
+ /** @internal — exposed for tests so they can assert WeakSet behavior */
28
+ export declare const __test__: {
29
+ activeTransactionDbs: WeakSet<object>;
30
+ };
31
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,CAAC,EAClD,EAAE,EAAE,GAAG,EACP,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAChC,OAAO,CAAC,CAAC,CAAC,CAqCZ;AAED,wEAAwE;AACxE,eAAO,MAAM,QAAQ;;CAEpB,CAAA"}
@@ -0,0 +1,72 @@
1
+ import { dbSupportsTransactions } from "./transaction-capability.js";
2
+ const activeTransactionDbs = new WeakSet();
3
+ function isUnsupportedTransactionError(error) {
4
+ return error instanceof Error && /No transactions support/i.test(error.message);
5
+ }
6
+ /**
7
+ * Run `callback` inside a database transaction when the driver supports one,
8
+ * or invoke it directly against the same `db` handle when it doesn't.
9
+ *
10
+ * Designed for Voyant services that share code paths between drivers with
11
+ * different transaction semantics:
12
+ *
13
+ * - `postgres-js` (node) and `neon-serverless` (WebSocket): real transactions.
14
+ * The driver's `transaction(...)` method is used.
15
+ * - `neon-http` (edge): the HTTP driver tagged with
16
+ * `VOYANT_DB_SUPPORTS_TRANSACTIONS = false` by `createDbClient`. The
17
+ * callback runs directly against `db`. Writes execute as independent
18
+ * statements — atomicity is lost on this driver. Callers that need true
19
+ * atomicity must select a transaction-capable adapter at startup.
20
+ *
21
+ * Nested calls are detected via a `WeakSet`: when invoked with a `tx` handle
22
+ * that the helper already opened, the callback runs in-place against that
23
+ * same handle (no second `BEGIN`).
24
+ *
25
+ * As a defense-in-depth, if a driver's `transaction()` throws with
26
+ * "No transactions support …" *before* the callback executes (i.e. the
27
+ * capability tag is missing on an HTTP-like driver), the helper retries by
28
+ * invoking the callback directly. Errors raised *after* the callback starts
29
+ * are not retried — they propagate.
30
+ */
31
+ export async function withOptionalTransaction(db, callback) {
32
+ if (db && typeof db === "object" && activeTransactionDbs.has(db)) {
33
+ return callback(db);
34
+ }
35
+ if (dbSupportsTransactions(db) === false) {
36
+ return callback(db);
37
+ }
38
+ const maybeTransactional = db;
39
+ if (typeof maybeTransactional.transaction !== "function") {
40
+ return callback(db);
41
+ }
42
+ let callbackStarted = false;
43
+ try {
44
+ return await maybeTransactional.transaction(async (tx) => {
45
+ callbackStarted = true;
46
+ const txKey = tx;
47
+ const trackable = txKey && typeof txKey === "object";
48
+ if (trackable) {
49
+ activeTransactionDbs.add(txKey);
50
+ }
51
+ try {
52
+ return await callback(tx);
53
+ }
54
+ finally {
55
+ if (trackable) {
56
+ activeTransactionDbs.delete(txKey);
57
+ }
58
+ }
59
+ });
60
+ }
61
+ catch (error) {
62
+ if (!callbackStarted && isUnsupportedTransactionError(error)) {
63
+ return callback(db);
64
+ }
65
+ throw error;
66
+ }
67
+ }
68
+ /** @internal — exposed for tests so they can assert WeakSet behavior */
69
+ export const __test__ = {
70
+ activeTransactionDbs,
71
+ };
72
+ //# sourceMappingURL=transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAEpE,MAAM,oBAAoB,GAAG,IAAI,OAAO,EAAU,CAAA;AAElD,SAAS,6BAA6B,CAAC,KAAc;IACnD,OAAO,KAAK,YAAY,KAAK,IAAI,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;AACjF,CAAC;AAMD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,EAAO,EACP,QAAiC;IAEjC,IAAI,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,oBAAoB,CAAC,GAAG,CAAC,EAAY,CAAC,EAAE,CAAC;QAC3E,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,IAAI,sBAAsB,CAAC,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;QACzC,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,MAAM,kBAAkB,GAAG,EAA+B,CAAA;IAC1D,IAAI,OAAO,kBAAkB,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QACzD,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;IACrB,CAAC;IAED,IAAI,eAAe,GAAG,KAAK,CAAA;IAC3B,IAAI,CAAC;QACH,OAAO,MAAM,kBAAkB,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACvD,eAAe,GAAG,IAAI,CAAA;YACtB,MAAM,KAAK,GAAG,EAAa,CAAA;YAC3B,MAAM,SAAS,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAA;YACpD,IAAI,SAAS,EAAE,CAAC;gBACd,oBAAoB,CAAC,GAAG,CAAC,KAAe,CAAC,CAAA;YAC3C,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAA;YAC3B,CAAC;oBAAS,CAAC;gBACT,IAAI,SAAS,EAAE,CAAC;oBACd,oBAAoB,CAAC,MAAM,CAAC,KAAe,CAAC,CAAA;gBAC9C,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,eAAe,IAAI,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAA;QACrB,CAAC;QACD,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,oBAAoB;CACrB,CAAA"}