@crowdsource.you/core 1.2.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 (339) hide show
  1. package/README.md +571 -0
  2. package/dist/cases.d.ts +66 -0
  3. package/dist/cases.d.ts.map +1 -0
  4. package/dist/cases.js +79 -0
  5. package/dist/cases.js.map +1 -0
  6. package/dist/client.d.ts +90 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +125 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/communityNotes.d.ts +49 -0
  11. package/dist/communityNotes.d.ts.map +1 -0
  12. package/dist/communityNotes.js +104 -0
  13. package/dist/communityNotes.js.map +1 -0
  14. package/dist/credential.d.ts +58 -0
  15. package/dist/credential.d.ts.map +1 -0
  16. package/dist/credential.js +71 -0
  17. package/dist/credential.js.map +1 -0
  18. package/dist/defaults.d.ts +61 -0
  19. package/dist/defaults.d.ts.map +1 -0
  20. package/dist/defaults.js +82 -0
  21. package/dist/defaults.js.map +1 -0
  22. package/dist/digest.d.ts +44 -0
  23. package/dist/digest.d.ts.map +1 -0
  24. package/dist/digest.js +79 -0
  25. package/dist/digest.js.map +1 -0
  26. package/dist/envelope.d.ts +143 -0
  27. package/dist/envelope.d.ts.map +1 -0
  28. package/dist/envelope.js +258 -0
  29. package/dist/envelope.js.map +1 -0
  30. package/dist/errors.d.ts +90 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +151 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/esm/cases.js +74 -0
  35. package/dist/esm/cases.js.map +1 -0
  36. package/dist/esm/client.js +121 -0
  37. package/dist/esm/client.js.map +1 -0
  38. package/dist/esm/communityNotes.js +100 -0
  39. package/dist/esm/communityNotes.js.map +1 -0
  40. package/dist/esm/credential.js +67 -0
  41. package/dist/esm/credential.js.map +1 -0
  42. package/dist/esm/defaults.js +77 -0
  43. package/dist/esm/defaults.js.map +1 -0
  44. package/dist/esm/digest.js +74 -0
  45. package/dist/esm/digest.js.map +1 -0
  46. package/dist/esm/envelope.js +252 -0
  47. package/dist/esm/envelope.js.map +1 -0
  48. package/dist/esm/errors.js +140 -0
  49. package/dist/esm/errors.js.map +1 -0
  50. package/dist/esm/express/index.js +29 -0
  51. package/dist/esm/express/index.js.map +1 -0
  52. package/dist/esm/express/middleware.js +293 -0
  53. package/dist/esm/express/middleware.js.map +1 -0
  54. package/dist/esm/express/store.js +69 -0
  55. package/dist/esm/express/store.js.map +1 -0
  56. package/dist/esm/express/verify.js +133 -0
  57. package/dist/esm/express/verify.js.map +1 -0
  58. package/dist/esm/index.js +57 -0
  59. package/dist/esm/index.js.map +1 -0
  60. package/dist/esm/outbox/client.js +43 -0
  61. package/dist/esm/outbox/client.js.map +1 -0
  62. package/dist/esm/outbox/decision.js +153 -0
  63. package/dist/esm/outbox/decision.js.map +1 -0
  64. package/dist/esm/outbox/delivery.js +129 -0
  65. package/dist/esm/outbox/delivery.js.map +1 -0
  66. package/dist/esm/outbox/enforcement/executor.js +219 -0
  67. package/dist/esm/outbox/enforcement/executor.js.map +1 -0
  68. package/dist/esm/outbox/enforcement/planner.js +326 -0
  69. package/dist/esm/outbox/enforcement/planner.js.map +1 -0
  70. package/dist/esm/outbox/evidence.js +173 -0
  71. package/dist/esm/outbox/evidence.js.map +1 -0
  72. package/dist/esm/outbox/inbound.js +87 -0
  73. package/dist/esm/outbox/inbound.js.map +1 -0
  74. package/dist/esm/outbox/index.js +71 -0
  75. package/dist/esm/outbox/index.js.map +1 -0
  76. package/dist/esm/outbox/intake.js +140 -0
  77. package/dist/esm/outbox/intake.js.map +1 -0
  78. package/dist/esm/outbox/integration.js +116 -0
  79. package/dist/esm/outbox/integration.js.map +1 -0
  80. package/dist/esm/outbox/outbox/dispatcher.js +114 -0
  81. package/dist/esm/outbox/outbox/dispatcher.js.map +1 -0
  82. package/dist/esm/outbox/outbox/service.js +271 -0
  83. package/dist/esm/outbox/outbox/service.js.map +1 -0
  84. package/dist/esm/outbox/postgres/index.js +41 -0
  85. package/dist/esm/outbox/postgres/index.js.map +1 -0
  86. package/dist/esm/outbox/postgres/registries.js +155 -0
  87. package/dist/esm/outbox/postgres/registries.js.map +1 -0
  88. package/dist/esm/outbox/postgres/reportColumns.js +191 -0
  89. package/dist/esm/outbox/postgres/reportColumns.js.map +1 -0
  90. package/dist/esm/outbox/postgres/store/enforcement.js +158 -0
  91. package/dist/esm/outbox/postgres/store/enforcement.js.map +1 -0
  92. package/dist/esm/outbox/postgres/store/events.js +101 -0
  93. package/dist/esm/outbox/postgres/store/events.js.map +1 -0
  94. package/dist/esm/outbox/postgres/store/index.js +59 -0
  95. package/dist/esm/outbox/postgres/store/index.js.map +1 -0
  96. package/dist/esm/outbox/postgres/store/outbox.js +207 -0
  97. package/dist/esm/outbox/postgres/store/outbox.js.map +1 -0
  98. package/dist/esm/outbox/postgres/store/reports.js +231 -0
  99. package/dist/esm/outbox/postgres/store/reports.js.map +1 -0
  100. package/dist/esm/outbox/postgres/store/transaction.js +29 -0
  101. package/dist/esm/outbox/postgres/store/transaction.js.map +1 -0
  102. package/dist/esm/outbox/postgres/tables.js +270 -0
  103. package/dist/esm/outbox/postgres/tables.js.map +1 -0
  104. package/dist/esm/outbox/reconciliation.js +157 -0
  105. package/dist/esm/outbox/reconciliation.js.map +1 -0
  106. package/dist/esm/outbox/reportStatus.js +22 -0
  107. package/dist/esm/outbox/reportStatus.js.map +1 -0
  108. package/dist/esm/outbox/retention.js +33 -0
  109. package/dist/esm/outbox/retention.js.map +1 -0
  110. package/dist/esm/outbox/store/types.js +30 -0
  111. package/dist/esm/outbox/store/types.js.map +1 -0
  112. package/dist/esm/outbox/types.js +23 -0
  113. package/dist/esm/outbox/types.js.map +1 -0
  114. package/dist/esm/outbox/webhook.js +145 -0
  115. package/dist/esm/outbox/webhook.js.map +1 -0
  116. package/dist/esm/package.json +1 -0
  117. package/dist/esm/reports.js +74 -0
  118. package/dist/esm/reports.js.map +1 -0
  119. package/dist/esm/testing/fixtures.js +132 -0
  120. package/dist/esm/testing/fixtures.js.map +1 -0
  121. package/dist/esm/testing/index.js +33 -0
  122. package/dist/esm/testing/index.js.map +1 -0
  123. package/dist/esm/testing/sandbox.js +337 -0
  124. package/dist/esm/testing/sandbox.js.map +1 -0
  125. package/dist/esm/testing/webhook-simulator.js +93 -0
  126. package/dist/esm/testing/webhook-simulator.js.map +1 -0
  127. package/dist/esm/transport.js +177 -0
  128. package/dist/esm/transport.js.map +1 -0
  129. package/dist/esm/webhookEndpoints.js +139 -0
  130. package/dist/esm/webhookEndpoints.js.map +1 -0
  131. package/dist/express/index.d.ts +32 -0
  132. package/dist/express/index.d.ts.map +1 -0
  133. package/dist/express/index.js +40 -0
  134. package/dist/express/index.js.map +1 -0
  135. package/dist/express/middleware.d.ts +97 -0
  136. package/dist/express/middleware.d.ts.map +1 -0
  137. package/dist/express/middleware.js +298 -0
  138. package/dist/express/middleware.js.map +1 -0
  139. package/dist/express/store.d.ts +45 -0
  140. package/dist/express/store.d.ts.map +1 -0
  141. package/dist/express/store.js +72 -0
  142. package/dist/express/store.js.map +1 -0
  143. package/dist/express/verify.d.ts +86 -0
  144. package/dist/express/verify.d.ts.map +1 -0
  145. package/dist/express/verify.js +138 -0
  146. package/dist/express/verify.js.map +1 -0
  147. package/dist/index.d.ts +67 -0
  148. package/dist/index.d.ts.map +1 -0
  149. package/dist/index.js +89 -0
  150. package/dist/index.js.map +1 -0
  151. package/dist/outbox/client.d.ts +35 -0
  152. package/dist/outbox/client.d.ts.map +1 -0
  153. package/dist/outbox/client.js +46 -0
  154. package/dist/outbox/client.js.map +1 -0
  155. package/dist/outbox/decision.d.ts +36 -0
  156. package/dist/outbox/decision.d.ts.map +1 -0
  157. package/dist/outbox/decision.js +159 -0
  158. package/dist/outbox/decision.js.map +1 -0
  159. package/dist/outbox/delivery.d.ts +50 -0
  160. package/dist/outbox/delivery.d.ts.map +1 -0
  161. package/dist/outbox/delivery.js +135 -0
  162. package/dist/outbox/delivery.js.map +1 -0
  163. package/dist/outbox/enforcement/executor.d.ts +26 -0
  164. package/dist/outbox/enforcement/executor.d.ts.map +1 -0
  165. package/dist/outbox/enforcement/executor.js +222 -0
  166. package/dist/outbox/enforcement/executor.js.map +1 -0
  167. package/dist/outbox/enforcement/planner.d.ts +50 -0
  168. package/dist/outbox/enforcement/planner.d.ts.map +1 -0
  169. package/dist/outbox/enforcement/planner.js +333 -0
  170. package/dist/outbox/enforcement/planner.js.map +1 -0
  171. package/dist/outbox/evidence.d.ts +114 -0
  172. package/dist/outbox/evidence.d.ts.map +1 -0
  173. package/dist/outbox/evidence.js +181 -0
  174. package/dist/outbox/evidence.js.map +1 -0
  175. package/dist/outbox/inbound.d.ts +78 -0
  176. package/dist/outbox/inbound.d.ts.map +1 -0
  177. package/dist/outbox/inbound.js +91 -0
  178. package/dist/outbox/inbound.js.map +1 -0
  179. package/dist/outbox/index.d.ts +79 -0
  180. package/dist/outbox/index.d.ts.map +1 -0
  181. package/dist/outbox/index.js +98 -0
  182. package/dist/outbox/index.js.map +1 -0
  183. package/dist/outbox/intake.d.ts +62 -0
  184. package/dist/outbox/intake.d.ts.map +1 -0
  185. package/dist/outbox/intake.js +145 -0
  186. package/dist/outbox/intake.js.map +1 -0
  187. package/dist/outbox/integration.d.ts +62 -0
  188. package/dist/outbox/integration.d.ts.map +1 -0
  189. package/dist/outbox/integration.js +119 -0
  190. package/dist/outbox/integration.js.map +1 -0
  191. package/dist/outbox/outbox/dispatcher.d.ts +26 -0
  192. package/dist/outbox/outbox/dispatcher.d.ts.map +1 -0
  193. package/dist/outbox/outbox/dispatcher.js +119 -0
  194. package/dist/outbox/outbox/dispatcher.js.map +1 -0
  195. package/dist/outbox/outbox/service.d.ts +124 -0
  196. package/dist/outbox/outbox/service.d.ts.map +1 -0
  197. package/dist/outbox/outbox/service.js +279 -0
  198. package/dist/outbox/outbox/service.js.map +1 -0
  199. package/dist/outbox/postgres/index.d.ts +44 -0
  200. package/dist/outbox/postgres/index.d.ts.map +1 -0
  201. package/dist/outbox/postgres/index.js +51 -0
  202. package/dist/outbox/postgres/index.js.map +1 -0
  203. package/dist/outbox/postgres/registries.d.ts +69 -0
  204. package/dist/outbox/postgres/registries.d.ts.map +1 -0
  205. package/dist/outbox/postgres/registries.js +159 -0
  206. package/dist/outbox/postgres/registries.js.map +1 -0
  207. package/dist/outbox/postgres/reportColumns.d.ts +154 -0
  208. package/dist/outbox/postgres/reportColumns.d.ts.map +1 -0
  209. package/dist/outbox/postgres/reportColumns.js +195 -0
  210. package/dist/outbox/postgres/reportColumns.js.map +1 -0
  211. package/dist/outbox/postgres/store/enforcement.d.ts +33 -0
  212. package/dist/outbox/postgres/store/enforcement.d.ts.map +1 -0
  213. package/dist/outbox/postgres/store/enforcement.js +161 -0
  214. package/dist/outbox/postgres/store/enforcement.js.map +1 -0
  215. package/dist/outbox/postgres/store/events.d.ts +46 -0
  216. package/dist/outbox/postgres/store/events.d.ts.map +1 -0
  217. package/dist/outbox/postgres/store/events.js +104 -0
  218. package/dist/outbox/postgres/store/events.js.map +1 -0
  219. package/dist/outbox/postgres/store/index.d.ts +27 -0
  220. package/dist/outbox/postgres/store/index.d.ts.map +1 -0
  221. package/dist/outbox/postgres/store/index.js +62 -0
  222. package/dist/outbox/postgres/store/index.js.map +1 -0
  223. package/dist/outbox/postgres/store/outbox.d.ts +8 -0
  224. package/dist/outbox/postgres/store/outbox.d.ts.map +1 -0
  225. package/dist/outbox/postgres/store/outbox.js +210 -0
  226. package/dist/outbox/postgres/store/outbox.js.map +1 -0
  227. package/dist/outbox/postgres/store/reports.d.ts +69 -0
  228. package/dist/outbox/postgres/store/reports.d.ts.map +1 -0
  229. package/dist/outbox/postgres/store/reports.js +234 -0
  230. package/dist/outbox/postgres/store/reports.js.map +1 -0
  231. package/dist/outbox/postgres/store/transaction.d.ts +49 -0
  232. package/dist/outbox/postgres/store/transaction.d.ts.map +1 -0
  233. package/dist/outbox/postgres/store/transaction.js +32 -0
  234. package/dist/outbox/postgres/store/transaction.js.map +1 -0
  235. package/dist/outbox/postgres/tables.d.ts +737 -0
  236. package/dist/outbox/postgres/tables.d.ts.map +1 -0
  237. package/dist/outbox/postgres/tables.js +273 -0
  238. package/dist/outbox/postgres/tables.js.map +1 -0
  239. package/dist/outbox/reconciliation.d.ts +49 -0
  240. package/dist/outbox/reconciliation.d.ts.map +1 -0
  241. package/dist/outbox/reconciliation.js +162 -0
  242. package/dist/outbox/reconciliation.js.map +1 -0
  243. package/dist/outbox/reportStatus.d.ts +12 -0
  244. package/dist/outbox/reportStatus.d.ts.map +1 -0
  245. package/dist/outbox/reportStatus.js +25 -0
  246. package/dist/outbox/reportStatus.js.map +1 -0
  247. package/dist/outbox/retention.d.ts +33 -0
  248. package/dist/outbox/retention.d.ts.map +1 -0
  249. package/dist/outbox/retention.js +36 -0
  250. package/dist/outbox/retention.js.map +1 -0
  251. package/dist/outbox/store/types.d.ts +466 -0
  252. package/dist/outbox/store/types.d.ts.map +1 -0
  253. package/dist/outbox/store/types.js +31 -0
  254. package/dist/outbox/store/types.js.map +1 -0
  255. package/dist/outbox/types.d.ts +660 -0
  256. package/dist/outbox/types.d.ts.map +1 -0
  257. package/dist/outbox/types.js +24 -0
  258. package/dist/outbox/types.js.map +1 -0
  259. package/dist/outbox/webhook.d.ts +15 -0
  260. package/dist/outbox/webhook.d.ts.map +1 -0
  261. package/dist/outbox/webhook.js +148 -0
  262. package/dist/outbox/webhook.js.map +1 -0
  263. package/dist/reports.d.ts +73 -0
  264. package/dist/reports.d.ts.map +1 -0
  265. package/dist/reports.js +78 -0
  266. package/dist/reports.js.map +1 -0
  267. package/dist/testing/fixtures.d.ts +62 -0
  268. package/dist/testing/fixtures.d.ts.map +1 -0
  269. package/dist/testing/fixtures.js +137 -0
  270. package/dist/testing/fixtures.js.map +1 -0
  271. package/dist/testing/index.d.ts +36 -0
  272. package/dist/testing/index.d.ts.map +1 -0
  273. package/dist/testing/index.js +43 -0
  274. package/dist/testing/index.js.map +1 -0
  275. package/dist/testing/sandbox.d.ts +109 -0
  276. package/dist/testing/sandbox.d.ts.map +1 -0
  277. package/dist/testing/sandbox.js +342 -0
  278. package/dist/testing/sandbox.js.map +1 -0
  279. package/dist/testing/webhook-simulator.d.ts +78 -0
  280. package/dist/testing/webhook-simulator.d.ts.map +1 -0
  281. package/dist/testing/webhook-simulator.js +98 -0
  282. package/dist/testing/webhook-simulator.js.map +1 -0
  283. package/dist/transport.d.ts +59 -0
  284. package/dist/transport.d.ts.map +1 -0
  285. package/dist/transport.js +181 -0
  286. package/dist/transport.js.map +1 -0
  287. package/dist/webhookEndpoints.d.ts +147 -0
  288. package/dist/webhookEndpoints.d.ts.map +1 -0
  289. package/dist/webhookEndpoints.js +143 -0
  290. package/dist/webhookEndpoints.js.map +1 -0
  291. package/package.json +127 -0
  292. package/src/cases.ts +119 -0
  293. package/src/client.ts +202 -0
  294. package/src/communityNotes.ts +194 -0
  295. package/src/credential.ts +100 -0
  296. package/src/defaults.ts +87 -0
  297. package/src/digest.ts +91 -0
  298. package/src/envelope.ts +432 -0
  299. package/src/errors.ts +165 -0
  300. package/src/express/index.ts +43 -0
  301. package/src/express/middleware.ts +387 -0
  302. package/src/express/store.ts +85 -0
  303. package/src/express/verify.ts +166 -0
  304. package/src/index.ts +107 -0
  305. package/src/outbox/client.ts +75 -0
  306. package/src/outbox/decision.ts +209 -0
  307. package/src/outbox/delivery.ts +163 -0
  308. package/src/outbox/enforcement/executor.ts +288 -0
  309. package/src/outbox/enforcement/planner.ts +377 -0
  310. package/src/outbox/evidence.ts +231 -0
  311. package/src/outbox/inbound.ts +140 -0
  312. package/src/outbox/index.ts +160 -0
  313. package/src/outbox/intake.ts +175 -0
  314. package/src/outbox/integration.ts +205 -0
  315. package/src/outbox/outbox/dispatcher.ts +131 -0
  316. package/src/outbox/outbox/service.ts +444 -0
  317. package/src/outbox/postgres/index.ts +59 -0
  318. package/src/outbox/postgres/registries.ts +177 -0
  319. package/src/outbox/postgres/reportColumns.ts +281 -0
  320. package/src/outbox/postgres/store/enforcement.ts +186 -0
  321. package/src/outbox/postgres/store/events.ts +112 -0
  322. package/src/outbox/postgres/store/index.ts +72 -0
  323. package/src/outbox/postgres/store/outbox.ts +273 -0
  324. package/src/outbox/postgres/store/reports.ts +349 -0
  325. package/src/outbox/postgres/store/transaction.ts +64 -0
  326. package/src/outbox/postgres/tables.ts +339 -0
  327. package/src/outbox/reconciliation.ts +199 -0
  328. package/src/outbox/reportStatus.ts +24 -0
  329. package/src/outbox/retention.ts +34 -0
  330. package/src/outbox/store/types.ts +528 -0
  331. package/src/outbox/types.ts +753 -0
  332. package/src/outbox/webhook.ts +165 -0
  333. package/src/reports.ts +138 -0
  334. package/src/testing/fixtures.ts +183 -0
  335. package/src/testing/index.ts +57 -0
  336. package/src/testing/sandbox.ts +469 -0
  337. package/src/testing/webhook-simulator.ts +166 -0
  338. package/src/transport.ts +250 -0
  339. package/src/webhookEndpoints.ts +256 -0
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.postgresReportStore = postgresReportStore;
4
+ const drizzle_orm_1 = require("drizzle-orm");
5
+ const OPTIONAL_REPORT_FIELDS = [
6
+ 'details',
7
+ 'localStatusReason',
8
+ 'crowdSourceReportId',
9
+ 'crowdSourceCaseId',
10
+ 'crowdSourceMerged',
11
+ 'contentSnapshotHash',
12
+ 'submittedAt',
13
+ 'lastDeliveryError',
14
+ 'decisionId',
15
+ 'decisionRevision',
16
+ 'decisionOutcome',
17
+ 'decisionStatus',
18
+ 'decidedAt',
19
+ 'enforcedAction',
20
+ 'enforcedAt',
21
+ ];
22
+ /** Drop the package's own optional fields when the column is NULL. */
23
+ function absentWhereNull(row) {
24
+ const normalised = { ...row };
25
+ for (const field of OPTIONAL_REPORT_FIELDS) {
26
+ if (normalised[field] === null)
27
+ delete normalised[field];
28
+ }
29
+ return normalised;
30
+ }
31
+ /**
32
+ * The row, as the port declares it.
33
+ *
34
+ * An unchecked declaration, not a conversion — the same escape the Mongoose store
35
+ * takes with `.lean<TReport>()`, and for the same reason: a driver cannot know an
36
+ * adopter's row type, and `ModerationReportTable` deliberately erases column types
37
+ * so that any adopter's table is accepted.
38
+ *
39
+ * What bounds it is that both halves are checked elsewhere. Column PRESENCE is a
40
+ * compile error, gated by `scripts/test-report-table-type.mjs`. Column VALUES are
41
+ * asserted by round-trips against a real database in
42
+ * `postgresReportStore.test.ts`. What remains unchecked is a column declared with
43
+ * the wrong TYPE, which the migration and the schema test cover instead.
44
+ */
45
+ function asReport(row) {
46
+ return absentWhereNull(row);
47
+ }
48
+ function postgresReportStore(input) {
49
+ const { db } = input;
50
+ const reports = input.reportTable;
51
+ /**
52
+ * `count(*)::int`, and the cast is load-bearing.
53
+ *
54
+ * `count(*)` is `bigint`, which postgres.js hands back as a STRING to avoid
55
+ * losing precision — so `sql<number>` without the cast is an assertion that
56
+ * quietly lies, and the caller's `number` is `'3'`. The `::int` makes the
57
+ * database do the conversion.
58
+ */
59
+ const total = (0, drizzle_orm_1.sql) `count(*)::int`;
60
+ return {
61
+ async findDuplicate({ reporter, reportedId, reportedType }, tx) {
62
+ const rows = await tx
63
+ .select()
64
+ .from(reports)
65
+ .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(reports.reporter, reporter), (0, drizzle_orm_1.eq)(reports.reportedId, reportedId), (0, drizzle_orm_1.eq)(reports.reportedType, reportedType)))
66
+ .limit(1);
67
+ const [row] = rows;
68
+ return row === undefined ? null : asReport(row);
69
+ },
70
+ async insert(report, tx) {
71
+ const rows = await tx
72
+ .insert(reports)
73
+ .values({
74
+ /**
75
+ * The application's own columns FIRST, so a field this package owns can
76
+ * never be overwritten by one it knows nothing about. A report whose
77
+ * `localStatus` came from `extra` would be queued with nothing to
78
+ * deliver it, or received with a delivery event that tries anyway.
79
+ *
80
+ * A key that is not a column raises here — Postgres has no silent
81
+ * discard. Mongoose strict mode drops an undeclared path with no throw
82
+ * and no warning, which is why the Mongo half needs a standing test
83
+ * that every DTO field resolves to a schema path.
84
+ */
85
+ ...report.extra,
86
+ reportedType: report.reportedType,
87
+ reportedId: report.reportedId,
88
+ reporter: report.reporter,
89
+ categories: [...report.categories],
90
+ ...(report.details === undefined ? {} : { details: report.details }),
91
+ localStatus: report.localStatus,
92
+ ...(report.localStatusReason === undefined
93
+ ? {}
94
+ : { localStatusReason: report.localStatusReason }),
95
+ })
96
+ .returning();
97
+ const [row] = rows;
98
+ if (row === undefined) {
99
+ throw new Error('The moderation report insert returned no row.');
100
+ }
101
+ return asReport(row);
102
+ },
103
+ async findById(reportId) {
104
+ const rows = await db.select().from(reports).where((0, drizzle_orm_1.eq)(reports.id, reportId)).limit(1);
105
+ const [row] = rows;
106
+ return row === undefined ? null : asReport(row);
107
+ },
108
+ async findByCaseId(caseId) {
109
+ const rows = await db
110
+ .select({
111
+ id: reports.id,
112
+ reportedType: reports.reportedType,
113
+ reportedId: reports.reportedId,
114
+ })
115
+ .from(reports)
116
+ .where((0, drizzle_orm_1.eq)(reports.crowdSourceCaseId, caseId));
117
+ return rows.map((row) => ({
118
+ id: String(row.id),
119
+ reportedType: String(row.reportedType),
120
+ reportedId: String(row.reportedId),
121
+ }));
122
+ },
123
+ async applyDecision(reportId, update, maxRevision) {
124
+ const rows = await db
125
+ .update(reports)
126
+ .set(decisionSet(update))
127
+ .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(reports.id, reportId),
128
+ /**
129
+ * The revision guard, in the WHERE clause. It is the DATABASE that
130
+ * refuses a stale write rather than a read-then-write in this
131
+ * process: deliveries overlap — CrowdSource retries for 24 hours, and
132
+ * a correction can arrive while the decision it supersedes is still
133
+ * being applied — and an older revision landing last would otherwise
134
+ * overwrite the current answer.
135
+ *
136
+ * `IS NULL` is the port of Mongo's `$exists: false`, because a report
137
+ * with no decision yet stores NULL rather than omitting the column.
138
+ * `<=` rather than `<` is deliberate: a redelivery of the SAME
139
+ * revision rewrites, which is harmless and keeps a partially-applied
140
+ * decision converging.
141
+ */
142
+ (0, drizzle_orm_1.or)((0, drizzle_orm_1.isNull)(reports.decisionRevision), (0, drizzle_orm_1.lte)(reports.decisionRevision, maxRevision))))
143
+ .returning({ id: reports.id });
144
+ return rows.length === 1;
145
+ },
146
+ async markSubmitted(reportId, submission) {
147
+ await db
148
+ .update(reports)
149
+ .set({
150
+ localStatus: 'submitted',
151
+ crowdSourceReportId: submission.crowdSourceReportId,
152
+ crowdSourceCaseId: submission.crowdSourceCaseId,
153
+ crowdSourceMerged: submission.crowdSourceMerged,
154
+ contentSnapshotHash: submission.contentSnapshotHash,
155
+ submittedAt: submission.submittedAt,
156
+ // A report that has landed carries no failure and no reason it was
157
+ // going nowhere. `null` CLEARS in drizzle; `undefined` would leave the
158
+ // stale value in place, which is the port of Mongo's `$unset`.
159
+ lastDeliveryError: null,
160
+ localStatusReason: null,
161
+ })
162
+ .where((0, drizzle_orm_1.eq)(reports.id, reportId));
163
+ },
164
+ async markDeliveryFailed(reportId, lastDeliveryError) {
165
+ await db
166
+ .update(reports)
167
+ .set({ localStatus: 'delivery_failed', lastDeliveryError })
168
+ .where((0, drizzle_orm_1.eq)(reports.id, reportId));
169
+ },
170
+ async close(reportId, localStatusReason) {
171
+ await db
172
+ .update(reports)
173
+ .set({ localStatus: 'closed', localStatusReason })
174
+ .where((0, drizzle_orm_1.eq)(reports.id, reportId));
175
+ },
176
+ async findPendingOldestFirst(limit) {
177
+ /**
178
+ * `queued` and `delivery_failed` only. `received` is excluded deliberately
179
+ * and the omission is the safety property, not an oversight: those reports
180
+ * have no subject provider, so an event re-derived for one would fail on
181
+ * its first attempt and dead-letter.
182
+ *
183
+ * Oldest first, and ASC needs no explicit NULLS placement: both drizzle and
184
+ * Postgres default ascending to NULLS LAST, so this matches the
185
+ * `(local_status, created_at)` index. A DESCENDING order would need the
186
+ * placement spelled out — see the enforcement store's reversal lookup for
187
+ * what that costs when it is not.
188
+ */
189
+ const rows = await db
190
+ .select({ id: reports.id })
191
+ .from(reports)
192
+ .where((0, drizzle_orm_1.inArray)(reports.localStatus, ['queued', 'delivery_failed']))
193
+ .orderBy((0, drizzle_orm_1.asc)(reports.createdAt))
194
+ .limit(limit);
195
+ return rows.map((row) => String(row.id));
196
+ },
197
+ async countAwaitingDecision(submittedBefore) {
198
+ const rows = await db
199
+ .select({ total })
200
+ .from(reports)
201
+ .where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(reports.localStatus, 'submitted'), (0, drizzle_orm_1.lt)(reports.submittedAt, submittedBefore)));
202
+ return rows[0]?.total ?? 0;
203
+ },
204
+ async countLocalOnly() {
205
+ const rows = await db
206
+ .select({ total })
207
+ .from(reports)
208
+ .where((0, drizzle_orm_1.eq)(reports.localStatus, 'received'));
209
+ return rows[0]?.total ?? 0;
210
+ },
211
+ };
212
+ }
213
+ /**
214
+ * The `$set` a decision writes, as one object.
215
+ *
216
+ * `extra` FIRST, for the same reason it is first on insert: it is the adopter's
217
+ * legacy verdict field, and this package's own fields must win.
218
+ */
219
+ function decisionSet(update) {
220
+ return {
221
+ ...update.extra,
222
+ localStatus: update.localStatus,
223
+ decisionId: update.decisionId,
224
+ decisionRevision: update.decisionRevision,
225
+ decisionOutcome: update.decisionOutcome,
226
+ decisionStatus: update.decisionStatus,
227
+ decidedAt: update.decidedAt,
228
+ ...(update.enforcedAction === undefined
229
+ ? {}
230
+ : { enforcedAction: update.enforcedAction }),
231
+ ...(update.enforcedAt === undefined ? {} : { enforcedAt: update.enforcedAt }),
232
+ };
233
+ }
234
+ //# sourceMappingURL=reports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reports.js","sourceRoot":"","sources":["../../../../src/outbox/postgres/store/reports.ts"],"names":[],"mappings":";;AA2HA,kDA2MC;AAtUD,6CAA8E;AAgE9E,MAAM,sBAAsB,GAAG;IAC7B,SAAS;IACT,mBAAmB;IACnB,qBAAqB;IACrB,mBAAmB;IACnB,mBAAmB;IACnB,qBAAqB;IACrB,aAAa;IACb,mBAAmB;IACnB,YAAY;IACZ,kBAAkB;IAClB,iBAAiB;IACjB,gBAAgB;IAChB,WAAW;IACX,gBAAgB;IAChB,YAAY;CACqC,CAAC;AAcpD,sEAAsE;AACtE,SAAS,eAAe,CAAC,GAA4B;IACnD,MAAM,UAAU,GAA4B,EAAE,GAAG,GAAG,EAAE,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,sBAAsB,EAAE,CAAC;QAC3C,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAS,QAAQ,CACf,GAA4B;IAE5B,OAAO,eAAe,CAAC,GAAG,CAAY,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB,CAAyC,KAG3E;IACC,MAAM,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IACrB,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC;IAElC;;;;;;;OAOG;IACH,MAAM,KAAK,GAAG,IAAA,iBAAG,EAAQ,eAAe,CAAC;IAEzC,OAAO;QACL,KAAK,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,EAAE;YAC5D,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,EAAE;iBACR,IAAI,CAAC,OAAO,CAAC;iBACb,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAC9B,IAAA,gBAAE,EAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,EAClC,IAAA,gBAAE,EAAC,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CACvC,CACF;iBACA,KAAK,CAAC,CAAC,CAAC,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACnB,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAU,GAAG,CAAC,CAAC;QAC3D,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE;YACrB,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC,OAAO,CAAC;iBACf,MAAM,CAAC;gBACN;;;;;;;;;;mBAUG;gBACH,GAAG,MAAM,CAAC,KAAK;gBACf,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;gBAClC,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpE,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,GAAG,CAAC,MAAM,CAAC,iBAAiB,KAAK,SAAS;oBACxC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,CAAC;aACrD,CAAC;iBACD,SAAS,EAAE,CAAC;YAEf,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACnB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,QAAQ,CAAU,GAAG,CAAC,CAAC;QAChC,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,QAAQ;YACrB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtF,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACnB,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAU,GAAG,CAAC,CAAC;QAC3D,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,MAAM;YACvB,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC;gBACN,EAAE,EAAE,OAAO,CAAC,EAAE;gBACd,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,UAAU,EAAE,OAAO,CAAC,UAAU;aAC/B,CAAC;iBACD,IAAI,CAAC,OAAO,CAAC;iBACb,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC,CAAC;YAEhD,OAAO,IAAI,CAAC,GAAG,CACb,CAAC,GAAG,EAAuB,EAAE,CAAC,CAAC;gBAC7B,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClB,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC;gBACtC,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC;aACnC,CAAC,CACH,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW;YAC/C,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;iBACxB,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC;YACxB;;;;;;;;;;;;;eAaG;YACH,IAAA,gBAAE,EACA,IAAA,oBAAM,EAAC,OAAO,CAAC,gBAAgB,CAAC,EAChC,IAAA,iBAAG,EAAC,OAAO,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAC3C,CACF,CACF;iBACA,SAAS,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;YAEjC,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC;QAC3B,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU;YACtC,MAAM,EAAE;iBACL,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC;gBACH,WAAW,EAAE,WAAW;gBACxB,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;gBACnD,iBAAiB,EAAE,UAAU,CAAC,iBAAiB;gBAC/C,iBAAiB,EAAE,UAAU,CAAC,iBAAiB;gBAC/C,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;gBACnD,WAAW,EAAE,UAAU,CAAC,WAAW;gBACnC,mEAAmE;gBACnE,uEAAuE;gBACvE,+DAA+D;gBAC/D,iBAAiB,EAAE,IAAI;gBACvB,iBAAiB,EAAE,IAAI;aACxB,CAAC;iBACD,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB;YAClD,MAAM,EAAE;iBACL,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;iBAC1D,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB;YACrC,MAAM,EAAE;iBACL,MAAM,CAAC,OAAO,CAAC;iBACf,GAAG,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAC;iBACjD,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,sBAAsB,CAAC,KAAK;YAChC;;;;;;;;;;;eAWG;YACH,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;iBAC1B,IAAI,CAAC,OAAO,CAAC;iBACb,KAAK,CAAC,IAAA,qBAAO,EAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC;iBAClE,OAAO,CAAC,IAAA,iBAAG,EAAC,OAAO,CAAC,SAAS,CAAC,CAAC;iBAC/B,KAAK,CAAC,KAAK,CAAC,CAAC;YAEhB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,CAAC,qBAAqB,CAAC,eAAe;YACzC,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;iBACjB,IAAI,CAAC,OAAO,CAAC;iBACb,KAAK,CACJ,IAAA,iBAAG,EACD,IAAA,gBAAE,EAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,EACpC,IAAA,gBAAE,EAAC,OAAO,CAAC,WAAW,EAAE,eAAe,CAAC,CACzC,CACF,CAAC;YACJ,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;QAC7B,CAAC;QAED,KAAK,CAAC,cAAc;YAClB,MAAM,IAAI,GAAG,MAAM,EAAE;iBAClB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;iBACjB,IAAI,CAAC,OAAO,CAAC;iBACb,KAAK,CAAC,IAAA,gBAAE,EAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;YAC9C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,MAAsC;IACzD,OAAO;QACL,GAAG,MAAM,CAAC,KAAK;QACf,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,GAAG,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS;YACrC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC;QAC9C,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,49 @@
1
+ import type { TablesRelationalConfig } from 'drizzle-orm';
2
+ import type { PgDatabase, PgQueryResultHKT } from 'drizzle-orm/pg-core';
3
+ import type { ModerationTransactionRunner } from '../../store/types.js';
4
+ /**
5
+ * The drizzle handle this package's Postgres stores talk to.
6
+ *
7
+ * Deliberately the BASE `PgDatabase` rather than a `PostgresJsDatabase`: the
8
+ * stores must accept both the pool handle an adopter builds and the `tx` handed
9
+ * to a `db.transaction` callback, and those are different types. Written this
10
+ * way, one signature serves both and no store needs to know which it holds.
11
+ *
12
+ * ## The generic that has to be `Record<string, unknown>`, and the error you get
13
+ *
14
+ * `TablesRelationalConfig` and `Record<string, unknown>` are the only spellings
15
+ * that accept both. The narrow one a reader reaches for first —
16
+ * `Record<string, never>` for the schema — accepts NEITHER (`TS2345`, the schema
17
+ * generic is invariant).
18
+ *
19
+ * The consequence lands on the ADOPTER, so it is worth stating: a handle built
20
+ * with NO schema (`drizzle(client)`, or `PostgresJsDatabase<Record<string, never>>`)
21
+ * is not assignable either, and the compiler explains it as
22
+ * `Seems like the schema generic is missing - did you forget to add it to your DB
23
+ * type?` — an error about `query`, on a store call that never touches the
24
+ * relational query builder. Pass your schema to `drizzle()` (or use
25
+ * `createDatabase({ databaseUrl, schema })` from `@oxy.so/db`) and it resolves.
26
+ * Both directions are verified in this package's own type-check.
27
+ */
28
+ export type ModerationPgHandle = PgDatabase<PgQueryResultHKT, Record<string, unknown>, TablesRelationalConfig>;
29
+ /**
30
+ * The transaction runner, in Postgres.
31
+ *
32
+ * READ COMMITTED, explicitly, and not `repeatable read`. Neither multi-statement
33
+ * transaction this package runs — a report insert plus an outbox upsert, an event
34
+ * update plus an outbox upsert — reads-then-decides in a way snapshot isolation
35
+ * protects, so `repeatable read` would import `40001` serialization failures and
36
+ * a retry loop for no benefit.
37
+ *
38
+ * What it deliberately does NOT promise: intake's duplicate-check-then-insert is
39
+ * not serialized at READ COMMITTED, and the "one report per reporter per object"
40
+ * unique index is explicitly the application's responsibility.
41
+ *
42
+ * The failure this runner exists to make impossible is subtler than Mongo's. A
43
+ * store call given `db` instead of `tx` inside the callback runs on a DIFFERENT
44
+ * pooled connection and commits on its own — no error, no warning, and the
45
+ * atomicity the outbox exists for is simply gone. `postgresOutboxStore.enqueue`
46
+ * refuses a handle that is not a transaction for exactly that reason.
47
+ */
48
+ export declare function postgresTransactionRunner(db: ModerationPgHandle): ModerationTransactionRunner<ModerationPgHandle>;
49
+ //# sourceMappingURL=transaction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../../../src/outbox/postgres/store/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,gBAAgB,EAChB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACvB,sBAAsB,CACvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,kBAAkB,GACrB,2BAA2B,CAAC,kBAAkB,CAAC,CAQjD"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.postgresTransactionRunner = postgresTransactionRunner;
4
+ /**
5
+ * The transaction runner, in Postgres.
6
+ *
7
+ * READ COMMITTED, explicitly, and not `repeatable read`. Neither multi-statement
8
+ * transaction this package runs — a report insert plus an outbox upsert, an event
9
+ * update plus an outbox upsert — reads-then-decides in a way snapshot isolation
10
+ * protects, so `repeatable read` would import `40001` serialization failures and
11
+ * a retry loop for no benefit.
12
+ *
13
+ * What it deliberately does NOT promise: intake's duplicate-check-then-insert is
14
+ * not serialized at READ COMMITTED, and the "one report per reporter per object"
15
+ * unique index is explicitly the application's responsibility.
16
+ *
17
+ * The failure this runner exists to make impossible is subtler than Mongo's. A
18
+ * store call given `db` instead of `tx` inside the callback runs on a DIFFERENT
19
+ * pooled connection and commits on its own — no error, no warning, and the
20
+ * atomicity the outbox exists for is simply gone. `postgresOutboxStore.enqueue`
21
+ * refuses a handle that is not a transaction for exactly that reason.
22
+ */
23
+ function postgresTransactionRunner(db) {
24
+ return {
25
+ async run(operation) {
26
+ return await db.transaction(async (tx) => await operation(tx), {
27
+ isolationLevel: 'read committed',
28
+ });
29
+ },
30
+ };
31
+ }
32
+ //# sourceMappingURL=transaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../src/outbox/postgres/store/transaction.ts"],"names":[],"mappings":";;AAqDA,8DAUC;AA7BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,yBAAyB,CACvC,EAAsB;IAEtB,OAAO;QACL,KAAK,CAAC,GAAG,CAAI,SAAiD;YAC5D,OAAO,MAAM,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,SAAS,CAAC,EAAE,CAAC,EAAE;gBAC7D,cAAc,EAAE,gBAAgB;aACjC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}