@storyshelf/core 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/README.md +49 -32
  2. package/dist/adapter/capture-queue.d.mts +44 -2
  3. package/dist/adapter/capture-runner.d.mts +127 -10
  4. package/dist/adapter/capture-runner.mjs +5 -12
  5. package/dist/adapter/database.d.mts +27 -8
  6. package/dist/adapter/database.mjs.map +1 -1
  7. package/dist/adapter/design.d.mts +85 -0
  8. package/dist/adapter/design.mjs +28 -0
  9. package/dist/adapter/design.mjs.map +1 -0
  10. package/dist/adapter/metadata.d.mts +3 -10
  11. package/dist/adapter/notifier.d.mts +6 -3
  12. package/dist/adapter/notifier.mjs +5 -1
  13. package/dist/adapter/oauth.d.mts +52 -0
  14. package/dist/adapter/setup.d.mts +4 -5
  15. package/dist/adapter/setup.mjs +2 -1
  16. package/dist/adapter/setup.mjs.map +1 -1
  17. package/dist/adapter/webhook-events.mjs +1 -1
  18. package/dist/adapters/capture-target-offers.d.mts +28 -0
  19. package/dist/adapters/capture-target-offers.mjs +58 -0
  20. package/dist/adapters/capture-target-offers.mjs.map +1 -0
  21. package/dist/adapters/capture-target.d.mts +71 -0
  22. package/dist/adapters/capture-target.mjs +76 -0
  23. package/dist/adapters/capture-target.mjs.map +1 -0
  24. package/dist/adapters/notifier/build-comment.d.mts +24 -0
  25. package/dist/adapters/notifier/build-comment.mjs +24 -0
  26. package/dist/adapters/notifier/build-comment.mjs.map +1 -0
  27. package/dist/adapters/notifier/build-state.d.mts +99 -0
  28. package/dist/adapters/notifier/build-state.mjs +218 -0
  29. package/dist/adapters/notifier/build-state.mjs.map +1 -0
  30. package/dist/adapters/notifier/events.d.mts +4 -2
  31. package/dist/adapters/notifier/events.mjs +31 -18
  32. package/dist/adapters/notifier/events.mjs.map +1 -1
  33. package/dist/adapters/notifier/provider.d.mts +53 -7
  34. package/dist/adapters/notifier/provider.mjs +12 -0
  35. package/dist/adapters/notifier/provider.mjs.map +1 -0
  36. package/dist/adapters/notifier/state.d.mts +24 -0
  37. package/dist/adapters/notifier/state.mjs +66 -0
  38. package/dist/adapters/notifier/state.mjs.map +1 -0
  39. package/dist/adapters/notifier/types.d.mts +51 -2
  40. package/dist/adapters/remote-browser.d.mts +87 -0
  41. package/dist/adapters/remote-browser.mjs +103 -0
  42. package/dist/adapters/remote-browser.mjs.map +1 -0
  43. package/dist/adapters/render-runs.d.mts +25 -0
  44. package/dist/adapters/render-runs.mjs +41 -0
  45. package/dist/adapters/render-runs.mjs.map +1 -0
  46. package/dist/adapters/setup-runner.mjs +2 -4
  47. package/dist/adapters/setup-runner.mjs.map +1 -1
  48. package/dist/adapters/sources.d.mts +12 -0
  49. package/dist/adapters/sources.mjs +20 -0
  50. package/dist/adapters/sources.mjs.map +1 -0
  51. package/dist/adapters/validate.mjs +25 -18
  52. package/dist/adapters/validate.mjs.map +1 -1
  53. package/dist/ai.d.mts +105 -0
  54. package/dist/ai.mjs +19 -0
  55. package/dist/ai.mjs.map +1 -0
  56. package/dist/auth.d.mts +8 -1
  57. package/dist/auth.mjs +14 -1
  58. package/dist/auth.mjs.map +1 -0
  59. package/dist/capture/a11y/axe-source.d.mts +18 -0
  60. package/dist/capture/a11y/axe-source.mjs +37 -0
  61. package/dist/capture/a11y/axe-source.mjs.map +1 -0
  62. package/dist/capture/a11y/in-page.d.mts +27 -0
  63. package/dist/capture/a11y/in-page.mjs +60 -0
  64. package/dist/capture/a11y/in-page.mjs.map +1 -0
  65. package/dist/capture/a11y/map.d.mts +24 -0
  66. package/dist/capture/a11y/map.mjs +48 -0
  67. package/dist/capture/a11y/map.mjs.map +1 -0
  68. package/dist/capture/a11y/options.d.mts +23 -0
  69. package/dist/capture/a11y/options.mjs +75 -0
  70. package/dist/capture/a11y/options.mjs.map +1 -0
  71. package/dist/capture/adapter.d.mts +41 -3
  72. package/dist/capture/adapter.mjs.map +1 -1
  73. package/dist/capture/affected.d.mts +2 -0
  74. package/dist/capture/affected.mjs +13 -4
  75. package/dist/capture/affected.mjs.map +1 -1
  76. package/dist/capture/attempt-logger.mjs +84 -0
  77. package/dist/capture/attempt-logger.mjs.map +1 -0
  78. package/dist/capture/browsers.d.mts +35 -0
  79. package/dist/capture/browsers.mjs +67 -0
  80. package/dist/capture/browsers.mjs.map +1 -0
  81. package/dist/capture/build-state/deliver.d.mts +32 -0
  82. package/dist/capture/build-state/deliver.mjs +118 -0
  83. package/dist/capture/build-state/deliver.mjs.map +1 -0
  84. package/dist/capture/build-state/index.d.mts +8 -0
  85. package/dist/capture/build-state/notify-job.d.mts +56 -0
  86. package/dist/capture/build-state/notify-job.mjs +133 -0
  87. package/dist/capture/build-state/notify-job.mjs.map +1 -0
  88. package/dist/capture/build-state/publisher.d.mts +23 -0
  89. package/dist/capture/build-state/publisher.mjs +107 -0
  90. package/dist/capture/build-state/publisher.mjs.map +1 -0
  91. package/dist/capture/build-state/resume.d.mts +9 -0
  92. package/dist/capture/build-state/resume.mjs +47 -0
  93. package/dist/capture/build-state/resume.mjs.map +1 -0
  94. package/dist/capture/build-state/types.d.mts +49 -0
  95. package/dist/capture/catalog/catalogue.d.mts +22 -0
  96. package/dist/capture/catalog/catalogue.mjs +53 -0
  97. package/dist/capture/catalog/catalogue.mjs.map +1 -0
  98. package/dist/capture/catalog/components.d.mts +23 -0
  99. package/dist/capture/catalog/components.mjs +55 -0
  100. package/dist/capture/catalog/components.mjs.map +1 -0
  101. package/dist/capture/catalog/history.d.mts +30 -0
  102. package/dist/capture/catalog/history.mjs +51 -0
  103. package/dist/capture/catalog/history.mjs.map +1 -0
  104. package/dist/capture/catalog/hook.d.mts +14 -0
  105. package/dist/capture/catalog/hook.mjs +19 -0
  106. package/dist/capture/catalog/hook.mjs.map +1 -0
  107. package/dist/capture/catalog/index.d.mts +11 -0
  108. package/dist/capture/catalog/load.d.mts +26 -0
  109. package/dist/capture/catalog/load.mjs +49 -0
  110. package/dist/capture/catalog/load.mjs.map +1 -0
  111. package/dist/capture/catalog/parse.d.mts +15 -0
  112. package/dist/capture/catalog/parse.mjs +56 -0
  113. package/dist/capture/catalog/parse.mjs.map +1 -0
  114. package/dist/capture/catalog/read.d.mts +12 -0
  115. package/dist/capture/catalog/read.mjs +33 -0
  116. package/dist/capture/catalog/read.mjs.map +1 -0
  117. package/dist/capture/catalog/types.d.mts +33 -0
  118. package/dist/capture/consumer/capture-handler.d.mts +58 -0
  119. package/dist/capture/consumer/capture-handler.mjs +118 -0
  120. package/dist/capture/consumer/capture-handler.mjs.map +1 -0
  121. package/dist/capture/consumer/idle.d.mts +17 -0
  122. package/dist/capture/consumer/idle.mjs +25 -0
  123. package/dist/capture/consumer/idle.mjs.map +1 -0
  124. package/dist/capture/consumer/index.d.mts +13 -0
  125. package/dist/capture/consumer/index.mjs +139 -0
  126. package/dist/capture/consumer/index.mjs.map +1 -0
  127. package/dist/capture/consumer/loop.mjs +110 -0
  128. package/dist/capture/consumer/loop.mjs.map +1 -0
  129. package/dist/capture/consumer/metrics.d.mts +41 -0
  130. package/dist/capture/consumer/metrics.mjs +38 -0
  131. package/dist/capture/consumer/metrics.mjs.map +1 -0
  132. package/dist/capture/consumer/retry.d.mts +33 -0
  133. package/dist/capture/consumer/retry.mjs +34 -0
  134. package/dist/capture/consumer/retry.mjs.map +1 -0
  135. package/dist/capture/consumer/run-job.mjs +195 -0
  136. package/dist/capture/consumer/run-job.mjs.map +1 -0
  137. package/dist/capture/consumer/startup.mjs +38 -0
  138. package/dist/capture/consumer/startup.mjs.map +1 -0
  139. package/dist/capture/consumer/types.d.mts +97 -0
  140. package/dist/capture/crash-failure.d.mts +25 -0
  141. package/dist/capture/crash-failure.mjs +70 -0
  142. package/dist/capture/crash-failure.mjs.map +1 -0
  143. package/dist/capture/db-queue/cadence.d.mts +32 -0
  144. package/dist/capture/db-queue/cadence.mjs +38 -0
  145. package/dist/capture/db-queue/cadence.mjs.map +1 -0
  146. package/dist/capture/db-queue/claim.d.mts +9 -0
  147. package/dist/capture/db-queue/claim.mjs +132 -0
  148. package/dist/capture/db-queue/claim.mjs.map +1 -0
  149. package/dist/capture/db-queue/clock.mjs +12 -0
  150. package/dist/capture/db-queue/clock.mjs.map +1 -0
  151. package/dist/capture/db-queue/codec.mjs +76 -0
  152. package/dist/capture/db-queue/codec.mjs.map +1 -0
  153. package/dist/capture/db-queue/index.d.mts +20 -0
  154. package/dist/capture/db-queue/index.mjs +89 -0
  155. package/dist/capture/db-queue/index.mjs.map +1 -0
  156. package/dist/capture/db-queue/keeper.d.mts +36 -0
  157. package/dist/capture/db-queue/keeper.mjs +92 -0
  158. package/dist/capture/db-queue/keeper.mjs.map +1 -0
  159. package/dist/capture/db-queue/lease.mjs +46 -0
  160. package/dist/capture/db-queue/lease.mjs.map +1 -0
  161. package/dist/capture/db-queue/lifecycle.mjs +36 -0
  162. package/dist/capture/db-queue/lifecycle.mjs.map +1 -0
  163. package/dist/capture/db-queue/operations.mjs +94 -0
  164. package/dist/capture/db-queue/operations.mjs.map +1 -0
  165. package/dist/capture/db-queue/poll-loop.d.mts +30 -0
  166. package/dist/capture/db-queue/poll-loop.mjs +89 -0
  167. package/dist/capture/db-queue/poll-loop.mjs.map +1 -0
  168. package/dist/capture/db-queue/poll.d.mts +10 -0
  169. package/dist/capture/db-queue/poll.mjs +69 -0
  170. package/dist/capture/db-queue/poll.mjs.map +1 -0
  171. package/dist/capture/db-queue/timers.d.mts +12 -0
  172. package/dist/capture/db-queue/timers.mjs +37 -0
  173. package/dist/capture/db-queue/timers.mjs.map +1 -0
  174. package/dist/capture/db-queue/types.d.mts +83 -0
  175. package/dist/capture/db-queue/types.mjs +12 -0
  176. package/dist/capture/db-queue/types.mjs.map +1 -0
  177. package/dist/capture/db-queue/wake.mjs +48 -0
  178. package/dist/capture/db-queue/wake.mjs.map +1 -0
  179. package/dist/capture/design.mjs +39 -0
  180. package/dist/capture/design.mjs.map +1 -0
  181. package/dist/capture/diff-record.mjs +23 -3
  182. package/dist/capture/diff-record.mjs.map +1 -1
  183. package/dist/capture/dispatch.d.mts +12 -7
  184. package/dist/capture/dispatch.mjs +86 -107
  185. package/dist/capture/dispatch.mjs.map +1 -1
  186. package/dist/capture/enrich.mjs +60 -0
  187. package/dist/capture/enrich.mjs.map +1 -0
  188. package/dist/capture/failure-sets.mjs +22 -0
  189. package/dist/capture/failure-sets.mjs.map +1 -0
  190. package/dist/capture/fingerprint.d.mts +42 -0
  191. package/dist/capture/fingerprint.mjs +83 -0
  192. package/dist/capture/fingerprint.mjs.map +1 -0
  193. package/dist/capture/forked/channel.d.mts +25 -0
  194. package/dist/capture/forked/child.d.mts +34 -0
  195. package/dist/capture/forked/child.mjs +202 -0
  196. package/dist/capture/forked/child.mjs.map +1 -0
  197. package/dist/capture/forked/crash-tracker.mjs +23 -0
  198. package/dist/capture/forked/crash-tracker.mjs.map +1 -0
  199. package/dist/capture/forked/decision.d.mts +26 -0
  200. package/dist/capture/forked/decision.mjs +27 -0
  201. package/dist/capture/forked/decision.mjs.map +1 -0
  202. package/dist/capture/forked/exit.mjs +12 -0
  203. package/dist/capture/forked/exit.mjs.map +1 -0
  204. package/dist/capture/forked/fork.d.mts +31 -0
  205. package/dist/capture/forked/fork.mjs +93 -0
  206. package/dist/capture/forked/fork.mjs.map +1 -0
  207. package/dist/capture/forked/forked-capture.d.mts +40 -0
  208. package/dist/capture/forked/forked-capture.mjs +240 -0
  209. package/dist/capture/forked/forked-capture.mjs.map +1 -0
  210. package/dist/capture/forked/lease-book.mjs +46 -0
  211. package/dist/capture/forked/lease-book.mjs.map +1 -0
  212. package/dist/capture/forked/protocol.d.mts +38 -0
  213. package/dist/capture/forked/protocol.mjs +25 -0
  214. package/dist/capture/forked/protocol.mjs.map +1 -0
  215. package/dist/capture/forked/runs.mjs +75 -0
  216. package/dist/capture/forked/runs.mjs.map +1 -0
  217. package/dist/capture/isolate.mjs +141 -0
  218. package/dist/capture/isolate.mjs.map +1 -0
  219. package/dist/capture/job-lease.d.mts +28 -0
  220. package/dist/capture/job-lease.mjs +57 -0
  221. package/dist/capture/job-lease.mjs.map +1 -0
  222. package/dist/capture/matrix.mjs +298 -0
  223. package/dist/capture/matrix.mjs.map +1 -0
  224. package/dist/capture/modes.d.mts +25 -0
  225. package/dist/capture/modes.mjs +107 -0
  226. package/dist/capture/modes.mjs.map +1 -0
  227. package/dist/capture/orchestrator.d.mts +37 -5
  228. package/dist/capture/orchestrator.mjs +118 -107
  229. package/dist/capture/orchestrator.mjs.map +1 -1
  230. package/dist/capture/pipeline.d.mts +9 -2
  231. package/dist/capture/pipeline.mjs +250 -45
  232. package/dist/capture/pipeline.mjs.map +1 -1
  233. package/dist/capture/progress.d.mts +11 -0
  234. package/dist/capture/progress.mjs +28 -0
  235. package/dist/capture/progress.mjs.map +1 -0
  236. package/dist/capture/publish/accept.d.mts +39 -0
  237. package/dist/capture/publish/accept.mjs +28 -0
  238. package/dist/capture/publish/accept.mjs.map +1 -0
  239. package/dist/capture/publish/complete.d.mts +46 -0
  240. package/dist/capture/publish/complete.mjs +64 -0
  241. package/dist/capture/publish/complete.mjs.map +1 -0
  242. package/dist/capture/publish/extract.d.mts +20 -0
  243. package/dist/capture/publish/extract.mjs +119 -0
  244. package/dist/capture/publish/extract.mjs.map +1 -0
  245. package/dist/capture/publish/handler.d.mts +28 -0
  246. package/dist/capture/publish/handler.mjs +62 -0
  247. package/dist/capture/publish/handler.mjs.map +1 -0
  248. package/dist/capture/publish/index.d.mts +10 -0
  249. package/dist/capture/publish/limits.d.mts +37 -0
  250. package/dist/capture/publish/limits.mjs +39 -0
  251. package/dist/capture/publish/limits.mjs.map +1 -0
  252. package/dist/capture/publish/published.d.mts +15 -0
  253. package/dist/capture/publish/published.mjs +18 -0
  254. package/dist/capture/publish/published.mjs.map +1 -0
  255. package/dist/capture/publish/run.d.mts +33 -0
  256. package/dist/capture/publish/run.mjs +30 -0
  257. package/dist/capture/publish/run.mjs.map +1 -0
  258. package/dist/capture/rediff.d.mts +1 -1
  259. package/dist/capture/rediff.mjs +4 -3
  260. package/dist/capture/rediff.mjs.map +1 -1
  261. package/dist/capture/render.mjs +53 -0
  262. package/dist/capture/render.mjs.map +1 -0
  263. package/dist/capture/scratch.d.mts +44 -0
  264. package/dist/capture/scratch.mjs +138 -0
  265. package/dist/capture/scratch.mjs.map +1 -0
  266. package/dist/capture/shard-plan.mjs +128 -0
  267. package/dist/capture/shard-plan.mjs.map +1 -0
  268. package/dist/capture/shards/context.mjs +51 -0
  269. package/dist/capture/shards/context.mjs.map +1 -0
  270. package/dist/capture/shards/execute.mjs +174 -0
  271. package/dist/capture/shards/execute.mjs.map +1 -0
  272. package/dist/capture/shards/fan-out.mjs +126 -0
  273. package/dist/capture/shards/fan-out.mjs.map +1 -0
  274. package/dist/capture/shards/history.mjs +35 -0
  275. package/dist/capture/shards/history.mjs.map +1 -0
  276. package/dist/capture/shards/reduce.mjs +97 -0
  277. package/dist/capture/shards/reduce.mjs.map +1 -0
  278. package/dist/capture/sizing.mjs +1 -11
  279. package/dist/capture/sizing.mjs.map +1 -1
  280. package/dist/capture/skip-checks.mjs +2 -65
  281. package/dist/capture/skip-checks.mjs.map +1 -1
  282. package/dist/capture/statics.d.mts +7 -8
  283. package/dist/capture/statics.mjs +25 -71
  284. package/dist/capture/statics.mjs.map +1 -1
  285. package/dist/capture/storybook-urls.d.mts +40 -0
  286. package/dist/capture/storybook-urls.mjs +41 -0
  287. package/dist/capture/storybook-urls.mjs.map +1 -0
  288. package/dist/capture/storybook.d.mts +12 -4
  289. package/dist/capture/storybook.mjs +56 -16
  290. package/dist/capture/storybook.mjs.map +1 -1
  291. package/dist/capture/target.mjs +21 -0
  292. package/dist/capture/target.mjs.map +1 -0
  293. package/dist/capture/targets.d.mts +25 -0
  294. package/dist/capture/targets.mjs +32 -0
  295. package/dist/capture/targets.mjs.map +1 -0
  296. package/dist/capture/tests.d.mts +37 -0
  297. package/dist/capture/tests.mjs +126 -0
  298. package/dist/capture/tests.mjs.map +1 -0
  299. package/dist/capture/token-chunks.mjs +74 -0
  300. package/dist/capture/token-chunks.mjs.map +1 -0
  301. package/dist/capture.d.mts +60 -7
  302. package/dist/capture.mjs +48 -3
  303. package/dist/config.d.mts +121 -12
  304. package/dist/config.mjs +9 -6
  305. package/dist/config.mjs.map +1 -1
  306. package/dist/diff.d.mts +9 -3
  307. package/dist/diff.mjs +16 -3
  308. package/dist/diff.mjs.map +1 -0
  309. package/dist/index.d.mts +1 -1
  310. package/dist/insights/budget.d.mts +20 -0
  311. package/dist/insights/budget.mjs +33 -0
  312. package/dist/insights/budget.mjs.map +1 -0
  313. package/dist/insights/envelope.d.mts +59 -0
  314. package/dist/insights/envelope.mjs +60 -0
  315. package/dist/insights/envelope.mjs.map +1 -0
  316. package/dist/insights/evidence-health.d.mts +32 -0
  317. package/dist/insights/evidence-health.mjs +28 -0
  318. package/dist/insights/evidence-health.mjs.map +1 -0
  319. package/dist/insights/evidence.d.mts +55 -0
  320. package/dist/insights/evidence.mjs +64 -0
  321. package/dist/insights/evidence.mjs.map +1 -0
  322. package/dist/insights/hash.d.mts +18 -0
  323. package/dist/insights/hash.mjs +21 -0
  324. package/dist/insights/hash.mjs.map +1 -0
  325. package/dist/insights/limits.d.mts +24 -0
  326. package/dist/insights/limits.mjs +24 -0
  327. package/dist/insights/limits.mjs.map +1 -0
  328. package/dist/insights/prompts/v1.d.mts +13 -0
  329. package/dist/insights/prompts/v1.mjs +34 -0
  330. package/dist/insights/prompts/v1.mjs.map +1 -0
  331. package/dist/insights/redact.d.mts +9 -0
  332. package/dist/insights/redact.mjs +24 -0
  333. package/dist/insights/redact.mjs.map +1 -0
  334. package/dist/insights/text.mjs +44 -0
  335. package/dist/insights/text.mjs.map +1 -0
  336. package/dist/insights.d.mts +11 -0
  337. package/dist/insights.mjs +12 -0
  338. package/dist/logger.mjs +17 -1
  339. package/dist/logger.mjs.map +1 -1
  340. package/dist/models/ai-budget-alert.d.mts +23 -0
  341. package/dist/models/ai-budget-alert.mjs +38 -0
  342. package/dist/models/ai-budget-alert.mjs.map +1 -0
  343. package/dist/models/ai-usage.d.mts +40 -0
  344. package/dist/models/ai-usage.mjs +61 -0
  345. package/dist/models/ai-usage.mjs.map +1 -0
  346. package/dist/models/baseline-archive.d.mts +84 -0
  347. package/dist/models/baseline-archive.mjs +106 -0
  348. package/dist/models/baseline-archive.mjs.map +1 -0
  349. package/dist/models/baseline-export.d.mts +19 -0
  350. package/dist/models/baseline-export.mjs +136 -0
  351. package/dist/models/baseline-export.mjs.map +1 -0
  352. package/dist/models/baseline-import.mjs +118 -0
  353. package/dist/models/baseline-import.mjs.map +1 -0
  354. package/dist/models/baseline-transfer.d.mts +49 -0
  355. package/dist/models/baseline-transfer.mjs +121 -0
  356. package/dist/models/baseline-transfer.mjs.map +1 -0
  357. package/dist/models/baseline.d.mts +32 -5
  358. package/dist/models/baseline.mjs +65 -20
  359. package/dist/models/baseline.mjs.map +1 -1
  360. package/dist/models/build-component.d.mts +28 -0
  361. package/dist/models/build-component.mjs +55 -0
  362. package/dist/models/build-component.mjs.map +1 -0
  363. package/dist/models/build-review-status.d.mts +29 -0
  364. package/dist/models/build-review-status.mjs +37 -0
  365. package/dist/models/build-review-status.mjs.map +1 -0
  366. package/dist/models/build-review.d.mts +28 -0
  367. package/dist/models/build-review.mjs +54 -0
  368. package/dist/models/build-review.mjs.map +1 -0
  369. package/dist/models/build.d.mts +25 -3
  370. package/dist/models/build.mjs +50 -11
  371. package/dist/models/build.mjs.map +1 -1
  372. package/dist/models/capture-attempt.d.mts +7 -1
  373. package/dist/models/capture-attempt.mjs +29 -4
  374. package/dist/models/capture-attempt.mjs.map +1 -1
  375. package/dist/models/capture-job.d.mts +106 -0
  376. package/dist/models/capture-job.mjs +288 -0
  377. package/dist/models/capture-job.mjs.map +1 -0
  378. package/dist/models/capture-log.d.mts +1 -1
  379. package/dist/models/capture-log.mjs +4 -3
  380. package/dist/models/capture-log.mjs.map +1 -1
  381. package/dist/models/capture-shard.d.mts +62 -0
  382. package/dist/models/capture-shard.mjs +190 -0
  383. package/dist/models/capture-shard.mjs.map +1 -0
  384. package/dist/models/changeset.d.mts +48 -0
  385. package/dist/models/changeset.mjs +81 -0
  386. package/dist/models/changeset.mjs.map +1 -0
  387. package/dist/models/columns.mjs +19 -0
  388. package/dist/models/columns.mjs.map +1 -0
  389. package/dist/models/comment.d.mts +4 -1
  390. package/dist/models/comment.mjs +7 -4
  391. package/dist/models/comment.mjs.map +1 -1
  392. package/dist/models/component.d.mts +43 -0
  393. package/dist/models/component.mjs +60 -0
  394. package/dist/models/component.mjs.map +1 -0
  395. package/dist/models/connections.d.mts +41 -0
  396. package/dist/models/connections.mjs +112 -0
  397. package/dist/models/connections.mjs.map +1 -0
  398. package/dist/models/content-ref.d.mts +1 -1
  399. package/dist/models/content-ref.mjs +1 -1
  400. package/dist/models/content-ref.mjs.map +1 -1
  401. package/dist/models/credentials.mjs +12 -2
  402. package/dist/models/credentials.mjs.map +1 -1
  403. package/dist/models/design-credentials.d.mts +41 -0
  404. package/dist/models/design-credentials.mjs +86 -0
  405. package/dist/models/design-credentials.mjs.map +1 -0
  406. package/dist/models/design-health.d.mts +16 -0
  407. package/dist/models/design-health.mjs +25 -0
  408. package/dist/models/design-health.mjs.map +1 -0
  409. package/dist/models/design-nodes.d.mts +83 -0
  410. package/dist/models/design-nodes.mjs +222 -0
  411. package/dist/models/design-nodes.mjs.map +1 -0
  412. package/dist/models/design-renders.mjs +74 -0
  413. package/dist/models/design-renders.mjs.map +1 -0
  414. package/dist/models/design-resolve.d.mts +29 -0
  415. package/dist/models/design-resolve.mjs +41 -0
  416. package/dist/models/design-resolve.mjs.map +1 -0
  417. package/dist/models/design.d.mts +39 -0
  418. package/dist/models/design.mjs +90 -0
  419. package/dist/models/design.mjs.map +1 -0
  420. package/dist/models/inherited-ratio.d.mts +21 -0
  421. package/dist/models/inherited-ratio.mjs +22 -0
  422. package/dist/models/inherited-ratio.mjs.map +1 -0
  423. package/dist/models/insight.d.mts +70 -0
  424. package/dist/models/insight.mjs +162 -0
  425. package/dist/models/insight.mjs.map +1 -0
  426. package/dist/models/label.d.mts +4 -2
  427. package/dist/models/label.mjs +25 -10
  428. package/dist/models/label.mjs.map +1 -1
  429. package/dist/models/member.d.mts +1 -1
  430. package/dist/models/member.mjs +5 -4
  431. package/dist/models/member.mjs.map +1 -1
  432. package/dist/models/notification-channel.d.mts +37 -3
  433. package/dist/models/notification-channel.mjs +88 -9
  434. package/dist/models/notification-channel.mjs.map +1 -1
  435. package/dist/models/notification-subscription.d.mts +1 -2
  436. package/dist/models/notification-subscription.mjs +7 -9
  437. package/dist/models/notification-subscription.mjs.map +1 -1
  438. package/dist/models/project-group-mapping.d.mts +6 -1
  439. package/dist/models/project-group-mapping.mjs +14 -4
  440. package/dist/models/project-group-mapping.mjs.map +1 -1
  441. package/dist/models/project.d.mts +9 -1
  442. package/dist/models/project.mjs +9 -4
  443. package/dist/models/project.mjs.map +1 -1
  444. package/dist/models/public-origin.d.mts +63 -0
  445. package/dist/models/public-origin.mjs +114 -0
  446. package/dist/models/public-origin.mjs.map +1 -0
  447. package/dist/models/review-switch-off.d.mts +14 -0
  448. package/dist/models/review-switch-off.mjs +26 -0
  449. package/dist/models/review-switch-off.mjs.map +1 -0
  450. package/dist/models/site-settings.d.mts +23 -0
  451. package/dist/models/site-settings.mjs +48 -0
  452. package/dist/models/site-settings.mjs.map +1 -0
  453. package/dist/models/snapshot.d.mts +36 -1
  454. package/dist/models/snapshot.mjs +50 -3
  455. package/dist/models/snapshot.mjs.map +1 -1
  456. package/dist/models/token.d.mts +13 -1
  457. package/dist/models/token.mjs +23 -5
  458. package/dist/models/token.mjs.map +1 -1
  459. package/dist/models/usage.d.mts +76 -0
  460. package/dist/models/usage.mjs +149 -0
  461. package/dist/models/usage.mjs.map +1 -0
  462. package/dist/models/user.d.mts +1 -1
  463. package/dist/models/user.mjs +4 -3
  464. package/dist/models/user.mjs.map +1 -1
  465. package/dist/models/webhook.d.mts +15 -1
  466. package/dist/models/webhook.mjs +33 -4
  467. package/dist/models/webhook.mjs.map +1 -1
  468. package/dist/models.d.mts +26 -3
  469. package/dist/models.mjs +27 -5
  470. package/dist/options.d.mts +18 -0
  471. package/dist/options.mjs +90 -0
  472. package/dist/options.mjs.map +1 -0
  473. package/dist/paths.d.mts +19 -4
  474. package/dist/paths.mjs +51 -10
  475. package/dist/paths.mjs.map +1 -1
  476. package/dist/retention/ai.d.mts +18 -0
  477. package/dist/retention/ai.mjs +23 -0
  478. package/dist/retention/ai.mjs.map +1 -0
  479. package/dist/retention/pending.mjs +47 -0
  480. package/dist/retention/pending.mjs.map +1 -0
  481. package/dist/retention/screenshot-sweep.d.mts +51 -0
  482. package/dist/retention/screenshot-sweep.mjs +128 -0
  483. package/dist/retention/screenshot-sweep.mjs.map +1 -0
  484. package/dist/retention.d.mts +16 -2
  485. package/dist/retention.mjs +71 -14
  486. package/dist/retention.mjs.map +1 -1
  487. package/dist/schema/baseline.d.mts +6 -0
  488. package/dist/schema/build-component.d.mts +25 -0
  489. package/dist/schema/build-review.d.mts +17 -0
  490. package/dist/schema/build.d.mts +7 -0
  491. package/dist/schema/capture-job.d.mts +60 -0
  492. package/dist/schema/capture-shard.d.mts +35 -0
  493. package/dist/schema/comment.d.mts +2 -0
  494. package/dist/schema/connection.d.mts +24 -0
  495. package/dist/schema/design.d.mts +58 -0
  496. package/dist/schema/insight.d.mts +54 -0
  497. package/dist/schema/notification.d.mts +4 -0
  498. package/dist/schema/project.d.mts +21 -0
  499. package/dist/schema/site-setting.d.mts +21 -0
  500. package/dist/schema/snapshot.d.mts +12 -0
  501. package/dist/schema/usage.d.mts +30 -0
  502. package/dist/schema.d.mts +11 -3
  503. package/dist/serverless.d.mts +21 -0
  504. package/dist/serverless.mjs +37 -0
  505. package/dist/serverless.mjs.map +1 -0
  506. package/dist/test-helpers/create-project.d.mts +1 -1
  507. package/dist/test-helpers/deferred.d.mts +39 -0
  508. package/dist/test-helpers/deferred.mjs +61 -0
  509. package/dist/test-helpers/deferred.mjs.map +1 -0
  510. package/dist/test-helpers/design-contract.d.mts +21 -0
  511. package/dist/test-helpers/design-contract.mjs +40 -0
  512. package/dist/test-helpers/design-contract.mjs.map +1 -0
  513. package/dist/test-helpers/fake-database.mjs +14 -2
  514. package/dist/test-helpers/fake-database.mjs.map +1 -1
  515. package/dist/test-helpers/fake-design.d.mts +43 -0
  516. package/dist/test-helpers/fake-design.mjs +114 -0
  517. package/dist/test-helpers/fake-design.mjs.map +1 -0
  518. package/dist/test-helpers/fake-notifier.d.mts +21 -0
  519. package/dist/test-helpers/fake-notifier.mjs +44 -0
  520. package/dist/test-helpers/fake-notifier.mjs.map +1 -0
  521. package/dist/test-helpers/fake-tables.mjs +255 -67
  522. package/dist/test-helpers/fake-tables.mjs.map +1 -1
  523. package/dist/test-helpers/manual-clock.d.mts +27 -0
  524. package/dist/test-helpers/manual-clock.mjs +56 -0
  525. package/dist/test-helpers/manual-clock.mjs.map +1 -0
  526. package/dist/test-helpers/notifier-contract.d.mts +7 -1
  527. package/dist/test-helpers/notifier-contract.mjs +32 -3
  528. package/dist/test-helpers/notifier-contract.mjs.map +1 -1
  529. package/dist/test-helpers/queue-contract.d.mts +16 -2
  530. package/dist/test-helpers/queue-contract.mjs +195 -1
  531. package/dist/test-helpers/queue-contract.mjs.map +1 -1
  532. package/dist/test-helpers/queue-multi-instance.d.mts +20 -0
  533. package/dist/test-helpers/queue-multi-instance.mjs +206 -0
  534. package/dist/test-helpers/queue-multi-instance.mjs.map +1 -0
  535. package/dist/test-helpers/runner-contract.mjs +11 -0
  536. package/dist/test-helpers/runner-contract.mjs.map +1 -1
  537. package/dist/test-helpers/sql-chunks.mjs +23 -0
  538. package/dist/test-helpers/sql-chunks.mjs.map +1 -1
  539. package/dist/test-helpers/storage-contract.mjs +1 -1
  540. package/dist/test-helpers.d.mts +9 -4
  541. package/dist/test-helpers.mjs +8 -3
  542. package/dist/types.d.mts +14 -3
  543. package/dist/types.mjs +21 -4
  544. package/dist/types.mjs.map +1 -1
  545. package/dist/urls.d.mts +4 -0
  546. package/dist/urls.mjs +11 -2
  547. package/dist/urls.mjs.map +1 -1
  548. package/dist/utils/adaptive-concurrency.d.mts +66 -0
  549. package/dist/utils/adaptive-concurrency.mjs +149 -0
  550. package/dist/utils/adaptive-concurrency.mjs.map +1 -0
  551. package/dist/utils/connect-retry.d.mts +26 -0
  552. package/dist/utils/connect-retry.mjs +43 -0
  553. package/dist/utils/connect-retry.mjs.map +1 -0
  554. package/dist/utils/environment.d.mts +19 -0
  555. package/dist/utils/environment.mjs +59 -0
  556. package/dist/utils/environment.mjs.map +1 -0
  557. package/dist/utils/http.d.mts +17 -1
  558. package/dist/utils/http.mjs +22 -3
  559. package/dist/utils/http.mjs.map +1 -1
  560. package/dist/utils/map-adaptive.d.mts +15 -0
  561. package/dist/utils/map-adaptive.mjs +72 -0
  562. package/dist/utils/map-adaptive.mjs.map +1 -0
  563. package/dist/utils/map-limit.d.mts +10 -0
  564. package/dist/utils/map-limit.mjs +32 -0
  565. package/dist/utils/map-limit.mjs.map +1 -0
  566. package/dist/utils/page-limiter.d.mts +37 -0
  567. package/dist/utils/page-limiter.mjs +56 -0
  568. package/dist/utils/page-limiter.mjs.map +1 -0
  569. package/dist/utils/public-origin.d.mts +20 -0
  570. package/dist/utils/public-origin.mjs +75 -0
  571. package/dist/utils/public-origin.mjs.map +1 -0
  572. package/dist/utils/redact.mjs +3 -0
  573. package/dist/utils/redact.mjs.map +1 -1
  574. package/dist/utils/remote-environment.d.mts +39 -0
  575. package/dist/utils/remote-environment.mjs +114 -0
  576. package/dist/utils/remote-environment.mjs.map +1 -0
  577. package/dist/utils/resources.d.mts +64 -0
  578. package/dist/utils/resources.mjs +122 -0
  579. package/dist/utils/resources.mjs.map +1 -0
  580. package/dist/utils/screenshot-store.d.mts +15 -0
  581. package/dist/utils/screenshot-store.mjs +41 -0
  582. package/dist/utils/screenshot-store.mjs.map +1 -0
  583. package/dist/utils/session-gate.d.mts +22 -0
  584. package/dist/utils/session-gate.mjs +53 -0
  585. package/dist/utils/session-gate.mjs.map +1 -0
  586. package/dist/utils/storybook-token.d.mts +81 -0
  587. package/dist/utils/storybook-token.mjs +134 -0
  588. package/dist/utils/storybook-token.mjs.map +1 -0
  589. package/dist/utils/storybook-url.d.mts +15 -0
  590. package/dist/utils/storybook-url.mjs +21 -0
  591. package/dist/utils/storybook-url.mjs.map +1 -0
  592. package/dist/utils/timing.mjs +1 -1
  593. package/dist/utils/timing.mjs.map +1 -1
  594. package/dist/utils/zip-read.mjs +129 -0
  595. package/dist/utils/zip-read.mjs.map +1 -0
  596. package/dist/utils/zip-write.d.mts +18 -0
  597. package/dist/utils/zip-write.mjs +188 -0
  598. package/dist/utils/zip-write.mjs.map +1 -0
  599. package/dist/utils.d.mts +17 -3
  600. package/dist/utils.mjs +18 -4
  601. package/package.json +32 -20
  602. package/dist/adapter/capture-runner.mjs.map +0 -1
  603. package/dist/adapter/git-host/comments.d.mts +0 -41
  604. package/dist/adapter/git-host/comments.mjs +0 -54
  605. package/dist/adapter/git-host/comments.mjs.map +0 -1
  606. package/dist/adapter/git-host/helpers.d.mts +0 -13
  607. package/dist/adapter/git-host/helpers.mjs +0 -30
  608. package/dist/adapter/git-host/helpers.mjs.map +0 -1
  609. package/dist/adapter/git-host.d.mts +0 -42
  610. package/dist/capture/queue.d.mts +0 -38
  611. package/dist/capture/queue.mjs +0 -98
  612. package/dist/capture/queue.mjs.map +0 -1
  613. package/dist/capture/recovery.d.mts +0 -21
  614. package/dist/capture/recovery.mjs +0 -83
  615. package/dist/capture/recovery.mjs.map +0 -1
  616. package/dist/capture/status-fanout.mjs +0 -72
  617. package/dist/capture/status-fanout.mjs.map +0 -1
  618. package/dist/diff/engine.d.mts +0 -16
  619. package/dist/diff/engine.mjs +0 -87
  620. package/dist/diff/engine.mjs.map +0 -1
  621. package/dist/diff/options.d.mts +0 -42
  622. package/dist/diff/options.mjs +0 -15
  623. package/dist/diff/options.mjs.map +0 -1
  624. package/dist/models/status-config.d.mts +0 -38
  625. package/dist/models/status-config.mjs +0 -63
  626. package/dist/models/status-config.mjs.map +0 -1
  627. package/dist/schema/status-config.d.mts +0 -16
  628. package/dist/test-helpers/git-contract.d.mts +0 -11
  629. package/dist/test-helpers/git-contract.mjs +0 -34
  630. package/dist/test-helpers/git-contract.mjs.map +0 -1
  631. /package/dist/adapter/{git-host.mjs → oauth.mjs} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @storyshelf/core
