@storyshelf/core 0.3.1 → 0.5.3

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 (393) hide show
  1. package/README.md +38 -31
  2. package/dist/adapter/capture-queue.d.mts +29 -1
  3. package/dist/adapter/capture-runner.d.mts +18 -2
  4. package/dist/adapter/capture-runner.mjs +12 -1
  5. package/dist/adapter/capture-runner.mjs.map +1 -0
  6. package/dist/adapter/database.d.mts +67 -17
  7. package/dist/adapter/database.mjs +22 -55
  8. package/dist/adapter/database.mjs.map +1 -1
  9. package/dist/adapter/email-sender.d.mts +27 -0
  10. package/dist/adapter/email-sender.mjs +4 -0
  11. package/dist/adapter/metadata.d.mts +21 -15
  12. package/dist/adapter/notifier.d.mts +7 -0
  13. package/dist/adapter/notifier.mjs +6 -0
  14. package/dist/adapter/setup.d.mts +61 -0
  15. package/dist/adapter/setup.mjs +29 -0
  16. package/dist/adapter/setup.mjs.map +1 -0
  17. package/dist/adapter/webhook-events.d.mts +29 -0
  18. package/dist/adapter/webhook-events.mjs +83 -0
  19. package/dist/adapter/webhook-events.mjs.map +1 -0
  20. package/dist/adapters/notifier/events.d.mts +26 -0
  21. package/dist/adapters/notifier/events.mjs +66 -0
  22. package/dist/adapters/notifier/events.mjs.map +1 -0
  23. package/dist/adapters/notifier/format.d.mts +14 -0
  24. package/dist/adapters/notifier/format.mjs +96 -0
  25. package/dist/adapters/notifier/format.mjs.map +1 -0
  26. package/dist/adapters/notifier/provider.d.mts +32 -0
  27. package/dist/adapters/notifier/types.d.mts +56 -0
  28. package/dist/adapters/setup-runner.d.mts +23 -0
  29. package/dist/adapters/setup-runner.mjs +149 -0
  30. package/dist/adapters/setup-runner.mjs.map +1 -0
  31. package/dist/adapters/validate.d.mts +30 -0
  32. package/dist/adapters/validate.mjs +313 -0
  33. package/dist/adapters/validate.mjs.map +1 -0
  34. package/dist/auth.d.mts +94 -0
  35. package/dist/auth.mjs +4 -0
  36. package/dist/brand-packs.d.mts +16 -0
  37. package/dist/brand-packs.mjs +130 -0
  38. package/dist/brand-packs.mjs.map +1 -0
  39. package/dist/capture/adapter.d.mts +51 -1
  40. package/dist/capture/adapter.mjs.map +1 -1
  41. package/dist/capture/affected.d.mts +16 -0
  42. package/dist/capture/affected.mjs +64 -0
  43. package/dist/capture/affected.mjs.map +1 -0
  44. package/dist/capture/diff-record.mjs +30 -0
  45. package/dist/capture/diff-record.mjs.map +1 -0
  46. package/dist/capture/dispatch.d.mts +36 -0
  47. package/dist/capture/dispatch.mjs +88 -31
  48. package/dist/capture/dispatch.mjs.map +1 -1
  49. package/dist/capture/guards.mjs +31 -0
  50. package/dist/capture/guards.mjs.map +1 -0
  51. package/dist/capture/orchestrator.d.mts +41 -6
  52. package/dist/capture/orchestrator.mjs +151 -28
  53. package/dist/capture/orchestrator.mjs.map +1 -1
  54. package/dist/capture/pipeline.d.mts +30 -16
  55. package/dist/capture/pipeline.mjs +143 -39
  56. package/dist/capture/pipeline.mjs.map +1 -1
  57. package/dist/capture/recovery.d.mts +21 -0
  58. package/dist/capture/recovery.mjs +83 -0
  59. package/dist/capture/recovery.mjs.map +1 -0
  60. package/dist/capture/rediff.d.mts +35 -0
  61. package/dist/capture/rediff.mjs +77 -0
  62. package/dist/capture/rediff.mjs.map +1 -0
  63. package/dist/capture/sizing.d.mts +58 -0
  64. package/dist/capture/sizing.mjs +119 -0
  65. package/dist/capture/sizing.mjs.map +1 -0
  66. package/dist/capture/skip-checks.mjs +3 -3
  67. package/dist/capture/skip-checks.mjs.map +1 -1
  68. package/dist/capture/statics.d.mts +38 -0
  69. package/dist/capture/statics.mjs +38 -4
  70. package/dist/capture/statics.mjs.map +1 -1
  71. package/dist/capture/status-fanout.mjs +7 -2
  72. package/dist/capture/status-fanout.mjs.map +1 -1
  73. package/dist/capture/storybook.d.mts +31 -2
  74. package/dist/capture/storybook.mjs +77 -2
  75. package/dist/capture/storybook.mjs.map +1 -1
  76. package/dist/capture.d.mts +10 -4
  77. package/dist/capture.mjs +7 -2
  78. package/dist/config.d.mts +121 -4
  79. package/dist/config.mjs +55 -8
  80. package/dist/config.mjs.map +1 -1
  81. package/dist/index.d.mts +5 -56
  82. package/dist/index.mjs +4 -284
  83. package/dist/logger.d.mts +26 -17
  84. package/dist/logger.mjs +10 -5
  85. package/dist/logger.mjs.map +1 -1
  86. package/dist/models/baseline-status.d.mts +29 -0
  87. package/dist/models/baseline-status.mjs +26 -0
  88. package/dist/models/baseline-status.mjs.map +1 -0
  89. package/dist/models/baseline.d.mts +33 -0
  90. package/dist/models/baseline.mjs +35 -13
  91. package/dist/models/baseline.mjs.map +1 -1
  92. package/dist/models/build.d.mts +87 -0
  93. package/dist/models/build.mjs +83 -35
  94. package/dist/models/build.mjs.map +1 -1
  95. package/dist/models/capture-attempt.d.mts +40 -0
  96. package/dist/models/capture-attempt.mjs +85 -0
  97. package/dist/models/capture-attempt.mjs.map +1 -0
  98. package/dist/models/capture-log.d.mts +21 -0
  99. package/dist/models/capture-log.mjs +44 -0
  100. package/dist/models/capture-log.mjs.map +1 -0
  101. package/dist/models/comment.d.mts +29 -0
  102. package/dist/models/comment.mjs +11 -8
  103. package/dist/models/comment.mjs.map +1 -1
  104. package/dist/models/content-ref.d.mts +21 -0
  105. package/dist/models/content-ref.mjs +49 -0
  106. package/dist/models/content-ref.mjs.map +1 -0
  107. package/dist/models/credentials.d.mts +36 -0
  108. package/dist/models/credentials.mjs +103 -0
  109. package/dist/models/credentials.mjs.map +1 -0
  110. package/dist/models/label.d.mts +58 -0
  111. package/dist/models/label.mjs +32 -27
  112. package/dist/models/label.mjs.map +1 -1
  113. package/dist/models/member.d.mts +34 -0
  114. package/dist/models/member.mjs +20 -11
  115. package/dist/models/member.mjs.map +1 -1
  116. package/dist/models/notification-channel.d.mts +52 -0
  117. package/dist/models/notification-channel.mjs +93 -0
  118. package/dist/models/notification-channel.mjs.map +1 -0
  119. package/dist/models/notification-subscription.d.mts +44 -0
  120. package/dist/models/notification-subscription.mjs +89 -0
  121. package/dist/models/notification-subscription.mjs.map +1 -0
  122. package/dist/models/project-group-mapping.d.mts +30 -0
  123. package/dist/models/project-group-mapping.mjs +46 -0
  124. package/dist/models/project-group-mapping.mjs.map +1 -0
  125. package/dist/models/project.d.mts +54 -0
  126. package/dist/models/project.mjs +15 -11
  127. package/dist/models/project.mjs.map +1 -1
  128. package/dist/models/snapshot.d.mts +58 -0
  129. package/dist/models/snapshot.mjs +13 -7
  130. package/dist/models/snapshot.mjs.map +1 -1
  131. package/dist/models/status-config.d.mts +38 -0
  132. package/dist/models/status-config.mjs +12 -11
  133. package/dist/models/status-config.mjs.map +1 -1
  134. package/dist/models/token.d.mts +44 -0
  135. package/dist/models/token.mjs +18 -15
  136. package/dist/models/token.mjs.map +1 -1
  137. package/dist/models/user.d.mts +42 -0
  138. package/dist/models/user.mjs +65 -0
  139. package/dist/models/user.mjs.map +1 -0
  140. package/dist/models/webhook.d.mts +50 -0
  141. package/dist/models/webhook.mjs +12 -10
  142. package/dist/models/webhook.mjs.map +1 -1
  143. package/dist/models.d.mts +22 -0
  144. package/dist/models.mjs +23 -0
  145. package/dist/paths.mjs +29 -0
  146. package/dist/paths.mjs.map +1 -1
  147. package/dist/retention.d.mts +45 -0
  148. package/dist/retention.mjs +145 -0
  149. package/dist/retention.mjs.map +1 -0
  150. package/dist/schema/baseline.d.mts +1 -0
  151. package/dist/schema/build.d.mts +8 -0
  152. package/dist/schema/capture-attempt.d.mts +38 -0
  153. package/dist/schema/comment.d.mts +1 -1
  154. package/dist/schema/content-ref.d.mts +13 -0
  155. package/dist/schema/member.d.mts +2 -0
  156. package/dist/schema/notification.d.mts +35 -0
  157. package/dist/schema/project-group-mapping.d.mts +15 -0
  158. package/dist/schema/project.d.mts +4 -0
  159. package/dist/schema/snapshot.d.mts +7 -0
  160. package/dist/schema/token.d.mts +2 -0
  161. package/dist/schema/user.d.mts +11 -1
  162. package/dist/schema.d.mts +9 -46
  163. package/dist/schema.mjs +1 -55
  164. package/dist/test-helpers/create-project.d.mts +15 -0
  165. package/dist/test-helpers/create-project.mjs +28 -0
  166. package/dist/test-helpers/create-project.mjs.map +1 -0
  167. package/dist/test-helpers/database-contract.d.mts +13 -0
  168. package/dist/test-helpers/database-contract.mjs +58 -0
  169. package/dist/test-helpers/database-contract.mjs.map +1 -0
  170. package/dist/test-helpers/fake-adapters.d.mts +14 -0
  171. package/dist/test-helpers/fake-adapters.mjs +20 -0
  172. package/dist/test-helpers/fake-adapters.mjs.map +1 -0
  173. package/dist/test-helpers/fake-database.d.mts +11 -0
  174. package/dist/test-helpers/fake-database.mjs +104 -0
  175. package/dist/test-helpers/fake-database.mjs.map +1 -0
  176. package/dist/test-helpers/fake-storage.d.mts +14 -0
  177. package/dist/test-helpers/fake-storage.mjs +49 -0
  178. package/dist/test-helpers/fake-storage.mjs.map +1 -0
  179. package/dist/test-helpers/fake-tables.mjs +276 -0
  180. package/dist/test-helpers/fake-tables.mjs.map +1 -0
  181. package/dist/test-helpers/git-contract.d.mts +11 -0
  182. package/dist/test-helpers/git-contract.mjs +34 -0
  183. package/dist/test-helpers/git-contract.mjs.map +1 -0
  184. package/dist/test-helpers/notifier-contract.d.mts +11 -0
  185. package/dist/test-helpers/notifier-contract.mjs +34 -0
  186. package/dist/test-helpers/notifier-contract.mjs.map +1 -0
  187. package/dist/test-helpers/queue-contract.d.mts +11 -0
  188. package/dist/test-helpers/queue-contract.mjs +64 -0
  189. package/dist/test-helpers/queue-contract.mjs.map +1 -0
  190. package/dist/test-helpers/runner-contract.d.mts +11 -0
  191. package/dist/test-helpers/runner-contract.mjs +32 -0
  192. package/dist/test-helpers/runner-contract.mjs.map +1 -0
  193. package/dist/test-helpers/sql-chunks.mjs +138 -0
  194. package/dist/test-helpers/sql-chunks.mjs.map +1 -0
  195. package/dist/test-helpers/storage-contract.d.mts +11 -0
  196. package/dist/test-helpers/storage-contract.mjs +87 -0
  197. package/dist/test-helpers/storage-contract.mjs.map +1 -0
  198. package/dist/test-helpers.d.mts +13 -0
  199. package/dist/test-helpers.mjs +14 -0
  200. package/dist/tracing.mjs +63 -0
  201. package/dist/tracing.mjs.map +1 -0
  202. package/dist/types.d.mts +38 -5
  203. package/dist/types.mjs +18 -5
  204. package/dist/types.mjs.map +1 -1
  205. package/dist/urls.d.mts +12 -1
  206. package/dist/urls.mjs +22 -3
  207. package/dist/urls.mjs.map +1 -1
  208. package/dist/utils/encrypt.d.mts +48 -0
  209. package/dist/utils/encrypt.mjs +67 -13
  210. package/dist/utils/encrypt.mjs.map +1 -1
  211. package/dist/utils/hash.d.mts +17 -0
  212. package/dist/utils/hash.mjs +8 -2
  213. package/dist/utils/hash.mjs.map +1 -1
  214. package/dist/utils/http.d.mts +58 -0
  215. package/dist/utils/http.mjs +147 -0
  216. package/dist/utils/http.mjs.map +1 -0
  217. package/dist/utils/mime.d.mts +9 -0
  218. package/dist/utils/mime.mjs +33 -0
  219. package/dist/utils/mime.mjs.map +1 -0
  220. package/dist/utils/path-security.d.mts +12 -0
  221. package/dist/utils/path-security.mjs +24 -0
  222. package/dist/utils/path-security.mjs.map +1 -0
  223. package/dist/utils/redact.d.mts +17 -0
  224. package/dist/utils/redact.mjs +42 -0
  225. package/dist/utils/redact.mjs.map +1 -0
  226. package/dist/utils/timing.d.mts +19 -0
  227. package/dist/utils/timing.mjs +46 -0
  228. package/dist/utils/timing.mjs.map +1 -0
  229. package/dist/utils/ulid.d.mts +10 -0
  230. package/dist/utils/ulid.mjs +8 -8
  231. package/dist/utils/ulid.mjs.map +1 -1
  232. package/dist/utils.d.mts +12 -0
  233. package/dist/utils.mjs +13 -0
  234. package/package.json +69 -28
  235. package/dist/adapter/auth.d.mts +0 -50
  236. package/dist/adapter/auth.mjs +0 -10
  237. package/dist/adapter/auth.mjs.map +0 -1
  238. package/dist/adapter/init.d.mts +0 -58
  239. package/dist/adapter/init.mjs +0 -93
  240. package/dist/adapter/init.mjs.map +0 -1
  241. package/dist/adapters/webhook-events.mjs +0 -55
  242. package/dist/adapters/webhook-events.mjs.map +0 -1
  243. package/dist/ddl.d.mts +0 -8
  244. package/dist/ddl.mjs +0 -158
  245. package/dist/ddl.mjs.map +0 -1
  246. package/dist/index.mjs.map +0 -1
  247. package/dist/middleware/auth-gate.mjs +0 -36
  248. package/dist/middleware/auth-gate.mjs.map +0 -1
  249. package/dist/middleware/csrf.mjs +0 -40
  250. package/dist/middleware/csrf.mjs.map +0 -1
  251. package/dist/middleware/rate-limit.mjs +0 -39
  252. package/dist/middleware/rate-limit.mjs.map +0 -1
  253. package/dist/middleware/request-log.mjs +0 -28
  254. package/dist/middleware/request-log.mjs.map +0 -1
  255. package/dist/middleware/store-scope.mjs +0 -29
  256. package/dist/middleware/store-scope.mjs.map +0 -1
  257. package/dist/pages/build-detail.mjs +0 -339
  258. package/dist/pages/build-detail.mjs.map +0 -1
  259. package/dist/pages/build-diff-comments.mjs +0 -113
  260. package/dist/pages/build-diff-comments.mjs.map +0 -1
  261. package/dist/pages/build-diff-header.mjs +0 -163
  262. package/dist/pages/build-diff-header.mjs.map +0 -1
  263. package/dist/pages/build-diff-nav.mjs +0 -66
  264. package/dist/pages/build-diff-nav.mjs.map +0 -1
  265. package/dist/pages/build-diff-viewer.mjs +0 -197
  266. package/dist/pages/build-diff-viewer.mjs.map +0 -1
  267. package/dist/pages/build-diff.mjs +0 -90
  268. package/dist/pages/build-diff.mjs.map +0 -1
  269. package/dist/pages/compute-jobs.mjs +0 -198
  270. package/dist/pages/compute-jobs.mjs.map +0 -1
  271. package/dist/pages/label-detail.mjs +0 -228
  272. package/dist/pages/label-detail.mjs.map +0 -1
  273. package/dist/pages/login.mjs +0 -78
  274. package/dist/pages/login.mjs.map +0 -1
  275. package/dist/pages/project-builds.mjs +0 -231
  276. package/dist/pages/project-builds.mjs.map +0 -1
  277. package/dist/pages/project-create.mjs +0 -169
  278. package/dist/pages/project-create.mjs.map +0 -1
  279. package/dist/pages/project-settings.mjs +0 -102
  280. package/dist/pages/project-settings.mjs.map +0 -1
  281. package/dist/pages/projects.mjs +0 -184
  282. package/dist/pages/projects.mjs.map +0 -1
  283. package/dist/pages/root.mjs +0 -94
  284. package/dist/pages/root.mjs.map +0 -1
  285. package/dist/pages/settings-general.mjs +0 -192
  286. package/dist/pages/settings-general.mjs.map +0 -1
  287. package/dist/pages/settings-labels.mjs +0 -150
  288. package/dist/pages/settings-labels.mjs.map +0 -1
  289. package/dist/pages/settings-members.mjs +0 -125
  290. package/dist/pages/settings-members.mjs.map +0 -1
  291. package/dist/pages/settings-status.mjs +0 -152
  292. package/dist/pages/settings-status.mjs.map +0 -1
  293. package/dist/pages/settings-tests.mjs +0 -149
  294. package/dist/pages/settings-tests.mjs.map +0 -1
  295. package/dist/pages/settings-tokens.mjs +0 -96
  296. package/dist/pages/settings-tokens.mjs.map +0 -1
  297. package/dist/pages/settings-webhooks.mjs +0 -150
  298. package/dist/pages/settings-webhooks.mjs.map +0 -1
  299. package/dist/pages/storybook.mjs +0 -96
  300. package/dist/pages/storybook.mjs.map +0 -1
  301. package/dist/retention/purge.mjs +0 -67
  302. package/dist/retention/purge.mjs.map +0 -1
  303. package/dist/routers/admin.mjs +0 -42
  304. package/dist/routers/admin.mjs.map +0 -1
  305. package/dist/routers/assets.mjs +0 -25
  306. package/dist/routers/assets.mjs.map +0 -1
  307. package/dist/routers/auth.mjs +0 -78
  308. package/dist/routers/auth.mjs.map +0 -1
  309. package/dist/routers/builds.handlers.mjs +0 -184
  310. package/dist/routers/builds.handlers.mjs.map +0 -1
  311. package/dist/routers/builds.mjs +0 -185
  312. package/dist/routers/builds.mjs.map +0 -1
  313. package/dist/routers/comments.mjs +0 -90
  314. package/dist/routers/comments.mjs.map +0 -1
  315. package/dist/routers/health.mjs +0 -137
  316. package/dist/routers/health.mjs.map +0 -1
  317. package/dist/routers/helpers.mjs +0 -82
  318. package/dist/routers/helpers.mjs.map +0 -1
  319. package/dist/routers/htmx.mjs +0 -20
  320. package/dist/routers/htmx.mjs.map +0 -1
  321. package/dist/routers/labels.mjs +0 -110
  322. package/dist/routers/labels.mjs.map +0 -1
  323. package/dist/routers/media.mjs +0 -55
  324. package/dist/routers/media.mjs.map +0 -1
  325. package/dist/routers/members.mjs +0 -102
  326. package/dist/routers/members.mjs.map +0 -1
  327. package/dist/routers/projects.mjs +0 -122
  328. package/dist/routers/projects.mjs.map +0 -1
  329. package/dist/routers/schemas.mjs +0 -224
  330. package/dist/routers/schemas.mjs.map +0 -1
  331. package/dist/routers/settings-general.mjs +0 -95
  332. package/dist/routers/settings-general.mjs.map +0 -1
  333. package/dist/routers/settings-labels.mjs +0 -49
  334. package/dist/routers/settings-labels.mjs.map +0 -1
  335. package/dist/routers/settings-members.mjs +0 -30
  336. package/dist/routers/settings-members.mjs.map +0 -1
  337. package/dist/routers/settings-status.mjs +0 -73
  338. package/dist/routers/settings-status.mjs.map +0 -1
  339. package/dist/routers/settings-tokens.mjs +0 -40
  340. package/dist/routers/settings-tokens.mjs.map +0 -1
  341. package/dist/routers/settings-webhooks.mjs +0 -63
  342. package/dist/routers/settings-webhooks.mjs.map +0 -1
  343. package/dist/routers/settings.handlers.mjs +0 -93
  344. package/dist/routers/settings.handlers.mjs.map +0 -1
  345. package/dist/routers/settings.mjs +0 -23
  346. package/dist/routers/settings.mjs.map +0 -1
  347. package/dist/routers/snapshots.mjs +0 -144
  348. package/dist/routers/snapshots.mjs.map +0 -1
  349. package/dist/routers/status-configs.mjs +0 -101
  350. package/dist/routers/status-configs.mjs.map +0 -1
  351. package/dist/routers/storybook.mjs +0 -120
  352. package/dist/routers/storybook.mjs.map +0 -1
  353. package/dist/routers/tokens.mjs +0 -81
  354. package/dist/routers/tokens.mjs.map +0 -1
  355. package/dist/routers/ui.mjs +0 -165
  356. package/dist/routers/ui.mjs.map +0 -1
  357. package/dist/routers/webhooks.mjs +0 -90
  358. package/dist/routers/webhooks.mjs.map +0 -1
  359. package/dist/schema/baseline.mjs +0 -22
  360. package/dist/schema/baseline.mjs.map +0 -1
  361. package/dist/schema/build.mjs +0 -29
  362. package/dist/schema/build.mjs.map +0 -1
  363. package/dist/schema/comment.mjs +0 -26
  364. package/dist/schema/comment.mjs.map +0 -1
  365. package/dist/schema/label.mjs +0 -30
  366. package/dist/schema/label.mjs.map +0 -1
  367. package/dist/schema/member.mjs +0 -19
  368. package/dist/schema/member.mjs.map +0 -1
  369. package/dist/schema/project.mjs +0 -25
  370. package/dist/schema/project.mjs.map +0 -1
  371. package/dist/schema/snapshot.mjs +0 -34
  372. package/dist/schema/snapshot.mjs.map +0 -1
  373. package/dist/schema/status-config.mjs +0 -20
  374. package/dist/schema/status-config.mjs.map +0 -1
  375. package/dist/schema/token.mjs +0 -19
  376. package/dist/schema/token.mjs.map +0 -1
  377. package/dist/schema/user.mjs +0 -19
  378. package/dist/schema/user.mjs.map +0 -1
  379. package/dist/schema/webhook.mjs +0 -20
  380. package/dist/schema/webhook.mjs.map +0 -1
  381. package/dist/schema.mjs.map +0 -1
  382. package/dist/store.mjs +0 -20
  383. package/dist/store.mjs.map +0 -1
  384. package/dist/ui/document.mjs +0 -348
  385. package/dist/ui/document.mjs.map +0 -1
  386. package/dist/ui/feedback.mjs +0 -24
  387. package/dist/ui/feedback.mjs.map +0 -1
  388. package/dist/ui/forms.mjs +0 -117
  389. package/dist/ui/forms.mjs.map +0 -1
  390. package/dist/ui/styles.mjs +0 -174
  391. package/dist/ui/styles.mjs.map +0 -1
  392. package/dist/ui/theme.mjs +0 -44
  393. package/dist/ui/theme.mjs.map +0 -1
