@storyshelf/core 0.3.2 → 0.5.4

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 -70
  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 @@
1
+ {"version":3,"file":"fake-tables.mjs","names":[],"sources":["../../src/test-helpers/fake-tables.ts"],"sourcesContent":["/**\n * Dialect-free stub tables for the in-memory test fake.\n *\n * The fake never touches a driver: it only needs table handles whose columns\n * carry the property → column-name mapping (`getTableColumns`) and flow\n * through drizzle's expression builders (`eq`, `and`, `inArray`, `orderBy`)\n * into the `sql-chunks.ts` matcher. Real `Column`/`Table` base classes from\n * the `drizzle-orm` root (already a core dependency) satisfy both without\n * pulling in any dialect package (`sqlite-core`, `pg-core`, …).\n */\nimport { Column, Table } from \"drizzle-orm\";\nimport type { Tables } from \"../adapters/database.ts\";\n\n/** A column handle with driver passthrough mapping (the fake maps nothing). */\nclass FakeColumn extends Column {\n override getSQLType(): string {\n return this.columnType;\n }\n}\n\n// `Table.Symbol` is runtime-only (`@internal`, absent from the public types).\nconst columnsSymbol = (Table as unknown as { Symbol: { Columns: symbol } }).Symbol.Columns;\n\nfunction defineTable(name: string, columns: Record<string, string>): Table {\n const table = new Table(name, undefined, name);\n const handles: Record<string, FakeColumn> = {};\n for (const [property, dbName] of Object.entries(columns)) {\n handles[property] = new FakeColumn(table, {\n name: dbName,\n keyAsName: false,\n notNull: false,\n default: undefined,\n defaultFn: undefined,\n onUpdateFn: undefined,\n hasDefault: false,\n primaryKey: false,\n isUnique: false,\n uniqueName: undefined,\n uniqueType: undefined,\n dataType: \"string\",\n columnType: \"FakeColumn\",\n generated: undefined,\n generatedIdentity: undefined,\n });\n }\n (table as unknown as Record<symbol, unknown>)[columnsSymbol] = handles;\n return table;\n}\n\n// Stub tables matching the real schema's property -> column mapping.\n// No constraints or defaults — just names for whereMatches/orderRows.\nconst projects = defineTable(\"projects\", {\n id: \"id\",\n name: \"name\",\n slug: \"slug\",\n gitRepository: \"git_repository\",\n gitDefaultBranch: \"git_default_branch\",\n pixelThreshold: \"pixel_threshold\",\n maxDiffRatio: \"max_diff_ratio\",\n publicBranchRegex: \"public_branch_regex\",\n storybookMeta: \"storybook_meta\",\n executePlay: \"execute_play\",\n playTimeoutMs: \"play_timeout_ms\",\n runA11y: \"run_a11y\",\n browser: \"browser\",\n viewports: \"viewports\",\n automigrate: \"automigrate\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst projectStatusConfigs = defineTable(\"project_status_configs\", {\n id: \"id\",\n projectId: \"project_id\",\n provider: \"provider\",\n config: \"config\",\n tokenEncrypted: \"token_encrypted\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst builds = defineTable(\"builds\", {\n id: \"id\",\n projectId: \"project_id\",\n gitSha: \"git_sha\",\n gitBranch: \"git_branch\",\n isDefault: \"is_default\",\n authorEmail: \"author_email\",\n authorName: \"author_name\",\n message: \"message\",\n public: \"public\",\n status: \"status\",\n snapshotCount: \"snapshot_count\",\n changedCount: \"changed_count\",\n approvedCount: \"approved_count\",\n rejectedCount: \"rejected_count\",\n affectedOnly: \"affected_only\",\n baselineSha: \"baseline_sha\",\n changedFiles: \"changed_files\",\n affectedImportPaths: \"affected_import_paths\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst captureAttempts = defineTable(\"capture_attempts\", {\n id: \"id\",\n projectId: \"project_id\",\n buildId: \"build_id\",\n attemptNo: \"attempt_no\",\n status: \"status\",\n error: \"error\",\n reqId: \"req_id\",\n storyCount: \"story_count\",\n failedCount: \"failed_count\",\n queuedAt: \"queued_at\",\n startedAt: \"started_at\",\n finishedAt: \"finished_at\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst captureLogs = defineTable(\"capture_logs\", {\n id: \"id\",\n projectId: \"project_id\",\n buildId: \"build_id\",\n attemptId: \"attempt_id\",\n seq: \"seq\",\n level: \"level\",\n message: \"message\",\n fields: \"fields\",\n createdAt: \"created_at\",\n});\n\nconst snapshots = defineTable(\"snapshots\", {\n id: \"id\",\n projectId: \"project_id\",\n buildId: \"build_id\",\n storyId: \"story_id\",\n storyName: \"story_name\",\n storyTitle: \"story_title\",\n storyImportPath: \"story_import_path\",\n viewportName: \"viewport_name\",\n viewportWidth: \"viewport_width\",\n viewportHeight: \"viewport_height\",\n screenshotPath: \"screenshot_path\",\n diffPath: \"diff_path\",\n diffPixels: \"diff_pixels\",\n diffRatio: \"diff_ratio\",\n diffPassed: \"diff_passed\",\n status: \"status\",\n reviewedBy: \"reviewed_by\",\n reviewedAt: \"reviewed_at\",\n infraHash: \"infra_hash\",\n inherited: \"inherited\",\n baselineId: \"baseline_id\",\n baselineVersion: \"baseline_version\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst baselines = defineTable(\"baselines\", {\n id: \"id\",\n projectId: \"project_id\",\n storyId: \"story_id\",\n viewportName: \"viewport_name\",\n branch: \"branch\",\n snapshotId: \"snapshot_id\",\n screenshotPath: \"screenshot_path\",\n infraHash: \"infra_hash\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst comments = defineTable(\"comments\", {\n id: \"id\",\n projectId: \"project_id\",\n buildId: \"build_id\",\n snapshotId: \"snapshot_id\",\n userId: \"user_id\",\n body: \"body\",\n parentId: \"parent_id\",\n resolved: \"resolved\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst labelTypes = defineTable(\"label_types\", {\n id: \"id\",\n projectId: \"project_id\",\n key: \"key\",\n name: \"name\",\n linkTemplate: \"link_template\",\n color: \"color\",\n createdAt: \"created_at\",\n});\n\nconst buildLabels = defineTable(\"build_labels\", {\n id: \"id\",\n projectId: \"project_id\",\n buildId: \"build_id\",\n typeKey: \"type_key\",\n value: \"value\",\n createdAt: \"created_at\",\n});\n\nconst tokens = defineTable(\"tokens\", {\n id: \"id\",\n projectId: \"project_id\",\n name: \"name\",\n hash: \"hash\",\n userId: \"user_id\",\n lastUsedAt: \"last_used_at\",\n createdAt: \"created_at\",\n});\n\nconst webhooks = defineTable(\"webhooks\", {\n id: \"id\",\n projectId: \"project_id\",\n url: \"url\",\n secretEncrypted: \"secret_encrypted\",\n events: \"events\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst users = defineTable(\"users\", {\n id: \"id\",\n email: \"email\",\n name: \"name\",\n avatarUrl: \"avatar_url\",\n role: \"role\",\n lastLoginAt: \"last_login_at\",\n createdAt: \"created_at\",\n passwordHash: \"password_hash\",\n displayNameOverride: \"display_name_override\",\n authProvider: \"auth_provider\",\n disabled: \"disabled\",\n});\n\nconst userInviteTokens = defineTable(\"user_invite_tokens\", {\n id: \"id\",\n userId: \"user_id\",\n tokenHash: \"token_hash\",\n expiresAt: \"expires_at\",\n usedAt: \"used_at\",\n createdAt: \"created_at\",\n});\n\nconst projectMembers = defineTable(\"project_members\", {\n id: \"id\",\n projectId: \"project_id\",\n userId: \"user_id\",\n role: \"role\",\n source: \"source\",\n createdAt: \"created_at\",\n});\n\nconst projectGroupMappings = defineTable(\"project_group_mappings\", {\n id: \"id\",\n projectId: \"project_id\",\n groupName: \"group_name\",\n role: \"role\",\n createdAt: \"created_at\",\n});\n\nconst notificationChannels = defineTable(\"notification_channels\", {\n id: \"id\",\n projectId: \"project_id\",\n provider: \"provider\",\n config: \"config\",\n secretEncrypted: \"secret_encrypted\",\n events: \"events\",\n enabled: \"enabled\",\n createdAt: \"created_at\",\n updatedAt: \"updated_at\",\n});\n\nconst notificationSubscriptions = defineTable(\"notification_subscriptions\", {\n id: \"id\",\n projectId: \"project_id\",\n userId: \"user_id\",\n events: \"events\",\n via: \"via\",\n enabled: \"enabled\",\n createdAt: \"created_at\",\n});\n\nconst contentRefs = defineTable(\"content_refs\", {\n hash: \"hash\",\n refCount: \"ref_count\",\n lastSeenAt: \"last_seen_at\",\n createdAt: \"created_at\",\n});\n\n/** Stub schema bundled into the `Tables` map every fake serves. */\nexport const fakeSchema: Tables = {\n projects,\n projectStatusConfigs,\n builds,\n captureAttempts,\n captureLogs,\n snapshots,\n baselines,\n comments,\n labelTypes,\n buildLabels,\n tokens,\n webhooks,\n users,\n userInviteTokens,\n projectMembers,\n projectGroupMappings,\n notificationChannels,\n notificationSubscriptions,\n contentRefs,\n};\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { GitHostProvider } from "../adapter/git-host.mjs";
4
+ //#region src/test-helpers/git-contract.d.ts
5
+ /** Build the provider under test (sync or async factories both work). */
6
+ type GitFactory = () => GitHostProvider | Promise<GitHostProvider>;
7
+ /** Run the git-host contract against a factory. */
8
+ declare function gitContractSuite(label: string, make: GitFactory): void;
9
+ //#endregion
10
+ export { GitFactory, gitContractSuite };
11
+ //# sourceMappingURL=git-contract.d.mts.map
@@ -0,0 +1,34 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { describe, expect, it } from "vitest";
5
+ //#region src/test-helpers/git-contract.ts
6
+ /**
7
+ * Published git-host contract suite for first- and third-party providers.
8
+ *
9
+ * Structural conformance (identity, descriptor, config schema). Status
10
+ * posting stays per-package behind faked transports.
11
+ */
12
+ /** Run the git-host contract against a factory. */
13
+ function gitContractSuite(label, make) {
14
+ describe(`git-host contract: ${label}`, () => {
15
+ it("exposes git-host metadata with a config schema", async () => {
16
+ const provider = await make();
17
+ expect(provider.metadata.category).toBe("git-host");
18
+ expect(provider.metadata.kind.length).toBeGreaterThan(0);
19
+ expect(typeof provider.metadata.schema.parse).toBe("function");
20
+ });
21
+ it("exposes the create descriptor", async () => {
22
+ const provider = await make();
23
+ expect(typeof provider.create).toBe("function");
24
+ });
25
+ it("validates channel config through a real schema", async () => {
26
+ const result = (await make()).metadata.schema.safeParse({});
27
+ expect(typeof result.success).toBe("boolean");
28
+ });
29
+ });
30
+ }
31
+ //#endregion
32
+ export { gitContractSuite };
33
+
34
+ //# sourceMappingURL=git-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-contract.mjs","names":[],"sources":["../../src/test-helpers/git-contract.ts"],"sourcesContent":["/**\n * Published git-host contract suite for first- and third-party providers.\n *\n * Structural conformance (identity, descriptor, config schema). Status\n * posting stays per-package behind faked transports.\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { GitHostProvider } from \"../adapters/git-host/index.ts\";\n\n/** Build the provider under test (sync or async factories both work). */\nexport type GitFactory = () => GitHostProvider | Promise<GitHostProvider>;\n\n/** Run the git-host contract against a factory. */\nexport function gitContractSuite(label: string, make: GitFactory): void {\n describe(`git-host contract: ${label}`, () => {\n it(\"exposes git-host metadata with a config schema\", async () => {\n const provider = await make();\n expect(provider.metadata.category).toBe(\"git-host\");\n expect(provider.metadata.kind.length).toBeGreaterThan(0);\n expect(typeof provider.metadata.schema.parse).toBe(\"function\");\n });\n\n it(\"exposes the create descriptor\", async () => {\n const provider = await make();\n expect(typeof provider.create).toBe(\"function\");\n });\n\n it(\"validates channel config through a real schema\", async () => {\n const provider = await make();\n const result = provider.metadata.schema.safeParse({});\n expect(typeof result.success).toBe(\"boolean\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,iBAAiB,OAAe,MAAwB;CACtE,SAAS,sBAAsB,eAAe;EAC5C,GAAG,kDAAkD,YAAY;GAC/D,MAAM,WAAW,MAAM,KAAK;GAC5B,OAAO,SAAS,SAAS,QAAQ,CAAC,CAAC,KAAK,UAAU;GAClD,OAAO,SAAS,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;GACvD,OAAO,OAAO,SAAS,SAAS,OAAO,KAAK,CAAC,CAAC,KAAK,UAAU;EAC/D,CAAC;EAED,GAAG,iCAAiC,YAAY;GAC9C,MAAM,WAAW,MAAM,KAAK;GAC5B,OAAO,OAAO,SAAS,MAAM,CAAC,CAAC,KAAK,UAAU;EAChD,CAAC;EAED,GAAG,kDAAkD,YAAY;GAE/D,MAAM,UAAS,MADQ,KAAK,EAAA,CACJ,SAAS,OAAO,UAAU,CAAC,CAAC;GACpD,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,SAAS;EAC9C,CAAC;CACH,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { NotifierProvider } from "../adapters/notifier/provider.mjs";
4
+ //#region src/test-helpers/notifier-contract.d.ts
5
+ /** Build the provider under test (sync or async factories both work). */
6
+ type NotifierFactory = () => NotifierProvider | Promise<NotifierProvider>;
7
+ /** Run the notifier contract against a factory. */
8
+ declare function notifierContractSuite(label: string, make: NotifierFactory): void;
9
+ //#endregion
10
+ export { NotifierFactory, notifierContractSuite };
11
+ //# sourceMappingURL=notifier-contract.d.mts.map
@@ -0,0 +1,34 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { describe, expect, it } from "vitest";
5
+ //#region src/test-helpers/notifier-contract.ts
6
+ /**
7
+ * Published notifier contract suite for first- and third-party providers.
8
+ *
9
+ * Structural conformance (identity, descriptor, config schema). Message
10
+ * delivery stays per-package behind faked transports.
11
+ */
12
+ /** Run the notifier contract against a factory. */
13
+ function notifierContractSuite(label, make) {
14
+ describe(`notifier contract: ${label}`, () => {
15
+ it("exposes notifier metadata with a config schema", async () => {
16
+ const provider = await make();
17
+ expect(provider.metadata.category).toBe("notifier");
18
+ expect(provider.metadata.kind.length).toBeGreaterThan(0);
19
+ expect(typeof provider.metadata.schema.parse).toBe("function");
20
+ });
21
+ it("exposes the create descriptor", async () => {
22
+ const provider = await make();
23
+ expect(typeof provider.create).toBe("function");
24
+ });
25
+ it("validates channel config through a real schema", async () => {
26
+ const result = (await make()).metadata.schema.safeParse({});
27
+ expect(typeof result.success).toBe("boolean");
28
+ });
29
+ });
30
+ }
31
+ //#endregion
32
+ export { notifierContractSuite };
33
+
34
+ //# sourceMappingURL=notifier-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier-contract.mjs","names":[],"sources":["../../src/test-helpers/notifier-contract.ts"],"sourcesContent":["/**\n * Published notifier contract suite for first- and third-party providers.\n *\n * Structural conformance (identity, descriptor, config schema). Message\n * delivery stays per-package behind faked transports.\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { NotifierProvider } from \"../adapters/notifier/provider.ts\";\n\n/** Build the provider under test (sync or async factories both work). */\nexport type NotifierFactory = () => NotifierProvider | Promise<NotifierProvider>;\n\n/** Run the notifier contract against a factory. */\nexport function notifierContractSuite(label: string, make: NotifierFactory): void {\n describe(`notifier contract: ${label}`, () => {\n it(\"exposes notifier metadata with a config schema\", async () => {\n const provider = await make();\n expect(provider.metadata.category).toBe(\"notifier\");\n expect(provider.metadata.kind.length).toBeGreaterThan(0);\n expect(typeof provider.metadata.schema.parse).toBe(\"function\");\n });\n\n it(\"exposes the create descriptor\", async () => {\n const provider = await make();\n expect(typeof provider.create).toBe(\"function\");\n });\n\n it(\"validates channel config through a real schema\", async () => {\n const provider = await make();\n const result = provider.metadata.schema.safeParse({});\n expect(typeof result.success).toBe(\"boolean\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,sBAAsB,OAAe,MAA6B;CAChF,SAAS,sBAAsB,eAAe;EAC5C,GAAG,kDAAkD,YAAY;GAC/D,MAAM,WAAW,MAAM,KAAK;GAC5B,OAAO,SAAS,SAAS,QAAQ,CAAC,CAAC,KAAK,UAAU;GAClD,OAAO,SAAS,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;GACvD,OAAO,OAAO,SAAS,SAAS,OAAO,KAAK,CAAC,CAAC,KAAK,UAAU;EAC/D,CAAC;EAED,GAAG,iCAAiC,YAAY;GAC9C,MAAM,WAAW,MAAM,KAAK;GAC5B,OAAO,OAAO,SAAS,MAAM,CAAC,CAAC,KAAK,UAAU;EAChD,CAAC;EAED,GAAG,kDAAkD,YAAY;GAE/D,MAAM,UAAS,MADQ,KAAK,EAAA,CACJ,SAAS,OAAO,UAAU,CAAC,CAAC;GACpD,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,SAAS;EAC9C,CAAC;CACH,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { CaptureQueue } from "../adapter/capture-queue.mjs";
4
+ //#region src/test-helpers/queue-contract.d.ts
5
+ /** Build the adapter under test (sync or async factories both work). */
6
+ type QueueFactory = () => CaptureQueue | Promise<CaptureQueue>;
7
+ /** Run the queue contract against a factory. */
8
+ declare function queueContractSuite(label: string, make: QueueFactory): void;
9
+ //#endregion
10
+ export { QueueFactory, queueContractSuite };
11
+ //# sourceMappingURL=queue-contract.d.mts.map
@@ -0,0 +1,64 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { describe, expect, it } from "vitest";
5
+ //#region src/test-helpers/queue-contract.ts
6
+ /**
7
+ * Published queue contract suite for first- and third-party adapters.
8
+ *
9
+ * A package proves conformance in one line from its own vitest file:
10
+ *
11
+ * ```ts
12
+ * import { queueContractSuite } from "@storyshelf/core/test-helpers";
13
+ * queueContractSuite("sqs", () => createSqsCaptureQueue({ queueUrl, client: fake }));
14
+ * ```
15
+ *
16
+ * Behavioral cases (enqueue/status/active/recent) need a fake transport that
17
+ * answers realistically; structural cases (poll extension rule) run against
18
+ * any factory.
19
+ */
20
+ /** Run the queue contract against a factory. */
21
+ function queueContractSuite(label, make) {
22
+ describe(`queue contract: ${label}`, () => {
23
+ it("exposes capture-queue metadata", async () => {
24
+ const queue = await make();
25
+ expect(queue.metadata.category).toBe("capture-queue");
26
+ expect(queue.metadata.kind.length).toBeGreaterThan(0);
27
+ });
28
+ it("keeps the poll extension all-or-nothing", async () => {
29
+ const record = await make();
30
+ const present = [
31
+ "poll",
32
+ "ack",
33
+ "nack"
34
+ ].filter((method) => record[method] !== void 0);
35
+ expect([0, 3]).toContain(present.length);
36
+ for (const method of present) expect(typeof record[method]).toBe("function");
37
+ });
38
+ it("tracks an enqueued build through status/active/recent", async () => {
39
+ const queue = await make();
40
+ await queue.enqueue({ buildId: "b-contract-1" });
41
+ const entry = await queue.status("b-contract-1");
42
+ expect(entry?.buildId).toBe("b-contract-1");
43
+ expect(["queued", "running"]).toContain(entry?.status);
44
+ expect((await queue.active()).map((job) => job.buildId)).toContain("b-contract-1");
45
+ expect((await queue.recent(10)).map((job) => job.buildId)).toContain("b-contract-1");
46
+ expect(await queue.status("b-missing")).toBeNull();
47
+ });
48
+ it("keeps lifecycle idempotent when present", async () => {
49
+ const queue = await make();
50
+ if (queue.lifecycle === void 0) {
51
+ expect(queue.lifecycle).toBeUndefined();
52
+ return;
53
+ }
54
+ await queue.lifecycle.setup({});
55
+ await queue.lifecycle.setup({});
56
+ await queue.lifecycle.teardown();
57
+ await expect(queue.lifecycle.teardown()).resolves.toBeUndefined();
58
+ });
59
+ });
60
+ }
61
+ //#endregion
62
+ export { queueContractSuite };
63
+
64
+ //# sourceMappingURL=queue-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue-contract.mjs","names":[],"sources":["../../src/test-helpers/queue-contract.ts"],"sourcesContent":["/**\n * Published queue contract suite for first- and third-party adapters.\n *\n * A package proves conformance in one line from its own vitest file:\n *\n * ```ts\n * import { queueContractSuite } from \"@storyshelf/core/test-helpers\";\n * queueContractSuite(\"sqs\", () => createSqsCaptureQueue({ queueUrl, client: fake }));\n * ```\n *\n * Behavioral cases (enqueue/status/active/recent) need a fake transport that\n * answers realistically; structural cases (poll extension rule) run against\n * any factory.\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { CaptureQueue } from \"../adapters/capture-queue.ts\";\n\n/** Build the adapter under test (sync or async factories both work). */\nexport type QueueFactory = () => CaptureQueue | Promise<CaptureQueue>;\n\n/** Run the queue contract against a factory. */\nexport function queueContractSuite(label: string, make: QueueFactory): void {\n describe(`queue contract: ${label}`, () => {\n it(\"exposes capture-queue metadata\", async () => {\n const queue = await make();\n expect(queue.metadata.category).toBe(\"capture-queue\");\n expect(queue.metadata.kind.length).toBeGreaterThan(0);\n });\n\n it(\"keeps the poll extension all-or-nothing\", async () => {\n const queue = await make();\n const record = queue as unknown as Record<string, unknown>;\n const present = [\"poll\", \"ack\", \"nack\"].filter((method) => record[method] !== undefined);\n expect([0, 3]).toContain(present.length);\n for (const method of present) {\n expect(typeof record[method]).toBe(\"function\");\n }\n });\n\n it(\"tracks an enqueued build through status/active/recent\", async () => {\n const queue = await make();\n await queue.enqueue({ buildId: \"b-contract-1\" });\n const entry = await queue.status(\"b-contract-1\");\n expect(entry?.buildId).toBe(\"b-contract-1\");\n // Remote transports report \"queued\" until a worker polls; in-process\n // queues may already report \"running\".\n expect([\"queued\", \"running\"]).toContain(entry?.status);\n expect((await queue.active()).map((job) => job.buildId)).toContain(\"b-contract-1\");\n expect((await queue.recent(10)).map((job) => job.buildId)).toContain(\"b-contract-1\");\n expect(await queue.status(\"b-missing\")).toBeNull();\n });\n\n it(\"keeps lifecycle idempotent when present\", async () => {\n const queue = await make();\n if (queue.lifecycle === undefined) {\n expect(queue.lifecycle).toBeUndefined();\n return;\n }\n await queue.lifecycle.setup({} as never);\n await queue.lifecycle.setup({} as never);\n await queue.lifecycle.teardown();\n await expect(queue.lifecycle.teardown()).resolves.toBeUndefined();\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,mBAAmB,OAAe,MAA0B;CAC1E,SAAS,mBAAmB,eAAe;EACzC,GAAG,kCAAkC,YAAY;GAC/C,MAAM,QAAQ,MAAM,KAAK;GACzB,OAAO,MAAM,SAAS,QAAQ,CAAC,CAAC,KAAK,eAAe;GACpD,OAAO,MAAM,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACtD,CAAC;EAED,GAAG,2CAA2C,YAAY;GAExD,MAAM,SAAS,MADK,KAAK;GAEzB,MAAM,UAAU;IAAC;IAAQ;IAAO;GAAM,CAAC,CAAC,QAAQ,WAAW,OAAO,YAAY,KAAA,CAAS;GACvF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,QAAQ,MAAM;GACvC,KAAK,MAAM,UAAU,SACnB,OAAO,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,UAAU;EAEjD,CAAC;EAED,GAAG,yDAAyD,YAAY;GACtE,MAAM,QAAQ,MAAM,KAAK;GACzB,MAAM,MAAM,QAAQ,EAAE,SAAS,eAAe,CAAC;GAC/C,MAAM,QAAQ,MAAM,MAAM,OAAO,cAAc;GAC/C,OAAO,OAAO,OAAO,CAAC,CAAC,KAAK,cAAc;GAG1C,OAAO,CAAC,UAAU,SAAS,CAAC,CAAC,CAAC,UAAU,OAAO,MAAM;GACrD,QAAQ,MAAM,MAAM,OAAO,EAAA,CAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,UAAU,cAAc;GACjF,QAAQ,MAAM,MAAM,OAAO,EAAE,EAAA,CAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,UAAU,cAAc;GACnF,OAAO,MAAM,MAAM,OAAO,WAAW,CAAC,CAAC,CAAC,SAAS;EACnD,CAAC;EAED,GAAG,2CAA2C,YAAY;GACxD,MAAM,QAAQ,MAAM,KAAK;GACzB,IAAI,MAAM,cAAc,KAAA,GAAW;IACjC,OAAO,MAAM,SAAS,CAAC,CAAC,cAAc;IACtC;GACF;GACA,MAAM,MAAM,UAAU,MAAM,CAAC,CAAU;GACvC,MAAM,MAAM,UAAU,MAAM,CAAC,CAAU;GACvC,MAAM,MAAM,UAAU,SAAS;GAC/B,MAAM,OAAO,MAAM,UAAU,SAAS,CAAC,CAAC,CAAC,SAAS,cAAc;EAClE,CAAC;CACH,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { CaptureRunner } from "../adapter/capture-runner.mjs";
4
+ //#region src/test-helpers/runner-contract.d.ts
5
+ /** Build the adapter under test (sync or async factories both work). */
6
+ type RunnerFactory = () => CaptureRunner | Promise<CaptureRunner>;
7
+ /** Run the runner contract against a factory. */
8
+ declare function runnerContractSuite(label: string, make: RunnerFactory): void;
9
+ //#endregion
10
+ export { RunnerFactory, runnerContractSuite };
11
+ //# sourceMappingURL=runner-contract.d.mts.map
@@ -0,0 +1,32 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { describe, expect, it } from "vitest";
5
+ //#region src/test-helpers/runner-contract.ts
6
+ /**
7
+ * Published runner contract suite for first- and third-party adapters.
8
+ *
9
+ * Structural conformance (identity, render/cancel presence). Behavioral
10
+ * rendering stays per-package behind real or mocked browsers — the
11
+ * orchestrator owns timeouts, byte guards, and failure caps, so runners
12
+ * only promise to return PNG buffers and honor `cancel`.
13
+ */
14
+ /** Run the runner contract against a factory. */
15
+ function runnerContractSuite(label, make) {
16
+ describe(`runner contract: ${label}`, () => {
17
+ it("exposes capture-runner metadata", async () => {
18
+ const runner = await make();
19
+ expect(runner.metadata.category).toBe("capture-runner");
20
+ expect(runner.metadata.kind.length).toBeGreaterThan(0);
21
+ });
22
+ it("exposes render and cancel", async () => {
23
+ const runner = await make();
24
+ expect(typeof runner.render).toBe("function");
25
+ expect(typeof runner.cancel).toBe("function");
26
+ });
27
+ });
28
+ }
29
+ //#endregion
30
+ export { runnerContractSuite };
31
+
32
+ //# sourceMappingURL=runner-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-contract.mjs","names":[],"sources":["../../src/test-helpers/runner-contract.ts"],"sourcesContent":["/**\n * Published runner contract suite for first- and third-party adapters.\n *\n * Structural conformance (identity, render/cancel presence). Behavioral\n * rendering stays per-package behind real or mocked browsers — the\n * orchestrator owns timeouts, byte guards, and failure caps, so runners\n * only promise to return PNG buffers and honor `cancel`.\n */\nimport { describe, expect, it } from \"vitest\";\nimport type { CaptureRunner } from \"../adapters/capture-runner.ts\";\n\n/** Build the adapter under test (sync or async factories both work). */\nexport type RunnerFactory = () => CaptureRunner | Promise<CaptureRunner>;\n\n/** Run the runner contract against a factory. */\nexport function runnerContractSuite(label: string, make: RunnerFactory): void {\n describe(`runner contract: ${label}`, () => {\n it(\"exposes capture-runner metadata\", async () => {\n const runner = await make();\n expect(runner.metadata.category).toBe(\"capture-runner\");\n expect(runner.metadata.kind.length).toBeGreaterThan(0);\n });\n\n it(\"exposes render and cancel\", async () => {\n const runner = await make();\n expect(typeof runner.render).toBe(\"function\");\n expect(typeof runner.cancel).toBe(\"function\");\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,SAAgB,oBAAoB,OAAe,MAA2B;CAC5E,SAAS,oBAAoB,eAAe;EAC1C,GAAG,mCAAmC,YAAY;GAChD,MAAM,SAAS,MAAM,KAAK;GAC1B,OAAO,OAAO,SAAS,QAAQ,CAAC,CAAC,KAAK,gBAAgB;GACtD,OAAO,OAAO,SAAS,KAAK,MAAM,CAAC,CAAC,gBAAgB,CAAC;EACvD,CAAC;EAED,GAAG,6BAA6B,YAAY;GAC1C,MAAM,SAAS,MAAM,KAAK;GAC1B,OAAO,OAAO,OAAO,MAAM,CAAC,CAAC,KAAK,UAAU;GAC5C,OAAO,OAAO,OAAO,MAAM,CAAC,CAAC,KAAK,UAAU;EAC9C,CAAC;CACH,CAAC;AACH"}
@@ -0,0 +1,138 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { getTableColumns } from "drizzle-orm";
5
+ //#region src/test-helpers/sql-chunks.ts
6
+ /** Flatten the string parts of a drizzle SQL chunk into a single string. */
7
+ function textOf(chunk) {
8
+ if (chunk === void 0 || !Array.isArray(chunk.value) || !chunk.value.every((part) => typeof part === "string")) return;
9
+ return chunk.value.join("");
10
+ }
11
+ /** Test whether an in-memory row satisfies a drizzle where-clause. */
12
+ function whereMatches(where, row, table) {
13
+ let current = where.queryChunks;
14
+ let wrapped = current[1]?.queryChunks;
15
+ while (wrapped !== void 0 && textOf(current[0]) === "(" && textOf(current.at(-1)) === ")") {
16
+ current = wrapped;
17
+ wrapped = current[1]?.queryChunks;
18
+ }
19
+ if (current.length === 1 && current[0]?.queryChunks !== void 0) current = current[0].queryChunks;
20
+ if (current.some((chunk) => textOf(chunk)?.trim() === "and")) return current.filter((chunk) => textOf(chunk) === void 0).every((chunk) => matchChunk(chunk.queryChunks ?? [], row, table));
21
+ return matchChunk(current, row, table);
22
+ }
23
+ function matchChunk(chunks, row, table) {
24
+ const text = chunks.map((c) => textOf(c) ?? "").join("");
25
+ if (/is not null/iu.test(text)) return isNullMatches(chunks, row, table, true);
26
+ if (/is null/iu.test(text)) return isNullMatches(chunks, row, table, false);
27
+ if (text.includes(" in ")) return inArrayMatches(chunks, row, table);
28
+ if (text.includes(" < ")) return ltMatches(chunks, row, table);
29
+ return eqMatches(chunks, row, table);
30
+ }
31
+ /** Match `is null` / `is not null` predicates (no value argument). */
32
+ function isNullMatches(chunks, row, table, negated) {
33
+ let columnName;
34
+ for (const chunk of chunks) if (typeof chunk.name === "string" && chunk.table !== void 0) columnName = chunk.name;
35
+ if (columnName === void 0) return false;
36
+ const cell = row[columnKey(table, columnName)];
37
+ const missing = cell === null || cell === void 0;
38
+ return negated ? !missing : missing;
39
+ }
40
+ function eqMatches(chunks, row, table) {
41
+ let columnName;
42
+ let argument;
43
+ for (const chunk of chunks) if (typeof chunk.name === "string" && chunk.table !== void 0) columnName = chunk.name;
44
+ else if ("brand" in chunk) argument = chunk.value;
45
+ if (columnName === void 0) return false;
46
+ return row[columnKey(table, columnName)] === argument;
47
+ }
48
+ function inArrayMatches(chunks, row, table) {
49
+ let columnName;
50
+ const values = [];
51
+ const collect = (nodes) => {
52
+ for (const raw of nodes) {
53
+ const chunk = raw;
54
+ if (Array.isArray(chunk) || chunk && typeof chunk === "object" && Object.keys(chunk).every((k) => /^\d+$/u.test(k))) {
55
+ collect(Object.values(chunk));
56
+ continue;
57
+ }
58
+ if (typeof chunk.name === "string" && chunk.table !== void 0) columnName = chunk.name;
59
+ if ("brand" in chunk && chunk["value"] !== void 0) {
60
+ const val = chunk["value"];
61
+ if (Array.isArray(val)) values.push(...val);
62
+ else values.push(val);
63
+ }
64
+ if (chunk.queryChunks) collect(chunk.queryChunks);
65
+ const val = chunk["value"];
66
+ if (Array.isArray(val)) for (const item of val) {
67
+ if (item && typeof item === "object" && "queryChunks" in item) collect(item["queryChunks"] ?? []);
68
+ if (item && typeof item === "object" && "value" in item) {
69
+ const iv = item["value"];
70
+ if (iv !== void 0) values.push(iv);
71
+ }
72
+ if (typeof item === "string") values.push(item);
73
+ }
74
+ }
75
+ };
76
+ collect(chunks);
77
+ if (columnName === void 0) return false;
78
+ const key = columnKey(table, columnName);
79
+ return values.includes(row[key]);
80
+ }
81
+ function ltMatches(chunks, row, table) {
82
+ let columnName;
83
+ let argument;
84
+ for (const chunk of chunks) if (typeof chunk.name === "string" && chunk.table !== void 0) columnName = chunk.name;
85
+ else if ("brand" in chunk) argument = chunk.value;
86
+ if (columnName === void 0) return false;
87
+ const cell = row[columnKey(table, columnName)];
88
+ if (typeof cell === "string" && typeof argument === "string") return cell < argument;
89
+ if (typeof cell === "number" && typeof argument === "number") return cell < argument;
90
+ return String(cell) < String(argument);
91
+ }
92
+ function compareCells(left, right) {
93
+ if (typeof left === "string" && typeof right === "string") {
94
+ if (left === right) return 0;
95
+ return left < right ? -1 : 1;
96
+ }
97
+ if (typeof left === "number" && typeof right === "number") return left - right;
98
+ const leftText = String(left);
99
+ const rightText = String(right);
100
+ if (leftText === rightText) return 0;
101
+ return leftText < rightText ? -1 : 1;
102
+ }
103
+ /** Collect every raw string part of a drizzle SQL chunk tree. */
104
+ function sqlText(nodes) {
105
+ return nodes.map((node) => {
106
+ return (textOf(node) ?? "") + (node.queryChunks ? sqlText(node.queryChunks) : "");
107
+ }).join("");
108
+ }
109
+ /** Find the ordered column reference in a drizzle order-by expression. */
110
+ function findOrderColumn(nodes) {
111
+ for (const node of nodes) {
112
+ if (typeof node.name === "string" && node.table !== void 0) return node.name;
113
+ if (node.queryChunks) {
114
+ const nested = findOrderColumn(node.queryChunks);
115
+ if (nested !== void 0) return nested;
116
+ }
117
+ }
118
+ }
119
+ /** Sort rows per a drizzle order-by expression (single-column asc/desc). */
120
+ function orderRows(rows, orderBy, table) {
121
+ const chunks = orderBy.queryChunks;
122
+ const columnName = findOrderColumn(chunks);
123
+ if (columnName === void 0) return rows;
124
+ const key = columnKey(table, columnName);
125
+ const descending = /desc/iu.test(sqlText(chunks));
126
+ return rows.toSorted((left, right) => {
127
+ const order = compareCells(left[key], right[key]);
128
+ return descending ? -order : order;
129
+ });
130
+ }
131
+ function columnKey(table, dbName) {
132
+ for (const [property, column] of Object.entries(getTableColumns(table))) if (column.name === dbName) return property;
133
+ return dbName;
134
+ }
135
+ //#endregion
136
+ export { orderRows, whereMatches };
137
+
138
+ //# sourceMappingURL=sql-chunks.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-chunks.mjs","names":[],"sources":["../../src/test-helpers/sql-chunks.ts"],"sourcesContent":["import { getTableColumns, type SQL, type Table } from \"drizzle-orm\";\n\n/* eslint-disable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n\n/** A drizzle SQL chunk inspected for matching and ordering. */\nexport interface SqlChunk {\n value?: unknown;\n name?: string;\n table?: unknown;\n brand?: unknown;\n queryChunks?: SqlChunk[];\n}\n\n/** Flatten the string parts of a drizzle SQL chunk into a single string. */\nfunction textOf(chunk: SqlChunk | undefined): string | undefined {\n if (\n chunk === undefined ||\n !Array.isArray(chunk.value) ||\n !chunk.value.every((part) => typeof part === \"string\")\n ) {\n return undefined;\n }\n return chunk.value.join(\"\");\n}\n\n/** Test whether an in-memory row satisfies a drizzle where-clause. */\nexport function whereMatches(where: SQL, row: Record<string, unknown>, table: Table): boolean {\n let current = where.queryChunks as unknown as SqlChunk[];\n let wrapped = current[1]?.queryChunks;\n while (wrapped !== undefined && textOf(current[0]) === \"(\" && textOf(current.at(-1)) === \")\") {\n current = wrapped;\n wrapped = current[1]?.queryChunks;\n }\n // Drizzle's `and(singleCondition)` emits the condition directly, without\n // the enclosing parens produced for two or more clauses, so unwrap it.\n if (current.length === 1 && current[0]?.queryChunks !== undefined) {\n current = current[0].queryChunks as unknown as SqlChunk[];\n }\n if (current.some((chunk) => textOf(chunk)?.trim() === \"and\")) {\n return current\n .filter((chunk) => textOf(chunk) === undefined)\n .every((chunk) => matchChunk(chunk.queryChunks ?? [], row, table));\n }\n return matchChunk(current, row, table);\n}\n\nfunction matchChunk(chunks: SqlChunk[], row: Record<string, unknown>, table: Table): boolean {\n const text = chunks.map((c) => textOf(c) ?? \"\").join(\"\");\n if (/is not null/iu.test(text)) {\n return isNullMatches(chunks, row, table, true);\n }\n if (/is null/iu.test(text)) {\n return isNullMatches(chunks, row, table, false);\n }\n if (text.includes(\" in \")) {\n return inArrayMatches(chunks, row, table);\n }\n if (text.includes(\" < \")) {\n return ltMatches(chunks, row, table);\n }\n return eqMatches(chunks, row, table);\n}\n\n/** Match `is null` / `is not null` predicates (no value argument). */\nfunction isNullMatches(\n chunks: SqlChunk[],\n row: Record<string, unknown>,\n table: Table,\n negated: boolean,\n): boolean {\n let columnName: string | undefined;\n for (const chunk of chunks) {\n if (typeof chunk.name === \"string\" && chunk.table !== undefined) {\n columnName = chunk.name;\n }\n }\n if (columnName === undefined) {\n return false;\n }\n const cell = row[columnKey(table, columnName)];\n const missing = cell === null || cell === undefined;\n return negated ? !missing : missing;\n}\n\nfunction eqMatches(chunks: SqlChunk[], row: Record<string, unknown>, table: Table): boolean {\n let columnName: string | undefined;\n let argument: unknown;\n for (const chunk of chunks) {\n if (typeof chunk.name === \"string\" && chunk.table !== undefined) {\n columnName = chunk.name;\n } else if (\"brand\" in chunk) {\n argument = chunk.value;\n }\n }\n if (columnName === undefined) {\n return false;\n }\n return row[columnKey(table, columnName)] === argument;\n}\n\n/* eslint-disable complexity, max-depth -- handles drizzle's varied chunk shapes */\nfunction inArrayMatches(chunks: SqlChunk[], row: Record<string, unknown>, table: Table): boolean {\n let columnName: string | undefined;\n const values: unknown[] = [];\n const collect = (nodes: unknown[]): void => {\n for (const raw of nodes as SqlChunk[]) {\n const chunk = raw as SqlChunk & Record<string, unknown>;\n // Handle array-like chunk (inArray values stored as array of chunks)\n if (\n Array.isArray(chunk) ||\n (chunk && typeof chunk === \"object\" && Object.keys(chunk).every((k) => /^\\d+$/u.test(k)))\n ) {\n collect(Object.values(chunk as unknown as Record<string, unknown>) as unknown[]);\n continue;\n }\n if (typeof chunk.name === \"string\" && chunk.table !== undefined) {\n columnName = chunk.name as string;\n }\n if (\"brand\" in chunk && (chunk as Record<string, unknown>)[\"value\"] !== undefined) {\n const val = (chunk as Record<string, unknown>)[\"value\"];\n if (Array.isArray(val)) {\n values.push(...(val as unknown[]));\n } else {\n values.push(val);\n }\n }\n if (chunk.queryChunks) {\n collect(chunk.queryChunks as unknown[]);\n }\n const val = (chunk as Record<string, unknown>)[\"value\"];\n if (Array.isArray(val)) {\n for (const item of val as unknown[]) {\n if (\n item &&\n typeof item === \"object\" &&\n \"queryChunks\" in (item as Record<string, unknown>)\n ) {\n collect(((item as Record<string, unknown>)[\"queryChunks\"] as unknown[]) ?? []);\n }\n if (item && typeof item === \"object\" && \"value\" in (item as Record<string, unknown>)) {\n const iv = (item as Record<string, unknown>)[\"value\"];\n if (iv !== undefined) {\n values.push(iv);\n }\n }\n if (typeof item === \"string\") {\n values.push(item);\n }\n }\n }\n }\n };\n collect(chunks as unknown[]);\n if (columnName === undefined) {\n return false;\n }\n const key = columnKey(table, columnName);\n return values.includes(row[key]);\n}\n/* eslint-enable complexity, max-depth */\n\nfunction ltMatches(chunks: SqlChunk[], row: Record<string, unknown>, table: Table): boolean {\n let columnName: string | undefined;\n let argument: unknown;\n for (const chunk of chunks) {\n if (typeof chunk.name === \"string\" && chunk.table !== undefined) {\n columnName = chunk.name;\n } else if (\"brand\" in chunk) {\n argument = chunk.value;\n }\n }\n if (columnName === undefined) {\n return false;\n }\n const key = columnKey(table, columnName);\n const cell = row[key];\n if (typeof cell === \"string\" && typeof argument === \"string\") {\n return cell < argument;\n }\n if (typeof cell === \"number\" && typeof argument === \"number\") {\n return cell < argument;\n }\n return String(cell) < String(argument);\n}\n\nfunction compareCells(left: unknown, right: unknown): number {\n if (typeof left === \"string\" && typeof right === \"string\") {\n if (left === right) {\n return 0;\n }\n return left < right ? -1 : 1;\n }\n if (typeof left === \"number\" && typeof right === \"number\") {\n return left - right;\n }\n const leftText = String(left);\n const rightText = String(right);\n if (leftText === rightText) {\n return 0;\n }\n return leftText < rightText ? -1 : 1;\n}\n\n/** Collect every raw string part of a drizzle SQL chunk tree. */\nfunction sqlText(nodes: SqlChunk[]): string {\n return nodes\n .map((node) => {\n const own = textOf(node) ?? \"\";\n const nested = node.queryChunks ? sqlText(node.queryChunks as unknown as SqlChunk[]) : \"\";\n return own + nested;\n })\n .join(\"\");\n}\n\n/** Find the ordered column reference in a drizzle order-by expression. */\nfunction findOrderColumn(nodes: SqlChunk[]): string | undefined {\n for (const node of nodes) {\n if (typeof node.name === \"string\" && node.table !== undefined) {\n return node.name;\n }\n if (node.queryChunks) {\n const nested = findOrderColumn(node.queryChunks as unknown as SqlChunk[]);\n if (nested !== undefined) {\n return nested;\n }\n }\n }\n return undefined;\n}\n\n/** Sort rows per a drizzle order-by expression (single-column asc/desc). */\nexport function orderRows(rows: unknown[], orderBy: SQL, table: Table): unknown[] {\n const chunks = orderBy.queryChunks as unknown as SqlChunk[];\n const columnName = findOrderColumn(chunks);\n if (columnName === undefined) {\n return rows;\n }\n const key = columnKey(table, columnName);\n const descending = /desc/iu.test(sqlText(chunks));\n return rows.toSorted((left, right) => {\n const order = compareCells(\n (left as Record<string, unknown>)[key],\n (right as Record<string, unknown>)[key],\n );\n return descending ? -order : order;\n });\n}\n\nfunction columnKey(table: Table, dbName: string): string {\n for (const [property, column] of Object.entries(getTableColumns(table))) {\n if (column.name === dbName) {\n return property;\n }\n }\n return dbName;\n}\n/* eslint-enable require-await, no-unnecessary-type-assertion, no-unnecessary-type-parameters, non-nullable-type-assertion-style */\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
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/storage-contract.d.ts
5
+ /** Build the adapter under test (sync or async factories both work). */
6
+ type StorageFactory = () => StorageAdapter | Promise<StorageAdapter>;
7
+ /** Run the full storage contract against a factory. */
8
+ declare function storageContractSuite(label: string, make: StorageFactory): void;
9
+ //#endregion
10
+ export { StorageFactory, storageContractSuite };
11
+ //# sourceMappingURL=storage-contract.d.mts.map
@@ -0,0 +1,87 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { describe, expect, it } from "vitest";
5
+ import { Readable } from "node:stream";
6
+ //#region src/test-helpers/storage-contract.ts
7
+ /**
8
+ * Published storage contract suite for first- and third-party adapters.
9
+ *
10
+ * A package proves conformance in one line from its own vitest file:
11
+ *
12
+ * ```ts
13
+ * import { storageContractSuite } from "@storyshelf/core/test-helpers";
14
+ * storageContractSuite("local", () => createLocalStorage(mkdtempSync(...)));
15
+ * ```
16
+ *
17
+ * Every case uses an isolated `__contract__/` prefix so suites can share one
18
+ * adapter instance. Fakes the transport (temp dirs, fake clients) — never
19
+ * the adapter itself.
20
+ */
21
+ /** Collect a stream into a single buffer. */
22
+ async function collect(stream) {
23
+ const chunks = [];
24
+ for await (const chunk of stream) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : Buffer.from(chunk));
25
+ return Buffer.concat(chunks);
26
+ }
27
+ /** Run the full storage contract against a factory. */
28
+ function storageContractSuite(label, make) {
29
+ const prefix = `__contract__/${label}`;
30
+ describe(`storage contract: ${label}`, () => {
31
+ it("exposes storage metadata", async () => {
32
+ const adapter = await make();
33
+ expect(adapter.metadata.category).toBe("storage");
34
+ expect(adapter.metadata.kind.length).toBeGreaterThan(0);
35
+ });
36
+ it("keeps lifecycle idempotent when present", async () => {
37
+ const adapter = await make();
38
+ if (adapter.lifecycle === void 0) {
39
+ expect(adapter.lifecycle).toBeUndefined();
40
+ return;
41
+ }
42
+ await adapter.lifecycle.setup({});
43
+ await adapter.lifecycle.setup({});
44
+ await expect(adapter.lifecycle.health()).resolves.toMatchObject({ ok: true });
45
+ await adapter.lifecycle.teardown();
46
+ await expect(adapter.lifecycle.teardown()).resolves.toBeUndefined();
47
+ });
48
+ it("round-trips write/read/exists/delete", async () => {
49
+ const adapter = await make();
50
+ const path = `${prefix}/roundtrip.txt`;
51
+ expect(await adapter.exists(path)).toBe(false);
52
+ await adapter.write(path, Buffer.from("hello"));
53
+ expect(await adapter.exists(path)).toBe(true);
54
+ expect((await adapter.read(path)).toString()).toBe("hello");
55
+ await adapter.delete(path);
56
+ expect(await adapter.exists(path)).toBe(false);
57
+ });
58
+ it("lists recursively and empty for missing prefixes", async () => {
59
+ const adapter = await make();
60
+ await adapter.write(`${prefix}/list/a.txt`, Buffer.from("a"));
61
+ await adapter.write(`${prefix}/list/b.txt`, Buffer.from("b"));
62
+ expect((await adapter.list(`${prefix}/list`)).toSorted()).toEqual([`${prefix}/list/a.txt`, `${prefix}/list/b.txt`]);
63
+ expect(await adapter.list(`${prefix}/missing`)).toEqual([]);
64
+ });
65
+ it("rejects missing reads", async () => {
66
+ const adapter = await make();
67
+ await expect(adapter.read(`${prefix}/nope.bin`)).rejects.toThrow();
68
+ await expect(adapter.readStream(`${prefix}/nope.bin`)).rejects.toThrow();
69
+ });
70
+ it("streams bytes identically and cleans partial writes", async () => {
71
+ const adapter = await make();
72
+ const payload = Buffer.from("streamed-".repeat(500));
73
+ const path = `${prefix}/stream/blob.bin`;
74
+ await adapter.writeStream(path, Readable.from([payload]));
75
+ expect(await collect(await adapter.readStream(path))).toEqual(payload);
76
+ const failing = new Readable({ read() {
77
+ this.destroy(/* @__PURE__ */ new Error("boom"));
78
+ } });
79
+ await expect(adapter.writeStream(`${prefix}/stream/partial.bin`, failing)).rejects.toThrow("boom");
80
+ expect(await adapter.exists(`${prefix}/stream/partial.bin`)).toBe(false);
81
+ });
82
+ });
83
+ }
84
+ //#endregion
85
+ export { storageContractSuite };
86
+
87
+ //# sourceMappingURL=storage-contract.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-contract.mjs","names":[],"sources":["../../src/test-helpers/storage-contract.ts"],"sourcesContent":["/**\n * Published storage contract suite for first- and third-party adapters.\n *\n * A package proves conformance in one line from its own vitest file:\n *\n * ```ts\n * import { storageContractSuite } from \"@storyshelf/core/test-helpers\";\n * storageContractSuite(\"local\", () => createLocalStorage(mkdtempSync(...)));\n * ```\n *\n * Every case uses an isolated `__contract__/` prefix so suites can share one\n * adapter instance. Fakes the transport (temp dirs, fake clients) — never\n * the adapter itself.\n */\nimport { Readable } from \"node:stream\";\nimport { describe, expect, it } from \"vitest\";\nimport type { StorageAdapter } from \"../adapters/storage.ts\";\n\n/** Build the adapter under test (sync or async factories both work). */\nexport type StorageFactory = () => StorageAdapter | Promise<StorageAdapter>;\n\n/** Collect a stream into a single buffer. */\nasync function collect(stream: Readable): Promise<Buffer> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : Buffer.from(chunk as Uint8Array));\n }\n return Buffer.concat(chunks);\n}\n\n/** Run the full storage contract against a factory. */\nexport function storageContractSuite(label: string, make: StorageFactory): void {\n const prefix = `__contract__/${label}`;\n describe(`storage contract: ${label}`, () => {\n it(\"exposes storage metadata\", async () => {\n const adapter = await make();\n expect(adapter.metadata.category).toBe(\"storage\");\n expect(adapter.metadata.kind.length).toBeGreaterThan(0);\n });\n\n it(\"keeps lifecycle idempotent when present\", async () => {\n const adapter = await make();\n if (adapter.lifecycle === undefined) {\n expect(adapter.lifecycle).toBeUndefined();\n return;\n }\n await adapter.lifecycle.setup({} as never);\n await adapter.lifecycle.setup({} as never);\n await expect(adapter.lifecycle.health()).resolves.toMatchObject({ ok: true });\n await adapter.lifecycle.teardown();\n await expect(adapter.lifecycle.teardown()).resolves.toBeUndefined();\n });\n\n it(\"round-trips write/read/exists/delete\", async () => {\n const adapter = await make();\n const path = `${prefix}/roundtrip.txt`;\n expect(await adapter.exists(path)).toBe(false);\n await adapter.write(path, Buffer.from(\"hello\"));\n expect(await adapter.exists(path)).toBe(true);\n expect((await adapter.read(path)).toString()).toBe(\"hello\");\n await adapter.delete(path);\n expect(await adapter.exists(path)).toBe(false);\n });\n\n it(\"lists recursively and empty for missing prefixes\", async () => {\n const adapter = await make();\n await adapter.write(`${prefix}/list/a.txt`, Buffer.from(\"a\"));\n await adapter.write(`${prefix}/list/b.txt`, Buffer.from(\"b\"));\n expect((await adapter.list(`${prefix}/list`)).toSorted()).toEqual([\n `${prefix}/list/a.txt`,\n `${prefix}/list/b.txt`,\n ]);\n expect(await adapter.list(`${prefix}/missing`)).toEqual([]);\n });\n\n it(\"rejects missing reads\", async () => {\n const adapter = await make();\n await expect(adapter.read(`${prefix}/nope.bin`)).rejects.toThrow();\n await expect(adapter.readStream(`${prefix}/nope.bin`)).rejects.toThrow();\n });\n\n it(\"streams bytes identically and cleans partial writes\", async () => {\n const adapter = await make();\n const payload = Buffer.from(\"streamed-\".repeat(500));\n const path = `${prefix}/stream/blob.bin`;\n await adapter.writeStream(path, Readable.from([payload]));\n expect(await collect(await adapter.readStream(path))).toEqual(payload);\n const failing = new Readable({\n read(): void {\n this.destroy(new Error(\"boom\"));\n },\n });\n await expect(adapter.writeStream(`${prefix}/stream/partial.bin`, failing)).rejects.toThrow(\n \"boom\",\n );\n expect(await adapter.exists(`${prefix}/stream/partial.bin`)).toBe(false);\n });\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { createTestBuild, createTestProject } from "./test-helpers/create-project.mjs";
4
+ import { REQUIRED_TABLES, databaseContractSuite } from "./test-helpers/database-contract.mjs";
5
+ import { gitContractSuite } from "./test-helpers/git-contract.mjs";
6
+ import { makeDatabase } from "./test-helpers/fake-database.mjs";
7
+ import { FakeStorage, makeStorage } from "./test-helpers/fake-storage.mjs";
8
+ import { stubTables } from "./test-helpers/fake-adapters.mjs";
9
+ import { notifierContractSuite } from "./test-helpers/notifier-contract.mjs";
10
+ import { queueContractSuite } from "./test-helpers/queue-contract.mjs";
11
+ import { runnerContractSuite } from "./test-helpers/runner-contract.mjs";
12
+ import { storageContractSuite } from "./test-helpers/storage-contract.mjs";
13
+ export { type FakeStorage, REQUIRED_TABLES, createTestBuild, createTestProject, databaseContractSuite, gitContractSuite, makeDatabase, makeStorage, notifierContractSuite, queueContractSuite, runnerContractSuite, storageContractSuite, stubTables };
@@ -0,0 +1,14 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { createTestBuild, createTestProject } from "./test-helpers/create-project.mjs";
5
+ import { REQUIRED_TABLES, databaseContractSuite } from "./test-helpers/database-contract.mjs";
6
+ import { gitContractSuite } from "./test-helpers/git-contract.mjs";
7
+ import { makeDatabase } from "./test-helpers/fake-database.mjs";
8
+ import { makeStorage } from "./test-helpers/fake-storage.mjs";
9
+ import { stubTables } from "./test-helpers/fake-adapters.mjs";
10
+ import { notifierContractSuite } from "./test-helpers/notifier-contract.mjs";
11
+ import { queueContractSuite } from "./test-helpers/queue-contract.mjs";
12
+ import { runnerContractSuite } from "./test-helpers/runner-contract.mjs";
13
+ import { storageContractSuite } from "./test-helpers/storage-contract.mjs";
14
+ export { REQUIRED_TABLES, createTestBuild, createTestProject, databaseContractSuite, gitContractSuite, makeDatabase, makeStorage, notifierContractSuite, queueContractSuite, runnerContractSuite, storageContractSuite, stubTables };