2
2
 
3
- The domain layer of StoryShelf: adapter interfaces, models, capture pipeline, diff engine, and retention logic — with no HTTP dependency, so workers import it without pulling a server. The Hono router lives in `@storyshelf/app`. Compose pluggable adapters into a complete self-hosted visual testing server.
3
+ The domain layer of StoryShelf: adapter interfaces, models, capture pipeline, diff engine, and retention logic — with no HTTP dependency, so the capture consumer imports it without pulling a server. The Hono router lives in `@storyshelf/app`. Compose pluggable adapters into a complete self-hosted visual testing server.
4
4
 
5
5
  ## Install
6
6
 
@@ -22,13 +22,12 @@ import { createShelfApp } from "@storyshelf/app";
22
22
  const app = createShelfApp({
23
23
  database, // DatabaseAdapter
24
24
  storage, // StorageAdapter
25
- captureRunner, // CaptureRunner (optional)
25
+ testing: { runner: captureRunner, concurrency: 2, compare: { threads: 2 } }, // capture pipeline + screenshot comparison (optional; absent = Storybook hosting only)
26
26
  auth, // Auth from @storyshelf/auth (optional)
27
- gitHosts, // GitHostProvider[] (optional)
27
+ notifications: { notifiers: [...chatNotifiers, ...gitNotifiers] }, // NotifierProvider[]: chat, email and git (optional)
28
28
  logger, // pino Logger (optional; built internally if omitted)
29
29
  ui: { name: "My Shelf" }, // UIConfig (optional)
30
30
  config: {
31
- captureConcurrency: 2,
32
31
  purgeTtlDays: 30,
33
32
  branchTtlDays: 30,
34
33
  branchGcIntervalMs: 86_400_000,
@@ -39,23 +38,37 @@ const app = createShelfApp({
39
38
  serve({ fetch: app.fetch, port: 3000 });
40
39
  ```
41
40
 
41
+ Adapter `setup` hooks kick off in the background when the router is created. Await them before serving for fail-fast startup (or let the first request gate on settlement), and tear down adapters on shutdown:
42
+
43
+ ```ts
44
+ await app.lifecycle.setup();
45
+
46
+ const server = serve({ fetch: app.fetch, port: 3000 });
47
+ process.on("SIGTERM", () => {
48
+ app.lifecycle
49
+ .teardown()
50
+ .then(() => server.close())
51
+ .catch(() => {});
52
+ });
53
+ ```
54
+
42
55
  ## API
43
56
 
44
57
  ### `createShelfApp(options: ShelfOptions): Hono`
45
58
 
46
59
  Assembles the router from the provided adapters. `ShelfOptions`:
47
60
 
48
- | Option | Type | Description |
49
- | --------------- | --------------------------- | ---------------------------------------------------------------------------------------- |
50
- | `database` | `DatabaseAdapter` | **Required.** Data access. |
51
- | `storage` | `StorageAdapter` | **Required.** Blob storage for screenshots, diffs, storybook archives. |
52
- | `captureRunner` | `CaptureRunner` | Optional. Enables the async capture pipeline (pure renderer). |
53
- | `captureQueue` | `CaptureQueue` | Optional. Queue adapter; defaults to `InMemoryCaptureQueue`. |
54
- | `auth` | `Auth` (`@storyshelf/auth`) | Optional. Enables auth and the login UI. |
55
- | `gitHosts` | `GitHostProvider[]` | Optional. Git-host adapters (GitHub/GitLab) for status checks, merge gates, PR comments. |
56
- | `logger` | `Logger` (pino) | Optional. Shared logger. Construct a fallback via `createShelfLogger()`. |
57
- | `ui` | `UIConfig` | Optional. UI branding. |
58
- | `config` | `ShelfConfig` | Optional. Server behavior. |
61
+ | Option | Type | Description |
62
+ | ----------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | `database` | `DatabaseAdapter` | **Required.** Data access. |
64
+ | `storage` | `StorageAdapter` | **Required.** Blob storage for screenshots, diffs, storybook archives. |
65
+ | `testing` | `{ runner, concurrency?, compare?, images? }` | Optional. Enables the async capture pipeline: `runner` (pure renderer; required, `testing: {}` throws; captures queue on the database), `concurrency` (jobs at once; default 2 on hosts with ≥ 2 CPUs and ≥ 3 GB, otherwise 1), `retries` (default 2). Absent means Storybook hosting only. `workerEntry` runs captures in a forked child the app pushes jobs to (`runCaptureChild`); `mode` is `auto` (default), `in-process` or `fork`. |
66
+ | `testing.compare` | `{ threads? }` | Optional. Worker threads for pixel diffs (default CPU count − 1; `0` = main thread). Also serves the re-diff endpoint. Overrides `STORYSHELF_DIFF_WORKERS`. |
67
+ | `notifications` | `{ notifiers?, emailSender?, config? }` | Optional. `notifiers` (Slack/Teams/email providers and the GitHub/GitLab git providers of `@storyshelf/notify-git`), `emailSender` (transport whose lifecycle hooks run with the app's), `config` (`fromEmail`, `fromName`, `footerText`, `slackUsername`). |
68
+ | `auth` | `Auth` (`@storyshelf/auth`) | Optional. Enables auth and the login UI. |
69
+ | `logger` | `Logger` (pino) | Optional. Shared logger. Construct a fallback via `createShelfLogger()`. |
70
+ | `ui` | `UIConfig` | Optional. UI branding. |
71
+ | `config` | `ShelfConfig` | Optional. Server behavior. |
59
72
 
60
73
  ### `ShelfConfig`
61
74
 
@@ -63,13 +76,14 @@ Assembles the router from the provided adapters. `ShelfOptions`:
63
76
  interface ShelfConfig {
64
77
  secret?: string; // session signing secret
65
78
  publishedBaseDomain?: string; // for published storybook URLs
66
- captureConcurrency?: number; // concurrent capture jobs (default 2)
67
- scratchDir?: string; // capture working directory (required with captureRunner)
79
+ scratchDir?: string; // working directory for publishing and capture (default: <os.tmpdir()>/storyshelf)
68
80
  purgeTtlDays?: number; // purge builds older than N days
69
81
  branchTtlDays?: number | null; // branch baseline TTL, days; null disables GC (default 30)
70
82
  branchGcIntervalMs?: number; // branch GC interval, ms; daily via interval clock (default 86_400_000)
71
83
  maxUploadBytes?: number; // single-zip upload cap (default 1 GiB)
72
- maxInlineUnzipSize?: number; // inline statics extraction cap; unset = capture-only
84
+ maxInlineUnzipSize?: number; // largest zip extracted inline at upload (default 50 MB; 0 = always a publish job)
85
+ maxZipEntries?: number; // most entries a zip may hold (default 50 000)
86
+ maxUnzippedBytes?: number; // most uncompressed bytes a zip may expand to (default 2 GiB)
73
87
  viewports?: Viewport[]; // capture viewports
74
88
  }
75
89
  ```
@@ -95,7 +109,8 @@ All adapters are constructor-injected (no AsyncLocalStorage). See `docs/architec
95
109
  - `Auth` (`@storyshelf/auth`) — the shelf authentication singleton: `check(request)`, `handler` (mount at `/api/auth/*`), `loginMethods()`, invites, sessions, passkeys. `AuthUser` and the shared `SESSION_COOKIE` live in `core/types`.
96
110
  - `CaptureRunner` (`core/adapter/capture-runner`) — a **pure capture renderer**: `render(input) => RenderResult`, `cancel(buildId)`. Also exports `RenderedSnapshot`, `RenderResult`, `StoryEntry`, `StorySourceAdapter`, `Viewport`.
97
111
  - `CaptureQueue` (`core/adapter/capture-queue`) — `enqueue({ buildId, reqId? })`, plus `status`, `active`, `recent`. Also exports `CaptureJob`, `QueueEntry`, `JobStatus`.
98
- - `GitHostProvider` / `GitHostAdapter` (`core/adapter/git-host`) — set commit status checks, detect merges, and upsert PR comments. Real providers ship in `@storyshelf/git-github` and `@storyshelf/git-gitlab`. Also exports `CheckStatus`.
112
+ - `DesignProvider` / `DesignClient` (`core/adapter/design`) — validate design links and fetch file metadata and rendered previews from a design tool. The Figma provider ships in `@storyshelf/design-figma`; also exports `parseDesignUrl` and `InvalidDesignUrlError`.
113
+ - `NotifierProvider` / `NotifierAdapter` (`core/adapter/notifier`) — one family with two delivery kinds: `message` providers (`@storyshelf/notify-chat`, `@storyshelf/notify-email`) `send` a formatted message; `state` providers (`@storyshelf/notify-git`: GitHub, GitLab) `setState` a commit status or pull-request comment, idempotently. Also exports `emitNotifications`, `statusesForBuild` (the pure build-to-statuses function), `writeBuildState`, `isStateProvider`, `NotifierState` and `NotifierStateTarget`; `core/capture` exports the `notify` job (`createBuildStatePublisher`, `createNotifyHandler`, `createNotifyEnqueuer`).
99
114
 
100
115
  ### Logging
101
116
 
@@ -105,11 +120,15 @@ All adapters are constructor-injected (no AsyncLocalStorage). See `docs/architec
105
120
 
106
121
  Import from `core/capture`, `core/diff`, and the model entries — never from the barrel:
107
122
 
108
- - `executeCaptureJob({ buildId, reqId }, deps)` (`core/capture`) — the capture **orchestrator**: loads the build, marks it `capturing`, extracts the uploaded archive into `scratchDir`, discovers stories, delegates rendering to a pure `CaptureRunner`, and persists. `createShelfApp` wires it into a `CaptureQueue` when `capture` is supplied (and requires `ShelfConfig.scratchDir`). Also exports `CaptureJobOptions`.
123
+ - `executeCaptureJob({ buildId, reqId }, deps)` (`core/capture`) — the capture **orchestrator**: loads the build, marks it `capturing`, extracts the uploaded archive into `scratchDir`, discovers stories, delegates rendering to a pure `CaptureRunner`, and persists. `createShelfApp` wires it into a `CaptureQueue` when `testing` is supplied (and requires `ShelfConfig.scratchDir`). Also exports `CaptureJobOptions`.
109
124
  - `persistCapture(ctx: CaptureContext)` (`core/capture`) — writes screenshots, diffs against the branch baseline, creates snapshots, and finalizes a build from a pure renderer's `captures`. Also exports `CaptureContext`.
110
125
  - `StorybookAdapter` (`core/capture`) — reads a built Storybook's `index.json`/`stories.json`.
111
- - `InMemoryCaptureQueue` (`core/capture`) — in-process, concurrency-limited queue for long-lived hosts; supply a remote queue with a separate worker for serverless.
112
- - `diffImages(baseline: Buffer, current: Buffer, options: DiffOptions): DiffResult` (`core/diff`) — pixelmatch-based diff. Also exports `DiffOptions`, `DiffResult`.
126
+ - `createCatalogLoader({ db, storage })`, `createCatalogHook(loader)`, `catalogueBuild`, `parseStorybookIndex`, `groupComponents`, `componentBuildHistory` (`core/capture`) — the Storybook catalog of a published build (ADR 0006, decision 9): `catalog.json` plus one `build_components` row per component, written by the `afterPublish` hook, loaded through an in-process LRU and catalogued lazily for older builds. `BuildComponentModel` (`core/models`) reads and replaces the rows.
127
+ - `BuildReviewModel`, `deriveReviewStatus`, `latestVerdicts` (`core/models`) — build-level review (ADR 0013, decision 3): `build_reviews` rows (a reviewer's newest row is their verdict) and the pure rule that turns them into `approved`, `rejected` or `pending` when `testing` is off and review is on. `publishVerdict` (`core/capture`) takes the project's review switch: a published non-default build is accepted when review is off.
128
+ - `computeChangeset`, `changesetOf`, `findChangesetBaseline`, `acceptPendingWithoutWork` (`core/models`) — the catalog changeset of a build (components added, removed and changed against its baseline build, ADR 0013 decision 8) and the pass that accepts a project's idle pending builds when review is turned off. `Retention.purge` (`core/retention`) also removes `pending` builds idle past the retention window.
129
+ - `createDatabaseCaptureQueue(db, options)` (`core/capture`) — a `PollableCaptureQueue` on the app's own database (`capture_jobs`; ADR 0006): per-attempt claim rows fence concurrent instances, leases follow progress, retries back off, `cancel(jobId | buildId)` reaches the holder within 5 s. Not wired into the app yet. `startPollLoop` and `keepJobLease` are the consumer-side helpers.
130
+ - `createCaptureConsumer({ queue, capture, handlers, config })` (`core/capture`) — the consumer loop over any `PollableCaptureQueue`: a handler per job kind (`capture` runs the core dispatch), a slot before each poll, retries with exponential backoff and the final-attempt rule, lease kept by progress, cancel and lease loss stop the run, `stop()` drains. `runCaptureChild` (forked capture) runs it over IPC.
131
+ - `diffImages(baseline: Buffer, current: Buffer, options: DiffOptions): Promise<DiffResult>` (`core/diff`) — pixelmatch-based diff (async since 0.7: the optional `sharp` codec is async). An optional fourth `codec` argument selects the PNG codec and defaults to `pngjs`. Re-exported from `@storyshelf/image`, which owns the image engines; also exports `diffImagesAsync` (worker pool), `configureImages({ engine, threads })`, `DiffOptions`, `DiffResult`. `configureDiffPool` remains as a deprecated alias.
113
132
  - Models, schema, and row types back every entity; retention runs inside the router (`Retention.purge` for builds + `Retention.purgeStaleBranches` for branch GC via `retention-timer.ts` daily sweep). (Models are private implementation details with no public entry — reach row types via `core/schema`.)
114
133
 
115
134
  ### Helpers
@@ -125,15 +144,13 @@ See `docs/architecture.md` and the ADRs in `docs/adr/`.
125
144
 
126
145
  ## Deployment targets
127
146
 
128
- The core router is runtime-agnostic (Web `Request`/`Response`, `fetch`, `crypto`, `URL`). The only Node-specific piece is the in-process `InMemoryCaptureQueue`, which suits long-lived Node servers; serverless runtimes swap in a remote `CaptureQueue` (e.g. `@storyshelf/queue-sqs`) plus a separate worker. You assemble a server for any platform — `storyshelf server init` generates a scaffold with the adapters you choose:
147
+ The core router is runtime-agnostic (Web `Request`/`Response`, `fetch`, `crypto`, `URL`). The Node-specific piece is the capture consumer and its optional forked child, which need a long-lived Node server: that is what the `testing` option turns on, and the database is the queue (ADR 0006). Without `testing` an instance only hosts Storybooks and runs on serverless platforms too. You assemble a server for any platform — `storyshelf server init` generates a scaffold with the adapters you choose:
129
148
 
130
- | Platform | Database | Storage | Capture queue | Server entry |
131
- | ------------------------------------------ | ------------------------------------- | -------------------------------- | ------------------------------- | -------------------------- |
132
- | **Vercel** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` (R2/S3) | Remote `CaptureQueue` + worker | Hono + `@hono/vercel-edge` |
133
- | **Cloudflare Workers** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` (R2) | Workers Queues `CaptureQueue` | Hono + Workers entry |
134
- | **Azure Functions** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` (Blob) | Azure Queues `CaptureQueue` | Hono + Azure handler |
135
- | **AWS Lambda** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` | SQS `CaptureQueue` | Hono + Lambda handler |
136
- | **Deno Deploy** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` | Custom `CaptureQueue` (Deno KV) | Hono + Deno entry |
137
- | **Bun / Node (VPS, Fly, Railway, Render)** | `db-sqlite` (+ `./bun-sqlite` on Bun) | `storage-local` / `storage-s3` | `InMemoryCaptureQueue` | `storyshelf-server serve` |
149
+ | Platform | Database | Storage | `testing` (capture) | Server entry |
150
+ | -------------------------------------------------------------------- | ------------------------------------- | ---------------------------------------------- | ------------------- | --------------------------------- |
151
+ | **Vercel, AWS Lambda, Azure Functions** | `@storyshelf/db-sqlite/turso` | `@storyshelf/storage-s3` | No (hosting only) | Hono + platform handler |
152
+ | **Cloudflare Workers** | `@storyshelf/db-sqlite/d1` or turso | `@storyshelf/storage-s3` (R2) | No (hosting only) | Hono + Workers entry |
153
+ | **Bun / Node (VPS, Fly, Railway, Render)** | `db-sqlite` (+ `./bun-sqlite` on Bun) | `storage-local` / `storage-s3` | Yes, database queue | `storyshelf-server serve` |
154
+ | **Container platforms (ECS, Cloud Run, Container Apps, Kubernetes)** | `db-postgres` / `db-mysql` | `storage-s3` / `storage-gcs` / `storage-azure` | Yes, database queue | `storyshelf server init` scaffold |
138
155
 
139
- All clouds are equal — pick the adapters that match your infrastructure. See the **Deployment** guide for recipes including a minimal Turso + S3 + `InMemoryCaptureQueue` example.
156
+ All clouds are equal — pick the adapters that match your infrastructure. See the **Deployment** guide for recipes including a minimal Turso + S3 example.
@@ -7,6 +7,8 @@ type JobStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
7
7
  /** Observable state of a single capture queue entry. */
8
8
  interface QueueEntry {
9
9
  buildId: string;
10
+ /** Set on the entry of a shard job; the build's own entry has none. */
11
+ shard?: string;
10
12
  status: JobStatus;
11
13
  queuedAt: string;
12
14
  startedAt?: string;
@@ -23,6 +25,11 @@ interface CaptureJob {
23
25
  * instead of starting a root span; absent means start a new trace.
24
26
  */
25
27
  traceparent?: string;
28
+ /**
29
+ * `capture_shards` row to render. Absent on a build job, which plans the build (and, when it is
30
+ * big, hands out shard jobs) or captures it whole; every transport carries it through unchanged.
31
+ */
32
+ shard?: string;
26
33
  }
27
34
  /** A job polled from a queue with transport metadata. */
28
35
  interface PollableJob extends CaptureJob {
@@ -30,9 +37,21 @@ interface PollableJob extends CaptureJob {
30
37
  receipt?: string;
31
38
  /** Number of delivery attempts already made (0 = first delivery). */
32
39
  attempts?: number;
40
+ /**
41
+ * Lease (visibility timeout / ack deadline / lock) in ms granted at poll
42
+ * time. The worker renews at a fraction of this while a capture runs;
43
+ * absent means the transport has no renewable lease.
44
+ */
45
+ leaseMs?: number;
33
46
  /** Raw transport message for debugging. */
34
47
  raw?: unknown;
35
48
  }
49
+ /**
50
+ * Outcome of renewing (or inspecting) a polled job's lease: `lost` means another consumer owns it
51
+ * now or the job already ended; `cancelled` means someone asked for the job to stop, and the holder
52
+ * should cancel its run and settle the job (queues without cancel never report it).
53
+ */
54
+ type LeaseRenewal = "ok" | "lost" | "cancelled";
36
55
  /**
37
56
  * A capture job queue, decoupled from the runtime.
38
57
  *
@@ -59,6 +78,12 @@ interface CaptureQueue extends Adapter<{
59
78
  active(): Promise<QueueEntry[]>;
60
79
  /** The most recent queue entries, newest first. */
61
80
  recent(limit: number): Promise<QueueEntry[]>;
81
+ /**
82
+ * Cancel by job id, or every unfinished job of a build by build id (every job kind of the build on the database queue). Optional. A job that has not
83
+ * started ends `cancelled` at once; a running one is flagged, and its holder sees `"cancelled"`
84
+ * from `extend`/`inspect`. Resolves true when anything matched.
85
+ */
86
+ cancel?(id: string): Promise<boolean>;
62
87
  }
63
88
  /** Extension for queues that support worker-side polling. */
64
89
  interface PollableCaptureQueue extends CaptureQueue {
@@ -68,12 +93,29 @@ interface PollableCaptureQueue extends CaptureQueue {
68
93
  }): Promise<PollableJob | null>;
69
94
  /** Acknowledge successful processing of a polled job. */
70
95
  ack(job: PollableJob): Promise<void>;
71
- /** Negatively acknowledge; requeue with optional delay when possible. */
96
+ /**
97
+ * Negatively acknowledge; requeue with optional delay when possible. `requeue: false` is a final
98
+ * failure: the job is dropped, and `error` says why for queues that keep a record of it.
99
+ */
72
100
  nack(job: PollableJob, options?: {
73
101
  requeue?: boolean;
74
102
  delayMs?: number;
103
+ error?: string;
75
104
  }): Promise<void>;
105
+ /**
106
+ * Extend the lease on an in-flight job by another `job.leaseMs`. Optional:
107
+ * queues without a renewable lease (e.g. Redis) omit it. May update
108
+ * `job.receipt` in place when the transport rotates it. Resolves `"lost"`
109
+ * only when the transport conclusively reports the message is no longer
110
+ * owned by this consumer; transient failures must reject.
111
+ */
112
+ extend?(job: PollableJob): Promise<LeaseRenewal>;
113
+ /**
114
+ * Read the job's state without renewing its lease: the holder's periodic cancel check.
115
+ * Optional; same outcomes as `extend`.
116
+ */
117
+ inspect?(job: PollableJob): Promise<LeaseRenewal>;
76
118
  }
77
119
  //#endregion
78
- export { CaptureJob, CaptureQueue, JobStatus, PollableCaptureQueue, PollableJob, QueueEntry };
120
+ export { CaptureJob, CaptureQueue, JobStatus, LeaseRenewal, PollableCaptureQueue, PollableJob, QueueEntry };
79
121
  //# sourceMappingURL=capture-queue.d.mts.map
@@ -1,10 +1,32 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- import { StoryEntry, StorySourceAdapter, Viewport } from "../capture/adapter.mjs";
3
+ import { StoryEntry, StoryParameters, StorySourceAdapter, Viewport } from "../capture/adapter.mjs";
4
+ import { BROWSER_NAMES, BrowserName, CaptureTarget, DEFAULT_BROWSER, ParsedTarget, RunnerTarget, TARGET_NAME_PATTERN, TargetLaunchError, TargetReach, TargetStatus, engineOf, isBrowserName, isCaptureTarget, parseTarget, tryParseTarget, unavailableReason } from "../adapters/capture-target.mjs";
5
+ import { TargetOffers, createTargetOffers } from "../adapters/capture-target-offers.mjs";
6
+ import { RemoteBrowser, RemoteConnection, RemoteOptions, RemoteProtocol, RemoteSupport, RemoteTarget, defineRemote, isRemoteBrowser, reachOf, remoteTargetsOf, scrubConnection } from "../adapters/remote-browser.mjs";
7
+ import { RenderRuns } from "../adapters/render-runs.mjs";
4
8
  import { Adapter } from "./metadata.mjs";
5
9
  import { JobStatus } from "./capture-queue.mjs";
6
10
  import { Logger } from "pino";
7
11
  //#region src/adapters/capture-runner.d.ts
12
+ /**
13
+ * The rendering environment a runner captured in. Two captures with the same environment (and
14
+ * engine and viewport) should produce identical pixels; a different one explains a visual diff
15
+ * that no code change caused. Every field is optional: runners report what they can.
16
+ */
17
+ interface CaptureEnvironment {
18
+ /** Browser build, as the driver reports it (for example `124.0.6367.29`). */
19
+ browserVersion?: string;
20
+ /**
21
+ * OS and CPU text rendering depends on: the host's `process.platform-arch` for a local browser;
22
+ * for a remote one what the browser reported (`linux`, `windows`), never the host's.
23
+ */
24
+ platform?: string;
25
+ /** Device pixel ratio the pages were rendered at. */
26
+ deviceScaleFactor?: number;
27
+ /** Digest of the installed system fonts, when they could be listed. */
28
+ fontsHash?: string;
29
+ }
8
30
  /** A screenshot produced by a capture renderer. */
9
31
  interface RenderedSnapshot {
10
32
  /** The rendered story (echoed back from the render request). */
@@ -15,6 +37,25 @@ interface RenderedSnapshot {
15
37
  viewport?: Viewport;
16
38
  /** PNG screenshot bytes. */
17
39
  screenshot: Buffer;
40
+ /** Target that produced the screenshot (the request's `target`); chromium when absent. */
41
+ browser?: CaptureTarget;
42
+ /**
43
+ * Wall-clock milliseconds the renderer spent on this capture, when it measured it. Recorded per
44
+ * snapshot and read back as the per-story cost a shard plan orders its work by (ADR 0005).
45
+ */
46
+ durationMs?: number;
47
+ /** Axe violation texts found on this capture (empty or absent: none, or not checked). */
48
+ a11y?: string[];
49
+ /**
50
+ * Set by the orchestrator when it already wrote the screenshot to storage
51
+ * (via `onCapture`); `screenshot` is then empty and must not be written again.
52
+ * Runners never set this.
53
+ */
54
+ stored?: boolean;
55
+ /** Where the orchestrator stored it (content-addressed); set together with `stored`. */
56
+ storedPath?: string;
57
+ /** Environment of the render pass that produced it; filled in by the orchestrator from {@link RenderResult.environment}. */
58
+ environment?: CaptureEnvironment;
18
59
  }
19
60
  /** A story/viewport that a renderer could not capture. */
20
61
  interface RenderFailure {
@@ -24,6 +65,8 @@ interface RenderFailure {
24
65
  viewportName: string;
25
66
  /** Error message. */
26
67
  error: string;
68
+ /** Target the failure happened on; chromium when absent. */
69
+ browser?: CaptureTarget;
27
70
  }
28
71
  /** The outcome of a render request. */
29
72
  interface RenderResult {
@@ -31,6 +74,17 @@ interface RenderResult {
31
74
  captures: RenderedSnapshot[];
32
75
  /** Story/viewport pairs the renderer could not capture. */
33
76
  failures: RenderFailure[];
77
+ /** What this render ran on; optional so third-party runners keep working. */
78
+ environment?: CaptureEnvironment;
79
+ }
80
+ /** What a runner reports for one Storybook `.test()` entry it ran in the iframe. */
81
+ interface TestOutcome {
82
+ /** The test entry's id (`<story id>:<test name slug>`). */
83
+ storyId: string;
84
+ status: "passed" | "failed";
85
+ /** Why it failed: the assertion, render error or timeout message. */
86
+ error?: string;
87
+ durationMs: number;
34
88
  }
35
89
  /**
36
90
  * A pure capture renderer.
@@ -43,12 +97,13 @@ interface RenderResult {
43
97
  * orchestrator's job (see `capture/orchestrator.ts`), keeping every adapter
44
98
  * implementation free of server concerns.
45
99
  */
46
- type BrowserName = "chromium" | "firefox" | "webkit" | "chrome";
47
- /** Browser names accepted for capture rendering (Chromium default). */
48
- declare const BROWSER_NAMES: readonly ["chromium", "firefox", "webkit", "chrome"];
49
100
  interface CaptureRunner extends Adapter<{
50
101
  readonly category: "capture-runner";
51
- readonly supportedBrowsers?: readonly BrowserName[];
102
+ /**
103
+ * Every target the runner offers, default first (ADR 0007, decision 1), with whether each can
104
+ * render now. A runner that omits it offers any target.
105
+ */
106
+ readonly targets?: readonly RunnerTarget[];
52
107
  }> {
53
108
  /**
54
109
  * Render configured viewports for the given stories of an extracted
@@ -59,6 +114,11 @@ interface CaptureRunner extends Adapter<{
59
114
  render(input: {
60
115
  /** Build being captured, used to correlate cancels with in-flight work. */
61
116
  buildId: string;
117
+ /**
118
+ * This call's handle within the build, for `cancel(buildId, runId)`: several renders of one
119
+ * build (its shards) can be in flight in one process. Absent, the build id is used.
120
+ */
121
+ runId?: string | undefined;
62
122
  /** Root of the already-extracted Storybook build. */
63
123
  storybookDir: string;
64
124
  /** Stories to render. */
@@ -73,8 +133,22 @@ interface CaptureRunner extends Adapter<{
73
133
  playTimeoutMs?: number;
74
134
  /** Whether to run a11y checks (axe) before screenshot; annotated as non-blocking. */
75
135
  runA11y?: boolean;
76
- /** Browser to use for rendering (chromium default). */
77
- browser?: BrowserName;
136
+ /** Target to render on (chromium when absent). */
137
+ target?: CaptureTarget;
138
+ /**
139
+ * An absolute URL to the build's Storybook that the target's browser can reach, set for a
140
+ * `reach: "url"` target (ADR 0007, decision 5). The runner navigates there instead of to its
141
+ * loopback server; a `reach: "url"` target given none fails to start. Never logged.
142
+ */
143
+ storybookUrl?: string;
144
+ /**
145
+ * Optional streaming hand-off. When provided, the runner awaits it with each
146
+ * capture as soon as it is taken, then drops the buffer instead of adding the
147
+ * capture to `RenderResult.captures`, so a large build never holds every
148
+ * screenshot in memory. A rejection is reported as a render failure for that
149
+ * story/viewport. Runners that do not support it return captures as usual.
150
+ */
151
+ onCapture?: (capture: RenderedSnapshot) => Promise<void>;
78
152
  /**
79
153
  * Test/extension seam: override the story source adapter (defaults to
80
154
  * `StorybookAdapter`). Only the renderer uses it; discovery stays the
@@ -82,9 +156,52 @@ interface CaptureRunner extends Adapter<{
82
156
  */
83
157
  adapter?: StorySourceAdapter;
84
158
  }): Promise<RenderResult>;
85
- /** Cancel a pending or in-flight render for a build. */
86
- cancel(buildId: string): Promise<void>;
159
+ /**
160
+ * Optional pre-pass reading each story's fully resolved parameters (project,
161
+ * component and story levels stacked) from the running preview. Storybook's
162
+ * index rarely carries parameters, so this is how the orchestrator learns
163
+ * which modes a story declares before it builds the capture matrix.
164
+ * Absent or failing, the orchestrator falls back to index parameters.
165
+ */
166
+ extractParameters?(input: {
167
+ buildId: string;
168
+ storybookDir: string;
169
+ stories: StoryEntry[];
170
+ logger?: Logger;
171
+ /** Target to read the parameters on: the project's primary (chromium when absent). */
172
+ target?: CaptureTarget;
173
+ /** As on `render`: the URL a `reach: "url"` target's browser opens. */
174
+ storybookUrl?: string;
175
+ adapter?: StorySourceAdapter;
176
+ }): Promise<Record<string, StoryParameters>>;
177
+ /**
178
+ * Optional: run Storybook 10 `.test()` entries (index `subtype: "test"`) as interaction tests.
179
+ * Each entry's iframe URL renders the story it is written under and runs the test body as the
180
+ * play function; the runner reports pass or fail per entry from Storybook's own events, and
181
+ * takes no screenshot. A runner without it leaves projects that turn tests on with a warning.
182
+ * Cancellable with `cancel`, like `render`.
183
+ */
184
+ runTests?(input: {
185
+ buildId: string;
186
+ runId?: string | undefined;
187
+ storybookDir: string;
188
+ /** The test entries to run (`StoryEntry.parentId` is set). */
189
+ tests: StoryEntry[];
190
+ logger?: Logger;
191
+ /** Timeout for one test (render plus body) in ms. */
192
+ playTimeoutMs?: number;
193
+ /** Target to run on: the project's primary (chromium when absent). */
194
+ target?: CaptureTarget;
195
+ /** As on `render`: the URL a `reach: "url"` target's browser opens. */
196
+ storybookUrl?: string;
197
+ adapter?: StorySourceAdapter;
198
+ }): Promise<TestOutcome[]>;
199
+ /**
200
+ * Cancel in-flight renders of a build: the ones started with `runId`, or every one of the build
201
+ * when it is absent. Runners can track their calls with {@link RenderRuns}.
202
+ */
203
+ cancel(buildId: string, runId?: string): Promise<void>;
87
204
  }
88
205
  //#endregion
89
- export { BROWSER_NAMES, BrowserName, CaptureRunner, type JobStatus, RenderFailure, RenderResult, RenderedSnapshot, type StoryEntry, type StorySourceAdapter, type Viewport };
206
+ export { BROWSER_NAMES, type BrowserName, CaptureEnvironment, CaptureRunner, type CaptureTarget, DEFAULT_BROWSER, type JobStatus, type ParsedTarget, type RemoteBrowser, type RemoteConnection, type RemoteOptions, type RemoteProtocol, type RemoteSupport, type RemoteTarget, RenderFailure, RenderResult, RenderRuns, RenderedSnapshot, type RunnerTarget, type StoryEntry, type StorySourceAdapter, TARGET_NAME_PATTERN, TargetLaunchError, type TargetOffers, type TargetReach, type TargetStatus, TestOutcome, type Viewport, createTargetOffers, defineRemote, engineOf, isBrowserName, isCaptureTarget, isRemoteBrowser, parseTarget, reachOf, remoteTargetsOf, scrubConnection, tryParseTarget, unavailableReason };
90
207
  //# sourceMappingURL=capture-runner.d.mts.map
@@ -1,15 +1,8 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/adapters/capture-runner.ts
5
- /** Browser names accepted for capture rendering (Chromium default). */
6
- const BROWSER_NAMES = [
7
- "chromium",
8
- "firefox",
9
- "webkit",
10
- "chrome"
11
- ];
12
- //#endregion
13
- export { BROWSER_NAMES };
14
-
15
- //# sourceMappingURL=capture-runner.mjs.map
4
+ import { BROWSER_NAMES, DEFAULT_BROWSER, TARGET_NAME_PATTERN, TargetLaunchError, engineOf, isBrowserName, isCaptureTarget, parseTarget, tryParseTarget, unavailableReason } from "../adapters/capture-target.mjs";
5
+ import { createTargetOffers } from "../adapters/capture-target-offers.mjs";
6
+ import { defineRemote, isRemoteBrowser, reachOf, remoteTargetsOf, scrubConnection } from "../adapters/remote-browser.mjs";
7
+ import { RenderRuns } from "../adapters/render-runs.mjs";
8
+ export { BROWSER_NAMES, DEFAULT_BROWSER, RenderRuns, TARGET_NAME_PATTERN, TargetLaunchError, createTargetOffers, defineRemote, engineOf, isBrowserName, isCaptureTarget, isRemoteBrowser, parseTarget, reachOf, remoteTargetsOf, scrubConnection, tryParseTarget, unavailableReason };
@@ -6,17 +6,30 @@ import { SQL, Table } from "drizzle-orm";
6
6
  /** Type-safe table map enforced on every DatabaseAdapter. */
7
7
  interface Tables {
8
8
  projects: Table;
9
- projectStatusConfigs: Table;
10
9
  builds: Table;
11
10
  captureAttempts: Table;
12
11
  captureLogs: Table;
12
+ captureShards: Table;
13
+ captureJobs: Table;
14
+ buildComponents: Table;
15
+ buildReviews: Table;
16
+ siteSettings: Table;
13
17
  snapshots: Table;
14
18
  baselines: Table;
15
19
  comments: Table;
16
20
  labelTypes: Table;
17
21
  buildLabels: Table;
22
+ projectLinks: Table;
23
+ designLinks: Table;
24
+ designCredentials: Table;
25
+ userConnections: Table;
26
+ designNodes: Table;
27
+ buildPackageUsage: Table;
18
28
  tokens: Table;
19
29
  webhooks: Table;
30
+ insights: Table;
31
+ aiUsage: Table;
32
+ aiBudgetAlerts: Table;
20
33
  notificationChannels: Table;
21
34
  notificationSubscriptions: Table;
22
35
  users: Table;
@@ -61,10 +74,18 @@ interface TxStore {
61
74
  /** Count rows matching an optional where condition. */
62
75
  count(table: Table, where?: SQL): Promise<number>;
63
76
  }
64
- /** Database abstraction over Drizzle tables, agnostic of dialect and driver. */
65
- interface DatabaseAdapter extends Adapter<{
77
+ /** Database-specific metadata: the family plus what the backing platform can carry. */
78
+ interface DatabaseAdapterMetadata {
66
79
  readonly category: "database";
67
- }> {
80
+ /**
81
+ * `false` when the database cannot back a deployment with `testing` (ADR 0006, decision 3): it
82
+ * is reachable only from a platform that ends the process after each request (Cloudflare D1).
83
+ * Unset means it can.
84
+ */
85
+ readonly supportsTesting?: boolean;
86
+ }
87
+ /** Database abstraction over Drizzle tables, agnostic of dialect and driver. */
88
+ interface DatabaseAdapter extends Adapter<DatabaseAdapterMetadata> {
68
89
  /** Table handles for this adapter's dialect, enforced with type safety. */
69
90
  readonly tables: Tables;
70
91
  /** Insert a row and return the inserted record. */
@@ -90,9 +111,7 @@ interface DatabaseAdapter extends Adapter<{
90
111
  }
91
112
  /** Driver-supplied identity plus lifecycle hooks. */
92
113
  interface DrizzleAdapterOptions {
93
- metadata: AdapterMetadata & {
94
- readonly category: "database";
95
- };
114
+ metadata: AdapterMetadata & DatabaseAdapterMetadata;
96
115
  tables: Tables;
97
116
  migrate: () => Promise<void> | void;
98
117
  close: () => Promise<void> | void;
@@ -100,5 +119,5 @@ interface DrizzleAdapterOptions {
100
119
  ping?: () => Promise<void> | void;
101
120
  }
102
121
  //#endregion
103
- export { DatabaseAdapter, DrizzleAdapterOptions, ListOptions, MAX_LIST_LIMIT, REQUIRED_TABLE_KEYS, Tables, TxStore, clampListLimit };
122
+ export { DatabaseAdapter, DatabaseAdapterMetadata, DrizzleAdapterOptions, ListOptions, MAX_LIST_LIMIT, REQUIRED_TABLE_KEYS, Tables, TxStore, clampListLimit };
104
123
  //# sourceMappingURL=database.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"database.mjs","names":[],"sources":["../../src/adapters/database.ts"],"sourcesContent":["/**\n * Database adapter interface: query builders over explicitly typed tables.\n *\n * Canonical home of the database contract — {@link DatabaseAdapter},\n * {@link Tables}, {@link TxStore}, {@link ListOptions}, and\n * {@link DrizzleAdapterOptions}. Driver machinery lives in the database\n * packages (`@storyshelf/db-sqlite`, `@storyshelf/db-postgres`).\n */\nimport type { SQL } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { Adapter, AdapterMetadata } from \"./metadata.ts\";\n\n/** Type-safe table map enforced on every DatabaseAdapter. */\nexport interface Tables {\n projects: Table;\n projectStatusConfigs: Table;\n builds: Table;\n captureAttempts: Table;\n captureLogs: Table;\n snapshots: Table;\n baselines: Table;\n comments: Table;\n labelTypes: Table;\n buildLabels: Table;\n tokens: Table;\n webhooks: Table;\n notificationChannels: Table;\n notificationSubscriptions: Table;\n users: Table;\n userInviteTokens: Table;\n projectMembers: Table;\n projectGroupMappings: Table;\n contentRefs: Table;\n}\n\n/** Table keys every DatabaseAdapter must expose (contract + validation share this). */\nexport const REQUIRED_TABLE_KEYS = [\n \"projects\",\n \"builds\",\n \"snapshots\",\n \"baselines\",\n \"comments\",\n \"labelTypes\",\n \"buildLabels\",\n \"tokens\",\n \"webhooks\",\n \"users\",\n \"projectMembers\",\n];\n\n/** Largest page any adapter serves in one list call. */\nexport const MAX_LIST_LIMIT = 1000;\n\n/** Clamp a list limit into [1, MAX_LIST_LIMIT]; undefined stays undefined. */\nexport function clampListLimit(limit?: number): number | undefined {\n if (limit === undefined) {\n return undefined;\n }\n if (!Number.isFinite(limit)) {\n return MAX_LIST_LIMIT;\n }\n return Math.min(Math.max(Math.floor(limit), 1), MAX_LIST_LIMIT);\n}\n\n/** Options that narrow and page a list query. */\nexport interface ListOptions {\n /** SQL WHERE condition. */\n where?: SQL;\n /** SQL ORDER BY condition. */\n orderBy?: SQL;\n /** Maximum number of rows to return. */\n limit?: number;\n /** Number of rows to skip. */\n offset?: number;\n}\n\n/**\n * Transactional CRUD subset available inside {@link DatabaseAdapter.transact}.\n * Mirrors the adapter surface minus metadata, lifecycle, and raw `all`\n * (opaque to transactions on some drivers).\n */\nexport interface TxStore {\n /** Insert a row and return the inserted record. */\n insert<T extends Table>(table: T, values: T[\"$inferInsert\"]): Promise<T[\"$inferSelect\"]>;\n /** Update a row by id and return the updated record. */\n update<T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]>;\n /** Fetch a single row by id, or null if not found. */\n get<T extends Table>(table: T, id: string): Promise<T[\"$inferSelect\"] | null>;\n /** Delete a row by id. */\n remove(table: Table, id: string): Promise<void>;\n /** List rows matching the given options. */\n list<T extends Table>(table: T, opts?: ListOptions): Promise<T[\"$inferSelect\"][]>;\n /** Count rows matching an optional where condition. */\n count(table: Table, where?: SQL): Promise<number>;\n}\n\n/** Database abstraction over Drizzle tables, agnostic of dialect and driver. */\nexport interface DatabaseAdapter extends Adapter<{ readonly category: \"database\" }> {\n /** Table handles for this adapter's dialect, enforced with type safety. */\n readonly tables: Tables;\n /** Insert a row and return the inserted record. */\n insert<T extends Table>(table: T, values: T[\"$inferInsert\"]): Promise<T[\"$inferSelect\"]>;\n /** Update a row by id and return the updated record. */\n update<T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]>;\n /** Fetch a single row by id, or null if not found. */\n get<T extends Table>(table: T, id: string): Promise<T[\"$inferSelect\"] | null>;\n /** Delete a row by id. */\n remove(table: Table, id: string): Promise<void>;\n /** List rows matching the given options. */\n list<T extends Table>(table: T, opts?: ListOptions): Promise<T[\"$inferSelect\"][]>;\n /** Count rows matching an optional where condition. */\n count(table: Table, where?: SQL): Promise<number>;\n /** Run an arbitrary SQL query and return typed rows. */\n all<T>(query: SQL): Promise<T[]>;\n /**\n * Run `fn` inside a transaction when the driver supports one.\n * Commits on resolve, rolls back on throw. Drivers without transaction\n * support omit this; callers must use `?.` and accept sequential execution.\n */\n transact?<R>(fn: (tx: TxStore) => Promise<R>): Promise<R>;\n}\n\n/** Driver-supplied identity plus lifecycle hooks. */\nexport interface DrizzleAdapterOptions {\n metadata: AdapterMetadata & { readonly category: \"database\" };\n tables: Tables;\n migrate: () => Promise<void> | void;\n close: () => Promise<void> | void;\n /** Cheap liveness probe (e.g. `SELECT 1`); omitted when the driver has none. */\n ping?: () => Promise<void> | void;\n}\n"],"mappings":";;;;;AAoCA,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,iBAAiB;;AAG9B,SAAgB,eAAe,OAAoC;CACjE,IAAI,UAAU,KAAA,GACZ;CAEF,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,OAAO;CAET,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC,GAAG,cAAc;AAChE"}
1
+ {"version":3,"file":"database.mjs","names":[],"sources":["../../src/adapters/database.ts"],"sourcesContent":["/**\n * Database adapter interface: query builders over explicitly typed tables.\n *\n * Canonical home of the database contract — {@link DatabaseAdapter},\n * {@link Tables}, {@link TxStore}, {@link ListOptions}, and\n * {@link DrizzleAdapterOptions}. Driver machinery lives in the database\n * packages (`@storyshelf/db-sqlite`, `@storyshelf/db-postgres`).\n */\nimport type { SQL } from \"drizzle-orm\";\nimport type { Table } from \"drizzle-orm\";\nimport type { Adapter, AdapterMetadata } from \"./metadata.ts\";\n\n/** Type-safe table map enforced on every DatabaseAdapter. */\nexport interface Tables {\n projects: Table;\n builds: Table;\n captureAttempts: Table;\n captureLogs: Table;\n captureShards: Table;\n captureJobs: Table;\n buildComponents: Table;\n buildReviews: Table;\n siteSettings: Table;\n snapshots: Table;\n baselines: Table;\n comments: Table;\n labelTypes: Table;\n buildLabels: Table;\n projectLinks: Table;\n designLinks: Table;\n designCredentials: Table;\n userConnections: Table;\n designNodes: Table;\n buildPackageUsage: Table;\n tokens: Table;\n webhooks: Table;\n insights: Table;\n aiUsage: Table;\n aiBudgetAlerts: Table;\n notificationChannels: Table;\n notificationSubscriptions: Table;\n users: Table;\n userInviteTokens: Table;\n projectMembers: Table;\n projectGroupMappings: Table;\n contentRefs: Table;\n}\n\n/** Table keys every DatabaseAdapter must expose (contract + validation share this). */\nexport const REQUIRED_TABLE_KEYS = [\n \"projects\",\n \"builds\",\n \"snapshots\",\n \"baselines\",\n \"comments\",\n \"labelTypes\",\n \"buildLabels\",\n \"tokens\",\n \"webhooks\",\n \"users\",\n \"projectMembers\",\n];\n\n/** Largest page any adapter serves in one list call. */\nexport const MAX_LIST_LIMIT = 1000;\n\n/** Clamp a list limit into [1, MAX_LIST_LIMIT]; undefined stays undefined. */\nexport function clampListLimit(limit?: number): number | undefined {\n if (limit === undefined) {\n return undefined;\n }\n if (!Number.isFinite(limit)) {\n return MAX_LIST_LIMIT;\n }\n return Math.min(Math.max(Math.floor(limit), 1), MAX_LIST_LIMIT);\n}\n\n/** Options that narrow and page a list query. */\nexport interface ListOptions {\n /** SQL WHERE condition. */\n where?: SQL;\n /** SQL ORDER BY condition. */\n orderBy?: SQL;\n /** Maximum number of rows to return. */\n limit?: number;\n /** Number of rows to skip. */\n offset?: number;\n}\n\n/**\n * Transactional CRUD subset available inside {@link DatabaseAdapter.transact}.\n * Mirrors the adapter surface minus metadata, lifecycle, and raw `all`\n * (opaque to transactions on some drivers).\n */\nexport interface TxStore {\n /** Insert a row and return the inserted record. */\n insert<T extends Table>(table: T, values: T[\"$inferInsert\"]): Promise<T[\"$inferSelect\"]>;\n /** Update a row by id and return the updated record. */\n update<T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]>;\n /** Fetch a single row by id, or null if not found. */\n get<T extends Table>(table: T, id: string): Promise<T[\"$inferSelect\"] | null>;\n /** Delete a row by id. */\n remove(table: Table, id: string): Promise<void>;\n /** List rows matching the given options. */\n list<T extends Table>(table: T, opts?: ListOptions): Promise<T[\"$inferSelect\"][]>;\n /** Count rows matching an optional where condition. */\n count(table: Table, where?: SQL): Promise<number>;\n}\n\n/** Database-specific metadata: the family plus what the backing platform can carry. */\nexport interface DatabaseAdapterMetadata {\n readonly category: \"database\";\n /**\n * `false` when the database cannot back a deployment with `testing` (ADR 0006, decision 3): it\n * is reachable only from a platform that ends the process after each request (Cloudflare D1).\n * Unset means it can.\n */\n readonly supportsTesting?: boolean;\n}\n\n/** Database abstraction over Drizzle tables, agnostic of dialect and driver. */\nexport interface DatabaseAdapter extends Adapter<DatabaseAdapterMetadata> {\n /** Table handles for this adapter's dialect, enforced with type safety. */\n readonly tables: Tables;\n /** Insert a row and return the inserted record. */\n insert<T extends Table>(table: T, values: T[\"$inferInsert\"]): Promise<T[\"$inferSelect\"]>;\n /** Update a row by id and return the updated record. */\n update<T extends Table>(\n table: T,\n id: string,\n values: Partial<T[\"$inferInsert\"]>,\n ): Promise<T[\"$inferSelect\"]>;\n /** Fetch a single row by id, or null if not found. */\n get<T extends Table>(table: T, id: string): Promise<T[\"$inferSelect\"] | null>;\n /** Delete a row by id. */\n remove(table: Table, id: string): Promise<void>;\n /** List rows matching the given options. */\n list<T extends Table>(table: T, opts?: ListOptions): Promise<T[\"$inferSelect\"][]>;\n /** Count rows matching an optional where condition. */\n count(table: Table, where?: SQL): Promise<number>;\n /** Run an arbitrary SQL query and return typed rows. */\n all<T>(query: SQL): Promise<T[]>;\n /**\n * Run `fn` inside a transaction when the driver supports one.\n * Commits on resolve, rolls back on throw. Drivers without transaction\n * support omit this; callers must use `?.` and accept sequential execution.\n */\n transact?<R>(fn: (tx: TxStore) => Promise<R>): Promise<R>;\n}\n\n/** Driver-supplied identity plus lifecycle hooks. */\nexport interface DrizzleAdapterOptions {\n metadata: AdapterMetadata & DatabaseAdapterMetadata;\n tables: Tables;\n migrate: () => Promise<void> | void;\n close: () => Promise<void> | void;\n /** Cheap liveness probe (e.g. `SELECT 1`); omitted when the driver has none. */\n ping?: () => Promise<void> | void;\n}\n"],"mappings":";;;;;AAiDA,MAAa,sBAAsB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAa,iBAAiB;;AAG9B,SAAgB,eAAe,OAAoC;CACjE,IAAI,UAAU,KAAA,GACZ;CAEF,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,OAAO;CAET,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,KAAK,GAAG,CAAC,GAAG,cAAc;AAChE"}