@@ -0,0 +1,28 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { BuildModel } from "../models/build.mjs";
5
+ import { ProjectModel } from "../models/project.mjs";
6
+ //#region src/test-helpers/create-project.ts
7
+ /** Create a test project with owner/repo defaults. */
8
+ async function createTestProject(db, tables, overrides) {
9
+ const { gitRepository: repo, ...rest } = overrides ?? {};
10
+ const gitRepository = repo ?? "owner/repo";
11
+ return await new ProjectModel(db, tables).create({
12
+ name: "Test",
13
+ gitRepository,
14
+ ...rest
15
+ });
16
+ }
17
+ /** Create a test build on main with sha-1 defaults. */
18
+ async function createTestBuild(db, tables, projectId, overrides) {
19
+ return await new BuildModel(db, tables).create(projectId, {
20
+ gitSha: "sha-1",
21
+ gitBranch: "main",
22
+ ...overrides
23
+ });
24
+ }
25
+ //#endregion
26
+ export { createTestBuild, createTestProject };
27
+
28
+ //# sourceMappingURL=create-project.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-project.mjs","names":[],"sources":["../../src/test-helpers/create-project.ts"],"sourcesContent":["import type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport { BuildModel, type BuildTables } from \"../models/build.ts\";\nimport { ProjectModel, type ProjectTables } from \"../models/project.ts\";\nimport type { Build } from \"../schema/build.ts\";\nimport type { Project } from \"../schema/project.ts\";\n\n/** Create a test project with owner/repo defaults. */\nexport async function createTestProject(\n db: DatabaseAdapter,\n tables: ProjectTables,\n overrides?: Partial<Project>,\n): Promise<Project> {\n const { gitRepository: repo, ...rest } = overrides ?? {};\n const gitRepository = repo ?? \"owner/repo\";\n return await new ProjectModel(db, tables).create({ name: \"Test\", gitRepository, ...rest });\n}\n\n/** Create a test build on main with sha-1 defaults. */\nexport async function createTestBuild(\n db: DatabaseAdapter,\n tables: BuildTables,\n projectId: string,\n overrides?: Partial<Build>,\n): Promise<Build> {\n return await new BuildModel(db, tables).create(projectId, {\n gitSha: \"sha-1\",\n gitBranch: \"main\",\n ...overrides,\n } as Parameters<BuildModel[\"create\"]>[1]);\n}\n"],"mappings":";;;;;;;AAOA,eAAsB,kBACpB,IACA,QACA,WACkB;CAClB,MAAM,EAAE,eAAe,MAAM,GAAG,SAAS,aAAa,CAAC;CACvD,MAAM,gBAAgB,QAAQ;CAC9B,OAAO,MAAM,IAAI,aAAa,IAAI,MAAM,CAAC,CAAC,OAAO;EAAE,MAAM;EAAQ;EAAe,GAAG;CAAK,CAAC;AAC3F;;AAGA,eAAsB,gBACpB,IACA,QACA,WACA,WACgB;CAChB,OAAO,MAAM,IAAI,WAAW,IAAI,MAAM,CAAC,CAAC,OAAO,WAAW;EACxD,QAAQ;EACR,WAAW;EACX,GAAG;CACL,CAAwC;AAC1C"}
@@ -0,0 +1,13 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { DatabaseAdapter } from "../adapter/database.mjs";
4
+ //#region src/test-helpers/database-contract.d.ts
5
+ /** Tables every adapter must expose (single-sourced from the contract). */
6
+ declare const REQUIRED_TABLES: string[];
7
+ /** Build the adapter under test (sync or async factories both work). */
8
+ type DatabaseFactory = () => DatabaseAdapter | Promise<DatabaseAdapter>;
9
+ /** Run the database contract against a factory. */
10
+ declare function databaseContractSuite(label: string, make: DatabaseFactory): void;
11
+ //#endregion
12
+ export { DatabaseFactory, REQUIRED_TABLES, databaseContractSuite };
13
+ //# sourceMappingURL=database-contract.d.mts.map
@@ -0,0 +1,58 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { REQUIRED_TABLE_KEYS } from "../adapter/database.mjs";
5
+ import { describe, expect, it } from "vitest";
6
+ //#region src/test-helpers/database-contract.ts
7
+ /**
8
+ * Published database contract suite for first- and third-party adapters.
9
+ *
10
+ * Structural conformance only (identity, table map, methods, lifecycle
11
+ * rule) — row-level CRUD stays per-package because insert shapes differ per
12
+ * dialect schema. A package proves conformance in one line:
13
+ *
14
+ * ```ts
15
+ * import { databaseContractSuite } from "@storyshelf/core/test-helpers";
16
+ * databaseContractSuite("sqlite", () => createSqliteDatabase(":memory:"));
17
+ * ```
18
+ */
19
+ /** Tables every adapter must expose (single-sourced from the contract). */
20
+ const REQUIRED_TABLES = REQUIRED_TABLE_KEYS;
21
+ const REQUIRED_METHODS = [
22
+ "insert",
23
+ "update",
24
+ "get",
25
+ "remove",
26
+ "list",
27
+ "count",
28
+ "all"
29
+ ];
30
+ /** Run the database contract against a factory. */
31
+ function databaseContractSuite(label, make) {
32
+ describe(`database contract: ${label}`, () => {
33
+ it("exposes database metadata", async () => {
34
+ const adapter = await make();
35
+ expect(adapter.metadata.category).toBe("database");
36
+ expect(adapter.metadata.kind.length).toBeGreaterThan(0);
37
+ });
38
+ it("exposes the full table map", async () => {
39
+ const tables = (await make()).tables;
40
+ for (const table of REQUIRED_TABLES) expect(tables[table], `missing table: ${table}`).toBeDefined();
41
+ });
42
+ it("exposes every CRUD method", async () => {
43
+ const adapter = await make();
44
+ for (const method of REQUIRED_METHODS) expect(typeof adapter[method]).toBe("function");
45
+ });
46
+ it("keeps the lifecycle rule (absent or all three hooks)", async () => {
47
+ const lifecycle = (await make()).lifecycle;
48
+ if (lifecycle === void 0) return;
49
+ expect(typeof lifecycle.setup).toBe("function");
50
+ expect(typeof lifecycle.teardown).toBe("function");
51
+ expect(typeof lifecycle.health).toBe("function");
52
+ });
53
+ });
54
+ }
55
+ //#endregion
56
+ export { REQUIRED_TABLES, databaseContractSuite };
57
+
58
+ //# sourceMappingURL=database-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-contract.mjs","names":[],"sources":["../../src/test-helpers/database-contract.ts"],"sourcesContent":["/**\n * Published database contract suite for first- and third-party adapters.\n *\n * Structural conformance only (identity, table map, methods, lifecycle\n * rule) — row-level CRUD stays per-package because insert shapes differ per\n * dialect schema. A package proves conformance in one line:\n *\n * ```ts\n * import { databaseContractSuite } from \"@storyshelf/core/test-helpers\";\n * databaseContractSuite(\"sqlite\", () => createSqliteDatabase(\":memory:\"));\n * ```\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport { REQUIRED_TABLE_KEYS } from \"../adapters/database.ts\";\n\n/** Tables every adapter must expose (single-sourced from the contract). */\nexport const REQUIRED_TABLES = REQUIRED_TABLE_KEYS;\n\nconst REQUIRED_METHODS = [\"insert\", \"update\", \"get\", \"remove\", \"list\", \"count\", \"all\"];\n\n/** Build the adapter under test (sync or async factories both work). */\nexport type DatabaseFactory = () => DatabaseAdapter | Promise<DatabaseAdapter>;\n\n/** Run the database contract against a factory. */\nexport function databaseContractSuite(label: string, make: DatabaseFactory): void {\n describe(`database contract: ${label}`, () => {\n it(\"exposes database metadata\", async () => {\n const adapter = await make();\n expect(adapter.metadata.category).toBe(\"database\");\n expect(adapter.metadata.kind.length).toBeGreaterThan(0);\n });\n\n it(\"exposes the full table map\", async () => {\n const adapter = await make();\n const tables = adapter.tables as unknown as Record<string, unknown>;\n for (const table of REQUIRED_TABLES) {\n expect(tables[table], `missing table: ${table}`).toBeDefined();\n }\n });\n\n it(\"exposes every CRUD method\", async () => {\n const adapter = await make();\n for (const method of REQUIRED_METHODS) {\n expect(typeof (adapter as unknown as Record<string, unknown>)[method]).toBe(\"function\");\n }\n });\n\n it(\"keeps the lifecycle rule (absent or all three hooks)\", async () => {\n const adapter = await make();\n const lifecycle = adapter.lifecycle as\n | { setup?: unknown; teardown?: unknown; health?: unknown }\n | undefined;\n if (lifecycle === undefined) {\n return;\n }\n expect(typeof lifecycle.setup).toBe(\"function\");\n expect(typeof lifecycle.teardown).toBe(\"function\");\n expect(typeof lifecycle.health).toBe(\"function\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAiBA,MAAa,kBAAkB;AAE/B,MAAM,mBAAmB;CAAC;CAAU;CAAU;CAAO;CAAU;CAAQ;CAAS;AAAK;;AAMrF,SAAgB,sBAAsB,OAAe,MAA6B;CAChF,SAAS,sBAAsB,eAAe;EAC5C,GAAG,6BAA6B,YAAY;GAC1C,MAAM,UAAU,MAAM,KAAK;GAC3B,OAAO,QAAQ,SAAS,QAAQ,CAAC,CAAC,KAAK,UAAU;GACjD,OAAO,QAAQ,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACxD,CAAC;EAED,GAAG,8BAA8B,YAAY;GAE3C,MAAM,UAAS,MADO,KAAK,EAAA,CACJ;GACvB,KAAK,MAAM,SAAS,iBAClB,OAAO,OAAO,QAAQ,kBAAkB,OAAO,CAAC,CAAC,YAAY;EAEjE,CAAC;EAED,GAAG,6BAA6B,YAAY;GAC1C,MAAM,UAAU,MAAM,KAAK;GAC3B,KAAK,MAAM,UAAU,kBACnB,OAAO,OAAQ,QAA+C,OAAO,CAAC,CAAC,KAAK,UAAU;EAE1F,CAAC;EAED,GAAG,wDAAwD,YAAY;GAErE,MAAM,aAAY,MADI,KAAK,EAAA,CACD;GAG1B,IAAI,cAAc,KAAA,GAChB;GAEF,OAAO,OAAO,UAAU,KAAK,CAAC,CAAC,KAAK,UAAU;GAC9C,OAAO,OAAO,UAAU,QAAQ,CAAC,CAAC,KAAK,UAAU;GACjD,OAAO,OAAO,UAAU,MAAM,CAAC,CAAC,KAAK,UAAU;EACjD,CAAC;CACH,CAAC;AACH"}
@@ -0,0 +1,14 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { DatabaseAdapter } from "../adapter/database.mjs";
4
+ import { makeDatabase } from "./fake-database.mjs";
5
+ import { FakeStorage, makeStorage } from "./fake-storage.mjs";
6
+ //#region src/test-helpers/fake-adapters.d.ts
7
+ /**
8
+ * Empty table map for spec/test doubles whose methods never run (OpenAPI
9
+ * generation, asset serving). Satisfies boot validation without a driver.
10
+ */
11
+ declare function stubTables(): DatabaseAdapter["tables"];
12
+ //#endregion
13
+ export { type FakeStorage, makeDatabase, makeStorage, stubTables };
14
+ //# sourceMappingURL=fake-adapters.d.mts.map
@@ -0,0 +1,20 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { REQUIRED_TABLE_KEYS } from "../adapter/database.mjs";
5
+ import { makeDatabase } from "./fake-database.mjs";
6
+ import { makeStorage } from "./fake-storage.mjs";
7
+ //#region src/test-helpers/fake-adapters.ts
8
+ /**
9
+ * Empty table map for spec/test doubles whose methods never run (OpenAPI
10
+ * generation, asset serving). Satisfies boot validation without a driver.
11
+ */
12
+ function stubTables() {
13
+ const tables = {};
14
+ for (const key of REQUIRED_TABLE_KEYS) tables[key] = {};
15
+ return tables;
16
+ }
17
+ //#endregion
18
+ export { makeDatabase, makeStorage, stubTables };
19
+
20
+ //# sourceMappingURL=fake-adapters.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-adapters.mjs","names":[],"sources":["../../src/test-helpers/fake-adapters.ts"],"sourcesContent":["/**\n * In-memory test doubles for adapter-contract tests.\n *\n * Re-exports the focused fakes so existing imports keep working; new code\n * should import `fake-storage.ts`, `fake-database.ts`, or `sql-chunks.ts`\n * directly.\n */\nimport type { DatabaseAdapter } from \"../adapters/database.ts\";\nimport { REQUIRED_TABLE_KEYS } from \"../adapters/database.ts\";\nexport { makeDatabase } from \"./fake-database.ts\";\nexport { makeStorage, type FakeStorage } from \"./fake-storage.ts\";\n\n/**\n * Empty table map for spec/test doubles whose methods never run (OpenAPI\n * generation, asset serving). Satisfies boot validation without a driver.\n */\nexport function stubTables(): DatabaseAdapter[\"tables\"] {\n const tables: Record<string, unknown> = {};\n for (const key of REQUIRED_TABLE_KEYS) {\n tables[key] = {};\n }\n return tables as unknown as DatabaseAdapter[\"tables\"];\n}\n"],"mappings":";;;;;;;;;;;AAgBA,SAAgB,aAAwC;CACtD,MAAM,SAAkC,CAAC;CACzC,KAAK,MAAM,OAAO,qBAChB,OAAO,OAAO,CAAC;CAEjB,OAAO;AACT"}
@@ -0,0 +1,11 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { DatabaseAdapter } from "../adapter/database.mjs";
4
+ //#region src/test-helpers/fake-database.d.ts
5
+ /** Create an in-memory database adapter for capture pipeline tests. */
6
+ declare function makeDatabase(): {
7
+ db: DatabaseAdapter;
8
+ };
9
+ //#endregion
10
+ export { makeDatabase };
11
+ //# sourceMappingURL=fake-database.d.mts.map
@@ -0,0 +1,104 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { clampListLimit } from "../adapter/database.mjs";
5
+ import { fakeSchema } from "./fake-tables.mjs";
6
+ import { orderRows, whereMatches } from "./sql-chunks.mjs";
7
+ //#region src/test-helpers/fake-database.ts
8
+ function withoutUndefined(values) {
9
+ return Object.fromEntries(Object.entries(values).filter((pair) => pair[1] !== void 0));
10
+ }
11
+ /** Create an in-memory database adapter for capture pipeline tests. */
12
+ function makeDatabase() {
13
+ const store = /* @__PURE__ */ new Map();
14
+ const rowsOf = (table) => {
15
+ let rowMap = store.get(table);
16
+ if (!rowMap) {
17
+ rowMap = /* @__PURE__ */ new Map();
18
+ store.set(table, rowMap);
19
+ }
20
+ return rowMap;
21
+ };
22
+ const insertRow = async (table, values) => {
23
+ const row = withoutUndefined(values);
24
+ const key = row["id"] ?? row["hash"];
25
+ rowsOf(table).set(key, row);
26
+ return row;
27
+ };
28
+ const updateRow = async (table, id, values) => {
29
+ const current = rowsOf(table).get(id);
30
+ if (current === void 0) throw new Error("row not found");
31
+ const merged = withoutUndefined({
32
+ ...current,
33
+ ...values
34
+ });
35
+ rowsOf(table).set(id, merged);
36
+ return merged;
37
+ };
38
+ const getRow = async (table, id) => {
39
+ const found = rowsOf(table).get(id);
40
+ if (found === void 0) return null;
41
+ return found;
42
+ };
43
+ const listRows = async (table, opts = {}) => {
44
+ let current = [...rowsOf(table).values()];
45
+ if (opts.where) {
46
+ const { where } = opts;
47
+ current = current.filter((row) => whereMatches(where, row, table));
48
+ }
49
+ if (opts.orderBy) current = orderRows(current, opts.orderBy, table);
50
+ if (opts.limit !== void 0) current = current.slice(0, clampListLimit(opts.limit));
51
+ return current;
52
+ };
53
+ const countRows = async (table, where) => {
54
+ return (await listRows(table, where ? { where } : {})).length;
55
+ };
56
+ const transactRows = async (fn) => {
57
+ const snapshot = /* @__PURE__ */ new Map();
58
+ for (const [table, rows] of store) snapshot.set(table, new Map([...rows].map(([id, row]) => [id, { ...row }])));
59
+ const tx = {
60
+ insert: insertRow,
61
+ update: updateRow,
62
+ get: getRow,
63
+ remove: async (table, id) => {
64
+ rowsOf(table).delete(id);
65
+ },
66
+ list: listRows,
67
+ count: countRows
68
+ };
69
+ try {
70
+ return await fn(tx);
71
+ } catch (error) {
72
+ store.clear();
73
+ for (const [table, rows] of snapshot) store.set(table, rows);
74
+ throw error;
75
+ }
76
+ };
77
+ return { db: {
78
+ metadata: {
79
+ name: "Fake Database",
80
+ version: "0.0.0",
81
+ kind: "memory",
82
+ category: "database"
83
+ },
84
+ tables: fakeSchema,
85
+ insert: insertRow,
86
+ update: updateRow,
87
+ get: getRow,
88
+ remove: async (table, id) => {
89
+ rowsOf(table).delete(id);
90
+ },
91
+ list: listRows,
92
+ count: countRows,
93
+ transact: transactRows,
94
+ all: async (_query) => {
95
+ const results = [];
96
+ for (const rows of store.values()) for (const row of rows.values()) results.push(row);
97
+ return results;
98
+ }
99
+ } };
100
+ }
101
+ //#endregion
102
+ export { makeDatabase };
103
+
104
+ //# sourceMappingURL=fake-database.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-database.mjs","names":[],"sources":["../../src/test-helpers/fake-database.ts"],"sourcesContent":["import type { SQL, Table } from \"drizzle-orm\";\nimport type { DatabaseAdapter, ListOptions, TxStore } from \"../adapters/database.ts\";\nimport { clampListLimit } from \"../adapters/database.ts\";\nimport { fakeSchema } from \"./fake-tables.ts\";\nimport { orderRows, whereMatches } from \"./sql-chunks.ts\";\n\nfunction withoutUndefined(values: unknown): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(values as Record<string, unknown>).filter((pair) => pair[1] !== undefined),\n );\n}\n\n// The in-memory fake back-fills Drizzle's inferred row types from raw maps\n// Without a driver, so the casts and await-free `async` methods are unavoidable.\n/* eslint-disable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n/** Create an in-memory database adapter for capture pipeline tests. */\nexport function makeDatabase(): { db: DatabaseAdapter } {\n const store = new Map<Table, Map<string, unknown>>();\n\n const rowsOf = (table: Table): Map<string, unknown> => {\n let rowMap = store.get(table);\n if (!rowMap) {\n rowMap = new Map();\n store.set(table, rowMap);\n }\n return rowMap;\n };\n\n const insertRow = async <T extends Table>(\n table: T,\n values: T[\"$inferInsert\"],\n ): Promise<T[\"$inferSelect\"]> => {\n const row = withoutUndefined(values);\n const key = (row[\"id\"] ?? row[\"hash\"]) as string;\n rowsOf(table).set(key, row);\n return row as T[\"$inferSelect\"];\n };\n\n const updateRow = async <T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]> => {\n const current = rowsOf(table).get(id) as Record<string, unknown> | undefined;\n if (current === undefined) {\n throw new Error(\"row not found\");\n }\n const merged = withoutUndefined({ ...current, ...values });\n rowsOf(table).set(id, merged);\n return merged as T[\"$inferSelect\"];\n };\n\n const getRow = async <T extends Table>(\n table: T,\n id: string,\n ): Promise<T[\"$inferSelect\"] | null> => {\n const found = rowsOf(table).get(id);\n if (found === undefined) {\n return null;\n }\n return found as T[\"$inferSelect\"];\n };\n\n const listRows = async <T extends Table>(\n table: T,\n opts: ListOptions = {},\n ): Promise<T[\"$inferSelect\"][]> => {\n let current = [...rowsOf(table).values()];\n if (opts.where) {\n const { where } = opts;\n current = current.filter((row) => whereMatches(where, row as Record<string, unknown>, table));\n }\n if (opts.orderBy) {\n current = orderRows(current, opts.orderBy, table);\n }\n if (opts.limit !== undefined) {\n current = current.slice(0, clampListLimit(opts.limit));\n }\n return current as T[\"$inferSelect\"][];\n };\n\n const countRows = async (table: Table, where?: SQL): Promise<number> => {\n const matching = await listRows(table, where ? { where } : {});\n return matching.length;\n };\n\n const transactRows = async <R>(fn: (tx: TxStore) => Promise<R>): Promise<R> => {\n const snapshot = new Map<Table, Map<string, unknown>>();\n for (const [table, rows] of store) {\n snapshot.set(\n table,\n new Map([...rows].map(([id, row]) => [id, { ...(row as Record<string, unknown>) }])),\n );\n }\n const tx: TxStore = {\n insert: insertRow,\n update: updateRow,\n get: getRow,\n remove: async (table, id) => {\n rowsOf(table).delete(id);\n },\n list: listRows,\n count: countRows,\n };\n try {\n return await fn(tx);\n } catch (error) {\n store.clear();\n for (const [table, rows] of snapshot) {\n store.set(table, rows);\n }\n throw error;\n }\n };\n\n const db: DatabaseAdapter = {\n metadata: { name: \"Fake Database\", version: \"0.0.0\", kind: \"memory\", category: \"database\" },\n tables: fakeSchema,\n insert: insertRow,\n update: updateRow,\n get: getRow,\n remove: async (table, id) => {\n rowsOf(table).delete(id);\n },\n list: listRows,\n count: countRows,\n transact: transactRows,\n all: async (_query: SQL) => {\n const results: Record<string, unknown>[] = [];\n for (const rows of store.values()) {\n for (const row of rows.values()) {\n results.push(row as Record<string, unknown>);\n }\n }\n return results as never[];\n },\n };\n return { db };\n}\n/* eslint-enable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n"],"mappings":";;;;;;;AAMA,SAAS,iBAAiB,QAA0C;CAClE,OAAO,OAAO,YACZ,OAAO,QAAQ,MAAiC,CAAC,CAAC,QAAQ,SAAS,KAAK,OAAO,KAAA,CAAS,CAC1F;AACF;;AAMA,SAAgB,eAAwC;CACtD,MAAM,wBAAQ,IAAI,IAAiC;CAEnD,MAAM,UAAU,UAAuC;EACrD,IAAI,SAAS,MAAM,IAAI,KAAK;EAC5B,IAAI,CAAC,QAAQ;GACX,yBAAS,IAAI,IAAI;GACjB,MAAM,IAAI,OAAO,MAAM;EACzB;EACA,OAAO;CACT;CAEA,MAAM,YAAY,OAChB,OACA,WAC+B;EAC/B,MAAM,MAAM,iBAAiB,MAAM;EACnC,MAAM,MAAO,IAAI,SAAS,IAAI;EAC9B,OAAO,KAAK,CAAC,CAAC,IAAI,KAAK,GAAG;EAC1B,OAAO;CACT;CAEA,MAAM,YAAY,OAChB,OACA,IACA,WAC+B;EAC/B,MAAM,UAAU,OAAO,KAAK,CAAC,CAAC,IAAI,EAAE;EACpC,IAAI,YAAY,KAAA,GACd,MAAM,IAAI,MAAM,eAAe;EAEjC,MAAM,SAAS,iBAAiB;GAAE,GAAG;GAAS,GAAG;EAAO,CAAC;EACzD,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,MAAM;EAC5B,OAAO;CACT;CAEA,MAAM,SAAS,OACb,OACA,OACsC;EACtC,MAAM,QAAQ,OAAO,KAAK,CAAC,CAAC,IAAI,EAAE;EAClC,IAAI,UAAU,KAAA,GACZ,OAAO;EAET,OAAO;CACT;CAEA,MAAM,WAAW,OACf,OACA,OAAoB,CAAC,MACY;EACjC,IAAI,UAAU,CAAC,GAAG,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC;EACxC,IAAI,KAAK,OAAO;GACd,MAAM,EAAE,UAAU;GAClB,UAAU,QAAQ,QAAQ,QAAQ,aAAa,OAAO,KAAgC,KAAK,CAAC;EAC9F;EACA,IAAI,KAAK,SACP,UAAU,UAAU,SAAS,KAAK,SAAS,KAAK;EAElD,IAAI,KAAK,UAAU,KAAA,GACjB,UAAU,QAAQ,MAAM,GAAG,eAAe,KAAK,KAAK,CAAC;EAEvD,OAAO;CACT;CAEA,MAAM,YAAY,OAAO,OAAc,UAAiC;EAEtE,QAAO,MADgB,SAAS,OAAO,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC,EAAA,CAC7C;CAClB;CAEA,MAAM,eAAe,OAAU,OAAgD;EAC7E,MAAM,2BAAW,IAAI,IAAiC;EACtD,KAAK,MAAM,CAAC,OAAO,SAAS,OAC1B,SAAS,IACP,OACA,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,EAAE,GAAI,IAAgC,CAAC,CAAC,CAAC,CACrF;EAEF,MAAM,KAAc;GAClB,QAAQ;GACR,QAAQ;GACR,KAAK;GACL,QAAQ,OAAO,OAAO,OAAO;IAC3B,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE;GACzB;GACA,MAAM;GACN,OAAO;EACT;EACA,IAAI;GACF,OAAO,MAAM,GAAG,EAAE;EACpB,SAAS,OAAO;GACd,MAAM,MAAM;GACZ,KAAK,MAAM,CAAC,OAAO,SAAS,UAC1B,MAAM,IAAI,OAAO,IAAI;GAEvB,MAAM;EACR;CACF;CAwBA,OAAO,EAAE,IAAA;EArBP,UAAU;GAAE,MAAM;GAAiB,SAAS;GAAS,MAAM;GAAU,UAAU;EAAW;EAC1F,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,QAAQ,OAAO,OAAO,OAAO;GAC3B,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE;EACzB;EACA,MAAM;EACN,OAAO;EACP,UAAU;EACV,KAAK,OAAO,WAAgB;GAC1B,MAAM,UAAqC,CAAC;GAC5C,KAAK,MAAM,QAAQ,MAAM,OAAO,GAC9B,KAAK,MAAM,OAAO,KAAK,OAAO,GAC5B,QAAQ,KAAK,GAA8B;GAG/C,OAAO;EACT;CAEQ,EAAE;AACd"}
@@ -0,0 +1,14 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { StorageAdapter } from "../adapter/storage.mjs";
4
+ //#region src/test-helpers/fake-storage.d.ts
5
+ /** Storage and database doubles used by the capture pipeline tests. */
6
+ interface FakeStorage {
7
+ storage: StorageAdapter;
8
+ objects: Map<string, Buffer>;
9
+ }
10
+ /** Create an in-memory storage adapter for capture pipeline tests. */
11
+ declare function makeStorage(): FakeStorage;
12
+ //#endregion
13
+ export { FakeStorage, makeStorage };
14
+ //# sourceMappingURL=fake-storage.d.mts.map
@@ -0,0 +1,49 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { Readable } from "node:stream";
5
+ //#region src/test-helpers/fake-storage.ts
6
+ /** Create an in-memory storage adapter for capture pipeline tests. */
7
+ function makeStorage() {
8
+ const objects = /* @__PURE__ */ new Map();
9
+ return {
10
+ storage: {
11
+ metadata: {
12
+ name: "Fake Storage",
13
+ version: "0.0.0",
14
+ kind: "memory",
15
+ category: "storage"
16
+ },
17
+ read: async (path) => {
18
+ const found = objects.get(path);
19
+ if (found === void 0) throw new Error(`no object at "${path}"`);
20
+ return await Promise.resolve(found);
21
+ },
22
+ write: async (path, data) => {
23
+ objects.set(path, Buffer.from(data));
24
+ await Promise.resolve();
25
+ },
26
+ delete: async (path) => {
27
+ objects.delete(path);
28
+ await Promise.resolve();
29
+ },
30
+ exists: async (path) => await Promise.resolve(objects.has(path)),
31
+ list: async (prefix) => await Promise.resolve([...objects.keys()].filter((key) => key.startsWith(prefix)).toSorted()),
32
+ writeStream: async (path, stream) => {
33
+ const chunks = [];
34
+ for await (const chunk of stream) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk));
35
+ objects.set(path, Buffer.concat(chunks));
36
+ },
37
+ readStream: async (path) => {
38
+ const found = objects.get(path);
39
+ if (found === void 0) throw new Error(`no object at "${path}"`);
40
+ return await Promise.resolve(Readable.from([found]));
41
+ }
42
+ },
43
+ objects
44
+ };
45
+ }
46
+ //#endregion
47
+ export { makeStorage };
48
+
49
+ //# sourceMappingURL=fake-storage.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fake-storage.mjs","names":[],"sources":["../../src/test-helpers/fake-storage.ts"],"sourcesContent":["import { Readable } from \"node:stream\";\nimport type { StorageAdapter } from \"../adapters/storage.ts\";\n\n/** Storage and database doubles used by the capture pipeline tests. */\nexport interface FakeStorage {\n storage: StorageAdapter;\n objects: Map<string, Buffer>;\n}\n\n/** Create an in-memory storage adapter for capture pipeline tests. */\nexport function makeStorage(): FakeStorage {\n const objects = new Map<string, Buffer>();\n const storage: StorageAdapter = {\n metadata: { name: \"Fake Storage\", version: \"0.0.0\", kind: \"memory\", category: \"storage\" },\n read: async (path) => {\n const found = objects.get(path);\n if (found === undefined) {\n throw new Error(`no object at \"${path}\"`);\n }\n return await Promise.resolve(found);\n },\n write: async (path, data) => {\n objects.set(path, Buffer.from(data));\n await Promise.resolve();\n },\n delete: async (path) => {\n objects.delete(path);\n await Promise.resolve();\n },\n exists: async (path) => await Promise.resolve(objects.has(path)),\n list: async (prefix) =>\n await Promise.resolve([...objects.keys()].filter((key) => key.startsWith(prefix)).toSorted()),\n writeStream: async (path, stream) => {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(\n typeof chunk === \"string\" ? Buffer.from(chunk) : Buffer.from(chunk as Uint8Array),\n );\n }\n objects.set(path, Buffer.concat(chunks));\n },\n readStream: async (path) => {\n const found = objects.get(path);\n if (found === undefined) {\n throw new Error(`no object at \"${path}\"`);\n }\n return await Promise.resolve(Readable.from([found]));\n },\n };\n return { storage, objects };\n}\n"],"mappings":";;;;;;AAUA,SAAgB,cAA2B;CACzC,MAAM,0BAAU,IAAI,IAAoB;CAsCxC,OAAO;EAAE,SAAA;GApCP,UAAU;IAAE,MAAM;IAAgB,SAAS;IAAS,MAAM;IAAU,UAAU;GAAU;GACxF,MAAM,OAAO,SAAS;IACpB,MAAM,QAAQ,QAAQ,IAAI,IAAI;IAC9B,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,iBAAiB,KAAK,EAAE;IAE1C,OAAO,MAAM,QAAQ,QAAQ,KAAK;GACpC;GACA,OAAO,OAAO,MAAM,SAAS;IAC3B,QAAQ,IAAI,MAAM,OAAO,KAAK,IAAI,CAAC;IACnC,MAAM,QAAQ,QAAQ;GACxB;GACA,QAAQ,OAAO,SAAS;IACtB,QAAQ,OAAO,IAAI;IACnB,MAAM,QAAQ,QAAQ;GACxB;GACA,QAAQ,OAAO,SAAS,MAAM,QAAQ,QAAQ,QAAQ,IAAI,IAAI,CAAC;GAC/D,MAAM,OAAO,WACX,MAAM,QAAQ,QAAQ,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,QAAQ,QAAQ,IAAI,WAAW,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;GAC9F,aAAa,OAAO,MAAM,WAAW;IACnC,MAAM,SAAmB,CAAC;IAC1B,WAAW,MAAM,SAAS,QACxB,OAAO,KACL,OAAO,UAAU,WAAW,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,KAAmB,CAClF;IAEF,QAAQ,IAAI,MAAM,OAAO,OAAO,MAAM,CAAC;GACzC;GACA,YAAY,OAAO,SAAS;IAC1B,MAAM,QAAQ,QAAQ,IAAI,IAAI;IAC9B,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,iBAAiB,KAAK,EAAE;IAE1C,OAAO,MAAM,QAAQ,QAAQ,SAAS,KAAK,CAAC,KAAK,CAAC,CAAC;GACrD;EAEa;EAAG;CAAQ;AAC5B"}
@@ -0,0 +1,276 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { Column, Table } from "drizzle-orm";
5
+ //#region src/test-helpers/fake-tables.ts
6
+ /**
7
+ * Dialect-free stub tables for the in-memory test fake.
8
+ *
9
+ * The fake never touches a driver: it only needs table handles whose columns
10
+ * carry the property → column-name mapping (`getTableColumns`) and flow
11
+ * through drizzle's expression builders (`eq`, `and`, `inArray`, `orderBy`)
12
+ * into the `sql-chunks.ts` matcher. Real `Column`/`Table` base classes from
13
+ * the `drizzle-orm` root (already a core dependency) satisfy both without
14
+ * pulling in any dialect package (`sqlite-core`, `pg-core`, …).
15
+ */
16
+ /** A column handle with driver passthrough mapping (the fake maps nothing). */
17
+ var FakeColumn = class extends Column {
18
+ getSQLType() {
19
+ return this.columnType;
20
+ }
21
+ };
22
+ const columnsSymbol = Table.Symbol.Columns;
23
+ function defineTable(name, columns) {
24
+ const table = new Table(name, void 0, name);
25
+ const handles = {};
26
+ for (const [property, dbName] of Object.entries(columns)) handles[property] = new FakeColumn(table, {
27
+ name: dbName,
28
+ keyAsName: false,
29
+ notNull: false,
30
+ default: void 0,
31
+ defaultFn: void 0,
32
+ onUpdateFn: void 0,
33
+ hasDefault: false,
34
+ primaryKey: false,
35
+ isUnique: false,
36
+ uniqueName: void 0,
37
+ uniqueType: void 0,
38
+ dataType: "string",
39
+ columnType: "FakeColumn",
40
+ generated: void 0,
41
+ generatedIdentity: void 0
42
+ });
43
+ table[columnsSymbol] = handles;
44
+ return table;
45
+ }
46
+ /** Stub schema bundled into the `Tables` map every fake serves. */
47
+ const fakeSchema = {
48
+ projects: defineTable("projects", {
49
+ id: "id",
50
+ name: "name",
51
+ slug: "slug",
52
+ gitRepository: "git_repository",
53
+ gitDefaultBranch: "git_default_branch",
54
+ pixelThreshold: "pixel_threshold",
55
+ maxDiffRatio: "max_diff_ratio",
56
+ publicBranchRegex: "public_branch_regex",
57
+ storybookMeta: "storybook_meta",
58
+ executePlay: "execute_play",
59
+ playTimeoutMs: "play_timeout_ms",
60
+ runA11y: "run_a11y",
61
+ browser: "browser",
62
+ viewports: "viewports",
63
+ automigrate: "automigrate",
64
+ createdAt: "created_at",
65
+ updatedAt: "updated_at"
66
+ }),
67
+ projectStatusConfigs: defineTable("project_status_configs", {
68
+ id: "id",
69
+ projectId: "project_id",
70
+ provider: "provider",
71
+ config: "config",
72
+ tokenEncrypted: "token_encrypted",
73
+ createdAt: "created_at",
74
+ updatedAt: "updated_at"
75
+ }),
76
+ builds: defineTable("builds", {
77
+ id: "id",
78
+ projectId: "project_id",
79
+ gitSha: "git_sha",
80
+ gitBranch: "git_branch",
81
+ isDefault: "is_default",
82
+ authorEmail: "author_email",
83
+ authorName: "author_name",
84
+ message: "message",
85
+ public: "public",
86
+ status: "status",
87
+ snapshotCount: "snapshot_count",
88
+ changedCount: "changed_count",
89
+ approvedCount: "approved_count",
90
+ rejectedCount: "rejected_count",
91
+ affectedOnly: "affected_only",
92
+ baselineSha: "baseline_sha",
93
+ changedFiles: "changed_files",
94
+ affectedImportPaths: "affected_import_paths",
95
+ createdAt: "created_at",
96
+ updatedAt: "updated_at"
97
+ }),
98
+ captureAttempts: defineTable("capture_attempts", {
99
+ id: "id",
100
+ projectId: "project_id",
101
+ buildId: "build_id",
102
+ attemptNo: "attempt_no",
103
+ status: "status",
104
+ error: "error",
105
+ reqId: "req_id",
106
+ storyCount: "story_count",
107
+ failedCount: "failed_count",
108
+ queuedAt: "queued_at",
109
+ startedAt: "started_at",
110
+ finishedAt: "finished_at",
111
+ createdAt: "created_at",
112
+ updatedAt: "updated_at"
113
+ }),
114
+ captureLogs: defineTable("capture_logs", {
115
+ id: "id",
116
+ projectId: "project_id",
117
+ buildId: "build_id",
118
+ attemptId: "attempt_id",
119
+ seq: "seq",
120
+ level: "level",
121
+ message: "message",
122
+ fields: "fields",
123
+ createdAt: "created_at"
124
+ }),
125
+ snapshots: defineTable("snapshots", {
126
+ id: "id",
127
+ projectId: "project_id",
128
+ buildId: "build_id",
129
+ storyId: "story_id",
130
+ storyName: "story_name",
131
+ storyTitle: "story_title",
132
+ storyImportPath: "story_import_path",
133
+ viewportName: "viewport_name",
134
+ viewportWidth: "viewport_width",
135
+ viewportHeight: "viewport_height",
136
+ screenshotPath: "screenshot_path",
137
+ diffPath: "diff_path",
138
+ diffPixels: "diff_pixels",
139
+ diffRatio: "diff_ratio",
140
+ diffPassed: "diff_passed",
141
+ status: "status",
142
+ reviewedBy: "reviewed_by",
143
+ reviewedAt: "reviewed_at",
144
+ infraHash: "infra_hash",
145
+ inherited: "inherited",
146
+ baselineId: "baseline_id",
147
+ baselineVersion: "baseline_version",
148
+ createdAt: "created_at",
149
+ updatedAt: "updated_at"
150
+ }),
151
+ baselines: defineTable("baselines", {
152
+ id: "id",
153
+ projectId: "project_id",
154
+ storyId: "story_id",
155
+ viewportName: "viewport_name",
156
+ branch: "branch",
157
+ snapshotId: "snapshot_id",
158
+ screenshotPath: "screenshot_path",
159
+ infraHash: "infra_hash",
160
+ createdAt: "created_at",
161
+ updatedAt: "updated_at"
162
+ }),
163
+ comments: defineTable("comments", {
164
+ id: "id",
165
+ projectId: "project_id",
166
+ buildId: "build_id",
167
+ snapshotId: "snapshot_id",
168
+ userId: "user_id",
169
+ body: "body",
170
+ parentId: "parent_id",
171
+ resolved: "resolved",
172
+ createdAt: "created_at",
173
+ updatedAt: "updated_at"
174
+ }),
175
+ labelTypes: defineTable("label_types", {
176
+ id: "id",
177
+ projectId: "project_id",
178
+ key: "key",
179
+ name: "name",
180
+ linkTemplate: "link_template",
181
+ color: "color",
182
+ createdAt: "created_at"
183
+ }),
184
+ buildLabels: defineTable("build_labels", {
185
+ id: "id",
186
+ projectId: "project_id",
187
+ buildId: "build_id",
188
+ typeKey: "type_key",
189
+ value: "value",
190
+ createdAt: "created_at"
191
+ }),
192
+ tokens: defineTable("tokens", {
193
+ id: "id",
194
+ projectId: "project_id",
195
+ name: "name",
196
+ hash: "hash",
197
+ userId: "user_id",
198
+ lastUsedAt: "last_used_at",
199
+ createdAt: "created_at"
200
+ }),
201
+ webhooks: defineTable("webhooks", {
202
+ id: "id",
203
+ projectId: "project_id",
204
+ url: "url",
205
+ secretEncrypted: "secret_encrypted",
206
+ events: "events",
207
+ createdAt: "created_at",
208
+ updatedAt: "updated_at"
209
+ }),
210
+ users: defineTable("users", {
211
+ id: "id",
212
+ email: "email",
213
+ name: "name",
214
+ avatarUrl: "avatar_url",
215
+ role: "role",
216
+ lastLoginAt: "last_login_at",
217
+ createdAt: "created_at",
218
+ passwordHash: "password_hash",
219
+ displayNameOverride: "display_name_override",
220
+ authProvider: "auth_provider",
221
+ disabled: "disabled"
222
+ }),
223
+ userInviteTokens: defineTable("user_invite_tokens", {
224
+ id: "id",
225
+ userId: "user_id",
226
+ tokenHash: "token_hash",
227
+ expiresAt: "expires_at",
228
+ usedAt: "used_at",
229
+ createdAt: "created_at"
230
+ }),
231
+ projectMembers: defineTable("project_members", {
232
+ id: "id",
233
+ projectId: "project_id",
234
+ userId: "user_id",
235
+ role: "role",
236
+ source: "source",
237
+ createdAt: "created_at"
238
+ }),
239
+ projectGroupMappings: defineTable("project_group_mappings", {
240
+ id: "id",
241
+ projectId: "project_id",
242
+ groupName: "group_name",
243
+ role: "role",
244
+ createdAt: "created_at"
245
+ }),
246
+ notificationChannels: defineTable("notification_channels", {
247
+ id: "id",
248
+ projectId: "project_id",
249
+ provider: "provider",
250
+ config: "config",
251
+ secretEncrypted: "secret_encrypted",
252
+ events: "events",
253
+ enabled: "enabled",
254
+ createdAt: "created_at",
255
+ updatedAt: "updated_at"
256
+ }),
257
+ notificationSubscriptions: defineTable("notification_subscriptions", {
258
+ id: "id",
259
+ projectId: "project_id",
260
+ userId: "user_id",
261
+ events: "events",
262
+ via: "via",
263
+ enabled: "enabled",
264
+ createdAt: "created_at"
265
+ }),
266
+ contentRefs: defineTable("content_refs", {
267
+ hash: "hash",
268
+ refCount: "ref_count",
269
+ lastSeenAt: "last_seen_at",
270
+ createdAt: "created_at"
271
+ })
272
+ };
273
+ //#endregion
274
+ export { fakeSchema };
275
+
276
+ //# sourceMappingURL=fake-tables.mjs.map