@storyshelf/core 0.6.2 → 0.8.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 (727) hide show
  1. package/README.md +49 -32
  2. package/dist/adapter/capture-queue.d.mts +44 -4
  3. package/dist/adapter/capture-runner.d.mts +134 -12
  4. package/dist/adapter/capture-runner.mjs +9 -12
  5. package/dist/adapter/database.d.mts +89 -10
  6. package/dist/adapter/database.mjs +4 -3
  7. package/dist/adapter/database.mjs.map +1 -1
  8. package/dist/adapter/design.d.mts +83 -0
  9. package/dist/adapter/design.mjs +27 -0
  10. package/dist/adapter/design.mjs.map +1 -0
  11. package/dist/adapter/email-sender.d.mts +0 -2
  12. package/dist/adapter/metadata.d.mts +3 -12
  13. package/dist/adapter/notifier.d.mts +6 -3
  14. package/dist/adapter/notifier.mjs +5 -1
  15. package/dist/adapter/oauth.d.mts +50 -0
  16. package/dist/adapter/setup.d.mts +4 -7
  17. package/dist/adapter/setup.mjs +3 -3
  18. package/dist/adapter/setup.mjs.map +1 -1
  19. package/dist/adapter/storage.d.mts +1 -3
  20. package/dist/adapter/webhook-events.d.mts +0 -2
  21. package/dist/adapter/webhook-events.mjs +13 -14
  22. package/dist/adapter/webhook-events.mjs.map +1 -1
  23. package/dist/adapters/capture-target-offers.d.mts +26 -0
  24. package/dist/adapters/capture-target-offers.mjs +57 -0
  25. package/dist/adapters/capture-target-offers.mjs.map +1 -0
  26. package/dist/adapters/capture-target.d.mts +69 -0
  27. package/dist/adapters/capture-target.mjs +75 -0
  28. package/dist/adapters/capture-target.mjs.map +1 -0
  29. package/dist/adapters/notifier/build-comment.d.mts +22 -0
  30. package/dist/adapters/notifier/build-comment.mjs +23 -0
  31. package/dist/adapters/notifier/build-comment.mjs.map +1 -0
  32. package/dist/adapters/notifier/build-state.d.mts +97 -0
  33. package/dist/adapters/notifier/build-state.mjs +217 -0
  34. package/dist/adapters/notifier/build-state.mjs.map +1 -0
  35. package/dist/adapters/notifier/events.d.mts +4 -4
  36. package/dist/adapters/notifier/events.mjs +32 -20
  37. package/dist/adapters/notifier/events.mjs.map +1 -1
  38. package/dist/adapters/notifier/format.d.mts +0 -2
  39. package/dist/adapters/notifier/format.mjs +1 -2
  40. package/dist/adapters/notifier/provider.d.mts +53 -9
  41. package/dist/adapters/notifier/provider.mjs +11 -0
  42. package/dist/adapters/notifier/provider.mjs.map +1 -0
  43. package/dist/adapters/notifier/state.d.mts +22 -0
  44. package/dist/adapters/notifier/state.mjs +65 -0
  45. package/dist/adapters/notifier/state.mjs.map +1 -0
  46. package/dist/adapters/notifier/types.d.mts +51 -4
  47. package/dist/adapters/remote-browser.d.mts +168 -0
  48. package/dist/adapters/remote-browser.mjs +201 -0
  49. package/dist/adapters/remote-browser.mjs.map +1 -0
  50. package/dist/adapters/remote-lease-attempt.mjs +39 -0
  51. package/dist/adapters/remote-lease-attempt.mjs.map +1 -0
  52. package/dist/adapters/remote-lease-error.d.mts +25 -0
  53. package/dist/adapters/remote-lease-error.mjs +54 -0
  54. package/dist/adapters/remote-lease-error.mjs.map +1 -0
  55. package/dist/adapters/remote-lease-held.d.mts +15 -0
  56. package/dist/adapters/remote-lease-held.mjs +86 -0
  57. package/dist/adapters/remote-lease-held.mjs.map +1 -0
  58. package/dist/adapters/remote-lease-shutdown.d.mts +12 -0
  59. package/dist/adapters/remote-lease-shutdown.mjs +32 -0
  60. package/dist/adapters/remote-lease-shutdown.mjs.map +1 -0
  61. package/dist/adapters/remote-lease.d.mts +39 -0
  62. package/dist/adapters/remote-lease.mjs +175 -0
  63. package/dist/adapters/remote-lease.mjs.map +1 -0
  64. package/dist/adapters/remote-limiter.mjs +121 -0
  65. package/dist/adapters/remote-limiter.mjs.map +1 -0
  66. package/dist/adapters/remote-pool.d.mts +56 -0
  67. package/dist/adapters/remote-pool.mjs +195 -0
  68. package/dist/adapters/remote-pool.mjs.map +1 -0
  69. package/dist/adapters/render-runs.d.mts +23 -0
  70. package/dist/adapters/render-runs.mjs +40 -0
  71. package/dist/adapters/render-runs.mjs.map +1 -0
  72. package/dist/adapters/setup-runner.d.mts +0 -2
  73. package/dist/adapters/setup-runner.mjs +3 -6
  74. package/dist/adapters/setup-runner.mjs.map +1 -1
  75. package/dist/adapters/sources.d.mts +10 -0
  76. package/dist/adapters/sources.mjs +19 -0
  77. package/dist/adapters/sources.mjs.map +1 -0
  78. package/dist/adapters/validate.d.mts +0 -2
  79. package/dist/adapters/validate.mjs +27 -20
  80. package/dist/adapters/validate.mjs.map +1 -1
  81. package/dist/ai.d.mts +103 -0
  82. package/dist/ai.mjs +18 -0
  83. package/dist/ai.mjs.map +1 -0
  84. package/dist/auth.d.mts +0 -2
  85. package/dist/auth.mjs +1 -2
  86. package/dist/brand-packs.d.mts +0 -2
  87. package/dist/brand-packs.mjs +0 -1
  88. package/dist/capture/a11y/axe-source.d.mts +16 -0
  89. package/dist/capture/a11y/axe-source.mjs +36 -0
  90. package/dist/capture/a11y/axe-source.mjs.map +1 -0
  91. package/dist/capture/a11y/in-page.d.mts +25 -0
  92. package/dist/capture/a11y/in-page.mjs +59 -0
  93. package/dist/capture/a11y/in-page.mjs.map +1 -0
  94. package/dist/capture/a11y/map.d.mts +22 -0
  95. package/dist/capture/a11y/map.mjs +47 -0
  96. package/dist/capture/a11y/map.mjs.map +1 -0
  97. package/dist/capture/a11y/options.d.mts +21 -0
  98. package/dist/capture/a11y/options.mjs +74 -0
  99. package/dist/capture/a11y/options.mjs.map +1 -0
  100. package/dist/capture/adapter.d.mts +46 -5
  101. package/dist/capture/adapter.mjs +1 -2
  102. package/dist/capture/adapter.mjs.map +1 -1
  103. package/dist/capture/affected.d.mts +2 -2
  104. package/dist/capture/affected.mjs +14 -6
  105. package/dist/capture/affected.mjs.map +1 -1
  106. package/dist/capture/attempt-logger.mjs +83 -0
  107. package/dist/capture/attempt-logger.mjs.map +1 -0
  108. package/dist/capture/browsers.d.mts +33 -0
  109. package/dist/capture/browsers.mjs +66 -0
  110. package/dist/capture/browsers.mjs.map +1 -0
  111. package/dist/capture/build-state/deliver.d.mts +30 -0
  112. package/dist/capture/build-state/deliver.mjs +117 -0
  113. package/dist/capture/build-state/deliver.mjs.map +1 -0
  114. package/dist/capture/build-state/index.d.mts +8 -0
  115. package/dist/capture/build-state/notify-job.d.mts +54 -0
  116. package/dist/capture/build-state/notify-job.mjs +132 -0
  117. package/dist/capture/build-state/notify-job.mjs.map +1 -0
  118. package/dist/capture/build-state/publisher.d.mts +21 -0
  119. package/dist/capture/build-state/publisher.mjs +106 -0
  120. package/dist/capture/build-state/publisher.mjs.map +1 -0
  121. package/dist/capture/build-state/resume.d.mts +7 -0
  122. package/dist/capture/build-state/resume.mjs +46 -0
  123. package/dist/capture/build-state/resume.mjs.map +1 -0
  124. package/dist/capture/build-state/types.d.mts +47 -0
  125. package/dist/capture/catalog/catalogue.d.mts +20 -0
  126. package/dist/capture/catalog/catalogue.mjs +52 -0
  127. package/dist/capture/catalog/catalogue.mjs.map +1 -0
  128. package/dist/capture/catalog/components.d.mts +21 -0
  129. package/dist/capture/catalog/components.mjs +54 -0
  130. package/dist/capture/catalog/components.mjs.map +1 -0
  131. package/dist/capture/catalog/history.d.mts +28 -0
  132. package/dist/capture/catalog/history.mjs +50 -0
  133. package/dist/capture/catalog/history.mjs.map +1 -0
  134. package/dist/capture/catalog/hook.d.mts +12 -0
  135. package/dist/capture/catalog/hook.mjs +18 -0
  136. package/dist/capture/catalog/hook.mjs.map +1 -0
  137. package/dist/capture/catalog/index.d.mts +11 -0
  138. package/dist/capture/catalog/load.d.mts +24 -0
  139. package/dist/capture/catalog/load.mjs +48 -0
  140. package/dist/capture/catalog/load.mjs.map +1 -0
  141. package/dist/capture/catalog/parse.d.mts +13 -0
  142. package/dist/capture/catalog/parse.mjs +55 -0
  143. package/dist/capture/catalog/parse.mjs.map +1 -0
  144. package/dist/capture/catalog/read.d.mts +15 -0
  145. package/dist/capture/catalog/read.mjs +39 -0
  146. package/dist/capture/catalog/read.mjs.map +1 -0
  147. package/dist/capture/catalog/types.d.mts +31 -0
  148. package/dist/capture/comparison-reference.d.mts +27 -0
  149. package/dist/capture/comparison-reference.mjs +75 -0
  150. package/dist/capture/comparison-reference.mjs.map +1 -0
  151. package/dist/capture/consumer/capture-handler.d.mts +56 -0
  152. package/dist/capture/consumer/capture-handler.mjs +117 -0
  153. package/dist/capture/consumer/capture-handler.mjs.map +1 -0
  154. package/dist/capture/consumer/idle.d.mts +15 -0
  155. package/dist/capture/consumer/idle.mjs +24 -0
  156. package/dist/capture/consumer/idle.mjs.map +1 -0
  157. package/dist/capture/consumer/index.d.mts +11 -0
  158. package/dist/capture/consumer/index.mjs +138 -0
  159. package/dist/capture/consumer/index.mjs.map +1 -0
  160. package/dist/capture/consumer/loop.mjs +109 -0
  161. package/dist/capture/consumer/loop.mjs.map +1 -0
  162. package/dist/capture/consumer/metrics.d.mts +39 -0
  163. package/dist/capture/consumer/metrics.mjs +37 -0
  164. package/dist/capture/consumer/metrics.mjs.map +1 -0
  165. package/dist/capture/consumer/retry.d.mts +31 -0
  166. package/dist/capture/consumer/retry.mjs +33 -0
  167. package/dist/capture/consumer/retry.mjs.map +1 -0
  168. package/dist/capture/consumer/run-job.mjs +194 -0
  169. package/dist/capture/consumer/run-job.mjs.map +1 -0
  170. package/dist/capture/consumer/startup.mjs +37 -0
  171. package/dist/capture/consumer/startup.mjs.map +1 -0
  172. package/dist/capture/consumer/types.d.mts +95 -0
  173. package/dist/capture/crash-failure.d.mts +23 -0
  174. package/dist/capture/crash-failure.mjs +69 -0
  175. package/dist/capture/crash-failure.mjs.map +1 -0
  176. package/dist/capture/db-queue/cadence.d.mts +30 -0
  177. package/dist/capture/db-queue/cadence.mjs +37 -0
  178. package/dist/capture/db-queue/cadence.mjs.map +1 -0
  179. package/dist/capture/db-queue/claim.d.mts +7 -0
  180. package/dist/capture/db-queue/claim.mjs +148 -0
  181. package/dist/capture/db-queue/claim.mjs.map +1 -0
  182. package/dist/capture/db-queue/clock.mjs +11 -0
  183. package/dist/capture/db-queue/clock.mjs.map +1 -0
  184. package/dist/capture/db-queue/codec.mjs +75 -0
  185. package/dist/capture/db-queue/codec.mjs.map +1 -0
  186. package/dist/capture/db-queue/index.d.mts +18 -0
  187. package/dist/capture/db-queue/index.mjs +89 -0
  188. package/dist/capture/db-queue/index.mjs.map +1 -0
  189. package/dist/capture/db-queue/keeper.d.mts +34 -0
  190. package/dist/capture/db-queue/keeper.mjs +91 -0
  191. package/dist/capture/db-queue/keeper.mjs.map +1 -0
  192. package/dist/capture/db-queue/lease.mjs +45 -0
  193. package/dist/capture/db-queue/lease.mjs.map +1 -0
  194. package/dist/capture/db-queue/lifecycle.mjs +35 -0
  195. package/dist/capture/db-queue/lifecycle.mjs.map +1 -0
  196. package/dist/capture/db-queue/operations.mjs +93 -0
  197. package/dist/capture/db-queue/operations.mjs.map +1 -0
  198. package/dist/capture/db-queue/poll-loop.d.mts +28 -0
  199. package/dist/capture/db-queue/poll-loop.mjs +88 -0
  200. package/dist/capture/db-queue/poll-loop.mjs.map +1 -0
  201. package/dist/capture/db-queue/poll.d.mts +8 -0
  202. package/dist/capture/db-queue/poll.mjs +68 -0
  203. package/dist/capture/db-queue/poll.mjs.map +1 -0
  204. package/dist/capture/db-queue/timers.d.mts +10 -0
  205. package/dist/capture/db-queue/timers.mjs +36 -0
  206. package/dist/capture/db-queue/timers.mjs.map +1 -0
  207. package/dist/capture/db-queue/types.d.mts +81 -0
  208. package/dist/capture/db-queue/types.mjs +11 -0
  209. package/dist/capture/db-queue/types.mjs.map +1 -0
  210. package/dist/capture/db-queue/wake.mjs +47 -0
  211. package/dist/capture/db-queue/wake.mjs.map +1 -0
  212. package/dist/capture/design.mjs +38 -0
  213. package/dist/capture/design.mjs.map +1 -0
  214. package/dist/capture/diff-record.mjs +24 -5
  215. package/dist/capture/diff-record.mjs.map +1 -1
  216. package/dist/capture/dispatch.d.mts +13 -10
  217. package/dist/capture/dispatch.mjs +102 -111
  218. package/dist/capture/dispatch.mjs.map +1 -1
  219. package/dist/capture/enrich.mjs +59 -0
  220. package/dist/capture/enrich.mjs.map +1 -0
  221. package/dist/capture/failure-sets.mjs +21 -0
  222. package/dist/capture/failure-sets.mjs.map +1 -0
  223. package/dist/capture/fingerprint.d.mts +40 -0
  224. package/dist/capture/fingerprint.mjs +82 -0
  225. package/dist/capture/fingerprint.mjs.map +1 -0
  226. package/dist/capture/forked/channel.d.mts +23 -0
  227. package/dist/capture/forked/child.d.mts +32 -0
  228. package/dist/capture/forked/child.mjs +201 -0
  229. package/dist/capture/forked/child.mjs.map +1 -0
  230. package/dist/capture/forked/crash-tracker.mjs +22 -0
  231. package/dist/capture/forked/crash-tracker.mjs.map +1 -0
  232. package/dist/capture/forked/decision.d.mts +24 -0
  233. package/dist/capture/forked/decision.mjs +26 -0
  234. package/dist/capture/forked/decision.mjs.map +1 -0
  235. package/dist/capture/forked/exit.mjs +11 -0
  236. package/dist/capture/forked/exit.mjs.map +1 -0
  237. package/dist/capture/forked/fork.d.mts +29 -0
  238. package/dist/capture/forked/fork.mjs +92 -0
  239. package/dist/capture/forked/fork.mjs.map +1 -0
  240. package/dist/capture/forked/forked-capture.d.mts +38 -0
  241. package/dist/capture/forked/forked-capture.mjs +239 -0
  242. package/dist/capture/forked/forked-capture.mjs.map +1 -0
  243. package/dist/capture/forked/lease-book.mjs +45 -0
  244. package/dist/capture/forked/lease-book.mjs.map +1 -0
  245. package/dist/capture/forked/protocol.d.mts +36 -0
  246. package/dist/capture/forked/protocol.mjs +24 -0
  247. package/dist/capture/forked/protocol.mjs.map +1 -0
  248. package/dist/capture/forked/runs.mjs +74 -0
  249. package/dist/capture/forked/runs.mjs.map +1 -0
  250. package/dist/capture/guards.mjs +1 -2
  251. package/dist/capture/ignore-regions.d.mts +36 -0
  252. package/dist/capture/ignore-regions.mjs +65 -0
  253. package/dist/capture/ignore-regions.mjs.map +1 -0
  254. package/dist/capture/isolate.mjs +140 -0
  255. package/dist/capture/isolate.mjs.map +1 -0
  256. package/dist/capture/job-lease.d.mts +26 -0
  257. package/dist/capture/job-lease.mjs +56 -0
  258. package/dist/capture/job-lease.mjs.map +1 -0
  259. package/dist/capture/matrix.mjs +298 -0
  260. package/dist/capture/matrix.mjs.map +1 -0
  261. package/dist/capture/modes.d.mts +23 -0
  262. package/dist/capture/modes.mjs +106 -0
  263. package/dist/capture/modes.mjs.map +1 -0
  264. package/dist/capture/orchestrator.d.mts +37 -7
  265. package/dist/capture/orchestrator.mjs +120 -110
  266. package/dist/capture/orchestrator.mjs.map +1 -1
  267. package/dist/capture/pipeline.d.mts +9 -4
  268. package/dist/capture/pipeline.mjs +284 -48
  269. package/dist/capture/pipeline.mjs.map +1 -1
  270. package/dist/capture/progress.d.mts +9 -0
  271. package/dist/capture/progress.mjs +27 -0
  272. package/dist/capture/progress.mjs.map +1 -0
  273. package/dist/capture/publish/accept.d.mts +37 -0
  274. package/dist/capture/publish/accept.mjs +27 -0
  275. package/dist/capture/publish/accept.mjs.map +1 -0
  276. package/dist/capture/publish/complete.d.mts +44 -0
  277. package/dist/capture/publish/complete.mjs +63 -0
  278. package/dist/capture/publish/complete.mjs.map +1 -0
  279. package/dist/capture/publish/extract.d.mts +18 -0
  280. package/dist/capture/publish/extract.mjs +120 -0
  281. package/dist/capture/publish/extract.mjs.map +1 -0
  282. package/dist/capture/publish/handler.d.mts +26 -0
  283. package/dist/capture/publish/handler.mjs +61 -0
  284. package/dist/capture/publish/handler.mjs.map +1 -0
  285. package/dist/capture/publish/index.d.mts +11 -0
  286. package/dist/capture/publish/invalid-zip.d.mts +8 -0
  287. package/dist/capture/publish/invalid-zip.mjs +11 -0
  288. package/dist/capture/publish/invalid-zip.mjs.map +1 -0
  289. package/dist/capture/publish/limits.d.mts +35 -0
  290. package/dist/capture/publish/limits.mjs +38 -0
  291. package/dist/capture/publish/limits.mjs.map +1 -0
  292. package/dist/capture/publish/published.d.mts +13 -0
  293. package/dist/capture/publish/published.mjs +17 -0
  294. package/dist/capture/publish/published.mjs.map +1 -0
  295. package/dist/capture/publish/run.d.mts +31 -0
  296. package/dist/capture/publish/run.mjs +29 -0
  297. package/dist/capture/publish/run.mjs.map +1 -0
  298. package/dist/capture/rediff.d.mts +1 -3
  299. package/dist/capture/rediff.mjs +23 -9
  300. package/dist/capture/rediff.mjs.map +1 -1
  301. package/dist/capture/render.mjs +52 -0
  302. package/dist/capture/render.mjs.map +1 -0
  303. package/dist/capture/scratch.d.mts +42 -0
  304. package/dist/capture/scratch.mjs +136 -0
  305. package/dist/capture/scratch.mjs.map +1 -0
  306. package/dist/capture/shard-plan.mjs +127 -0
  307. package/dist/capture/shard-plan.mjs.map +1 -0
  308. package/dist/capture/shards/context.mjs +51 -0
  309. package/dist/capture/shards/context.mjs.map +1 -0
  310. package/dist/capture/shards/execute.mjs +175 -0
  311. package/dist/capture/shards/execute.mjs.map +1 -0
  312. package/dist/capture/shards/fan-out.mjs +125 -0
  313. package/dist/capture/shards/fan-out.mjs.map +1 -0
  314. package/dist/capture/shards/history.mjs +34 -0
  315. package/dist/capture/shards/history.mjs.map +1 -0
  316. package/dist/capture/shards/reduce.mjs +96 -0
  317. package/dist/capture/shards/reduce.mjs.map +1 -0
  318. package/dist/capture/sizing.d.mts +0 -2
  319. package/dist/capture/sizing.mjs +2 -13
  320. package/dist/capture/sizing.mjs.map +1 -1
  321. package/dist/capture/skip-checks.mjs +3 -67
  322. package/dist/capture/skip-checks.mjs.map +1 -1
  323. package/dist/capture/statics.d.mts +7 -10
  324. package/dist/capture/statics.mjs +26 -74
  325. package/dist/capture/statics.mjs.map +1 -1
  326. package/dist/capture/storybook-urls.d.mts +38 -0
  327. package/dist/capture/storybook-urls.mjs +41 -0
  328. package/dist/capture/storybook-urls.mjs.map +1 -0
  329. package/dist/capture/storybook.d.mts +12 -6
  330. package/dist/capture/storybook.mjs +63 -19
  331. package/dist/capture/storybook.mjs.map +1 -1
  332. package/dist/capture/target.mjs +20 -0
  333. package/dist/capture/target.mjs.map +1 -0
  334. package/dist/capture/targets.d.mts +23 -0
  335. package/dist/capture/targets.mjs +31 -0
  336. package/dist/capture/targets.mjs.map +1 -0
  337. package/dist/capture/tests.d.mts +35 -0
  338. package/dist/capture/tests.mjs +136 -0
  339. package/dist/capture/tests.mjs.map +1 -0
  340. package/dist/capture/token-chunks.mjs +91 -0
  341. package/dist/capture/token-chunks.mjs.map +1 -0
  342. package/dist/capture.d.mts +63 -7
  343. package/dist/capture.mjs +51 -3
  344. package/dist/config.d.mts +136 -14
  345. package/dist/config.mjs +14 -8
  346. package/dist/config.mjs.map +1 -1
  347. package/dist/diff.d.mts +7 -3
  348. package/dist/diff.mjs +15 -3
  349. package/dist/diff.mjs.map +1 -0
  350. package/dist/index.d.mts +3 -3
  351. package/dist/index.mjs +2 -2
  352. package/dist/insights/budget.d.mts +18 -0
  353. package/dist/insights/budget.mjs +32 -0
  354. package/dist/insights/budget.mjs.map +1 -0
  355. package/dist/insights/envelope.d.mts +57 -0
  356. package/dist/insights/envelope.mjs +59 -0
  357. package/dist/insights/envelope.mjs.map +1 -0
  358. package/dist/insights/evidence-health.d.mts +30 -0
  359. package/dist/insights/evidence-health.mjs +27 -0
  360. package/dist/insights/evidence-health.mjs.map +1 -0
  361. package/dist/insights/evidence.d.mts +53 -0
  362. package/dist/insights/evidence.mjs +63 -0
  363. package/dist/insights/evidence.mjs.map +1 -0
  364. package/dist/insights/hash.d.mts +16 -0
  365. package/dist/insights/hash.mjs +20 -0
  366. package/dist/insights/hash.mjs.map +1 -0
  367. package/dist/insights/limits.d.mts +22 -0
  368. package/dist/insights/limits.mjs +23 -0
  369. package/dist/insights/limits.mjs.map +1 -0
  370. package/dist/insights/prompts/v1.d.mts +11 -0
  371. package/dist/insights/prompts/v1.mjs +33 -0
  372. package/dist/insights/prompts/v1.mjs.map +1 -0
  373. package/dist/insights/redact.d.mts +7 -0
  374. package/dist/insights/redact.mjs +23 -0
  375. package/dist/insights/redact.mjs.map +1 -0
  376. package/dist/insights/text.mjs +43 -0
  377. package/dist/insights/text.mjs.map +1 -0
  378. package/dist/insights.d.mts +11 -0
  379. package/dist/insights.mjs +12 -0
  380. package/dist/logger.d.mts +0 -2
  381. package/dist/logger.mjs +18 -3
  382. package/dist/logger.mjs.map +1 -1
  383. package/dist/models/ai-budget-alert.d.mts +21 -0
  384. package/dist/models/ai-budget-alert.mjs +37 -0
  385. package/dist/models/ai-budget-alert.mjs.map +1 -0
  386. package/dist/models/ai-usage.d.mts +38 -0
  387. package/dist/models/ai-usage.mjs +60 -0
  388. package/dist/models/ai-usage.mjs.map +1 -0
  389. package/dist/models/baseline-approval.d.mts +18 -0
  390. package/dist/models/baseline-approval.mjs +41 -0
  391. package/dist/models/baseline-approval.mjs.map +1 -0
  392. package/dist/models/baseline-archive.d.mts +82 -0
  393. package/dist/models/baseline-archive.mjs +105 -0
  394. package/dist/models/baseline-archive.mjs.map +1 -0
  395. package/dist/models/baseline-atomic.mjs +66 -0
  396. package/dist/models/baseline-atomic.mjs.map +1 -0
  397. package/dist/models/baseline-conflict.d.mts +6 -0
  398. package/dist/models/baseline-conflict.mjs +9 -0
  399. package/dist/models/baseline-conflict.mjs.map +1 -0
  400. package/dist/models/baseline-export.d.mts +17 -0
  401. package/dist/models/baseline-export.mjs +135 -0
  402. package/dist/models/baseline-export.mjs.map +1 -0
  403. package/dist/models/baseline-import.mjs +117 -0
  404. package/dist/models/baseline-import.mjs.map +1 -0
  405. package/dist/models/baseline-origin.d.mts +16 -0
  406. package/dist/models/baseline-origin.mjs +35 -0
  407. package/dist/models/baseline-origin.mjs.map +1 -0
  408. package/dist/models/baseline-status.d.mts +0 -2
  409. package/dist/models/baseline-status.mjs +1 -2
  410. package/dist/models/baseline-transfer.d.mts +48 -0
  411. package/dist/models/baseline-transfer.mjs +149 -0
  412. package/dist/models/baseline-transfer.mjs.map +1 -0
  413. package/dist/models/baseline.d.mts +37 -7
  414. package/dist/models/baseline.mjs +152 -28
  415. package/dist/models/baseline.mjs.map +1 -1
  416. package/dist/models/build-component.d.mts +26 -0
  417. package/dist/models/build-component.mjs +54 -0
  418. package/dist/models/build-component.mjs.map +1 -0
  419. package/dist/models/build-review-status.d.mts +27 -0
  420. package/dist/models/build-review-status.mjs +36 -0
  421. package/dist/models/build-review-status.mjs.map +1 -0
  422. package/dist/models/build-review.d.mts +26 -0
  423. package/dist/models/build-review.mjs +53 -0
  424. package/dist/models/build-review.mjs.map +1 -0
  425. package/dist/models/build.d.mts +25 -5
  426. package/dist/models/build.mjs +53 -15
  427. package/dist/models/build.mjs.map +1 -1
  428. package/dist/models/capture-attempt.d.mts +7 -3
  429. package/dist/models/capture-attempt.mjs +30 -6
  430. package/dist/models/capture-attempt.mjs.map +1 -1
  431. package/dist/models/capture-job.d.mts +104 -0
  432. package/dist/models/capture-job.mjs +287 -0
  433. package/dist/models/capture-job.mjs.map +1 -0
  434. package/dist/models/capture-log.d.mts +1 -3
  435. package/dist/models/capture-log.mjs +5 -5
  436. package/dist/models/capture-log.mjs.map +1 -1
  437. package/dist/models/capture-shard.d.mts +60 -0
  438. package/dist/models/capture-shard.mjs +189 -0
  439. package/dist/models/capture-shard.mjs.map +1 -0
  440. package/dist/models/changeset.d.mts +46 -0
  441. package/dist/models/changeset.mjs +80 -0
  442. package/dist/models/changeset.mjs.map +1 -0
  443. package/dist/models/columns.mjs +18 -0
  444. package/dist/models/columns.mjs.map +1 -0
  445. package/dist/models/comment.d.mts +4 -3
  446. package/dist/models/comment.mjs +8 -6
  447. package/dist/models/comment.mjs.map +1 -1
  448. package/dist/models/component.d.mts +41 -0
  449. package/dist/models/component.mjs +59 -0
  450. package/dist/models/component.mjs.map +1 -0
  451. package/dist/models/connections.d.mts +39 -0
  452. package/dist/models/connections.mjs +111 -0
  453. package/dist/models/connections.mjs.map +1 -0
  454. package/dist/models/content-ref.d.mts +1 -3
  455. package/dist/models/content-ref.mjs +2 -3
  456. package/dist/models/content-ref.mjs.map +1 -1
  457. package/dist/models/credentials.d.mts +0 -2
  458. package/dist/models/credentials.mjs +13 -4
  459. package/dist/models/credentials.mjs.map +1 -1
  460. package/dist/models/design-credentials.d.mts +39 -0
  461. package/dist/models/design-credentials.mjs +85 -0
  462. package/dist/models/design-credentials.mjs.map +1 -0
  463. package/dist/models/design-health.d.mts +14 -0
  464. package/dist/models/design-health.mjs +24 -0
  465. package/dist/models/design-health.mjs.map +1 -0
  466. package/dist/models/design-nodes.d.mts +81 -0
  467. package/dist/models/design-nodes.mjs +221 -0
  468. package/dist/models/design-nodes.mjs.map +1 -0
  469. package/dist/models/design-renders.mjs +73 -0
  470. package/dist/models/design-renders.mjs.map +1 -0
  471. package/dist/models/design-resolve.d.mts +27 -0
  472. package/dist/models/design-resolve.mjs +40 -0
  473. package/dist/models/design-resolve.mjs.map +1 -0
  474. package/dist/models/design.d.mts +37 -0
  475. package/dist/models/design.mjs +89 -0
  476. package/dist/models/design.mjs.map +1 -0
  477. package/dist/models/inherited-ratio.d.mts +19 -0
  478. package/dist/models/inherited-ratio.mjs +21 -0
  479. package/dist/models/inherited-ratio.mjs.map +1 -0
  480. package/dist/models/insight.d.mts +68 -0
  481. package/dist/models/insight.mjs +161 -0
  482. package/dist/models/insight.mjs.map +1 -0
  483. package/dist/models/label.d.mts +4 -4
  484. package/dist/models/label.mjs +26 -12
  485. package/dist/models/label.mjs.map +1 -1
  486. package/dist/models/member.d.mts +1 -3
  487. package/dist/models/member.mjs +6 -6
  488. package/dist/models/member.mjs.map +1 -1
  489. package/dist/models/notification-channel.d.mts +37 -5
  490. package/dist/models/notification-channel.mjs +89 -11
  491. package/dist/models/notification-channel.mjs.map +1 -1
  492. package/dist/models/notification-subscription.d.mts +1 -4
  493. package/dist/models/notification-subscription.mjs +8 -11
  494. package/dist/models/notification-subscription.mjs.map +1 -1
  495. package/dist/models/project-group-mapping.d.mts +6 -3
  496. package/dist/models/project-group-mapping.mjs +15 -6
  497. package/dist/models/project-group-mapping.mjs.map +1 -1
  498. package/dist/models/project.d.mts +9 -3
  499. package/dist/models/project.mjs +10 -6
  500. package/dist/models/project.mjs.map +1 -1
  501. package/dist/models/public-origin.d.mts +61 -0
  502. package/dist/models/public-origin.mjs +113 -0
  503. package/dist/models/public-origin.mjs.map +1 -0
  504. package/dist/models/review-switch-off.d.mts +12 -0
  505. package/dist/models/review-switch-off.mjs +25 -0
  506. package/dist/models/review-switch-off.mjs.map +1 -0
  507. package/dist/models/site-settings.d.mts +21 -0
  508. package/dist/models/site-settings.mjs +47 -0
  509. package/dist/models/site-settings.mjs.map +1 -0
  510. package/dist/models/snapshot.d.mts +39 -3
  511. package/dist/models/snapshot.mjs +54 -5
  512. package/dist/models/snapshot.mjs.map +1 -1
  513. package/dist/models/token.d.mts +13 -3
  514. package/dist/models/token.mjs +24 -7
  515. package/dist/models/token.mjs.map +1 -1
  516. package/dist/models/usage.d.mts +74 -0
  517. package/dist/models/usage.mjs +148 -0
  518. package/dist/models/usage.mjs.map +1 -0
  519. package/dist/models/user.d.mts +1 -3
  520. package/dist/models/user.mjs +5 -5
  521. package/dist/models/user.mjs.map +1 -1
  522. package/dist/models/webhook.d.mts +15 -3
  523. package/dist/models/webhook.mjs +34 -6
  524. package/dist/models/webhook.mjs.map +1 -1
  525. package/dist/models.d.mts +30 -4
  526. package/dist/models.mjs +31 -6
  527. package/dist/options.d.mts +16 -0
  528. package/dist/options.mjs +88 -0
  529. package/dist/options.mjs.map +1 -0
  530. package/dist/paths.d.mts +21 -6
  531. package/dist/paths.mjs +57 -12
  532. package/dist/paths.mjs.map +1 -1
  533. package/dist/retention/ai.d.mts +16 -0
  534. package/dist/retention/ai.mjs +22 -0
  535. package/dist/retention/ai.mjs.map +1 -0
  536. package/dist/retention/pending.mjs +46 -0
  537. package/dist/retention/pending.mjs.map +1 -0
  538. package/dist/retention/published-gzip-sweep.mjs +28 -0
  539. package/dist/retention/published-gzip-sweep.mjs.map +1 -0
  540. package/dist/retention/screenshot-sweep.d.mts +49 -0
  541. package/dist/retention/screenshot-sweep.mjs +127 -0
  542. package/dist/retention/screenshot-sweep.mjs.map +1 -0
  543. package/dist/retention.d.mts +16 -4
  544. package/dist/retention.mjs +76 -16
  545. package/dist/retention.mjs.map +1 -1
  546. package/dist/schema/baseline.d.mts +8 -2
  547. package/dist/schema/build-component.d.mts +23 -0
  548. package/dist/schema/build-review.d.mts +15 -0
  549. package/dist/schema/build.d.mts +7 -2
  550. package/dist/schema/capture-attempt.d.mts +0 -2
  551. package/dist/schema/capture-job.d.mts +58 -0
  552. package/dist/schema/capture-shard.d.mts +33 -0
  553. package/dist/schema/comment.d.mts +2 -2
  554. package/dist/schema/connection.d.mts +22 -0
  555. package/dist/schema/content-ref.d.mts +0 -2
  556. package/dist/schema/design.d.mts +56 -0
  557. package/dist/schema/insight.d.mts +52 -0
  558. package/dist/schema/label.d.mts +0 -2
  559. package/dist/schema/member.d.mts +0 -2
  560. package/dist/schema/notification.d.mts +4 -2
  561. package/dist/schema/project-group-mapping.d.mts +0 -2
  562. package/dist/schema/project.d.mts +21 -2
  563. package/dist/schema/site-setting.d.mts +19 -0
  564. package/dist/schema/snapshot.d.mts +17 -2
  565. package/dist/schema/token.d.mts +0 -2
  566. package/dist/schema/usage.d.mts +28 -0
  567. package/dist/schema/user.d.mts +0 -2
  568. package/dist/schema/webhook.d.mts +0 -2
  569. package/dist/schema.d.mts +12 -6
  570. package/dist/serverless.d.mts +19 -0
  571. package/dist/serverless.mjs +36 -0
  572. package/dist/serverless.mjs.map +1 -0
  573. package/dist/test-helpers/build-reference-contract.d.mts +14 -0
  574. package/dist/test-helpers/build-reference-contract.mjs +66 -0
  575. package/dist/test-helpers/build-reference-contract.mjs.map +1 -0
  576. package/dist/test-helpers/create-project.d.mts +1 -3
  577. package/dist/test-helpers/create-project.mjs +1 -2
  578. package/dist/test-helpers/database-contract.d.mts +0 -2
  579. package/dist/test-helpers/database-contract.mjs +37 -2
  580. package/dist/test-helpers/database-contract.mjs.map +1 -1
  581. package/dist/test-helpers/deferred.d.mts +37 -0
  582. package/dist/test-helpers/deferred.mjs +60 -0
  583. package/dist/test-helpers/deferred.mjs.map +1 -0
  584. package/dist/test-helpers/design-contract.d.mts +19 -0
  585. package/dist/test-helpers/design-contract.mjs +39 -0
  586. package/dist/test-helpers/design-contract.mjs.map +1 -0
  587. package/dist/test-helpers/fake-adapters.d.mts +0 -2
  588. package/dist/test-helpers/fake-adapters.mjs +1 -2
  589. package/dist/test-helpers/fake-database.d.mts +0 -2
  590. package/dist/test-helpers/fake-database.mjs +21 -4
  591. package/dist/test-helpers/fake-database.mjs.map +1 -1
  592. package/dist/test-helpers/fake-design.d.mts +41 -0
  593. package/dist/test-helpers/fake-design.mjs +113 -0
  594. package/dist/test-helpers/fake-design.mjs.map +1 -0
  595. package/dist/test-helpers/fake-notifier.d.mts +19 -0
  596. package/dist/test-helpers/fake-notifier.mjs +43 -0
  597. package/dist/test-helpers/fake-notifier.mjs.map +1 -0
  598. package/dist/test-helpers/fake-storage.d.mts +0 -2
  599. package/dist/test-helpers/fake-storage.mjs +1 -2
  600. package/dist/test-helpers/fake-tables.mjs +260 -69
  601. package/dist/test-helpers/fake-tables.mjs.map +1 -1
  602. package/dist/test-helpers/manual-clock.d.mts +25 -0
  603. package/dist/test-helpers/manual-clock.mjs +55 -0
  604. package/dist/test-helpers/manual-clock.mjs.map +1 -0
  605. package/dist/test-helpers/notifier-contract.d.mts +7 -3
  606. package/dist/test-helpers/notifier-contract.mjs +33 -5
  607. package/dist/test-helpers/notifier-contract.mjs.map +1 -1
  608. package/dist/test-helpers/queue-contract.d.mts +16 -4
  609. package/dist/test-helpers/queue-contract.mjs +196 -3
  610. package/dist/test-helpers/queue-contract.mjs.map +1 -1
  611. package/dist/test-helpers/queue-multi-instance.d.mts +18 -0
  612. package/dist/test-helpers/queue-multi-instance.mjs +205 -0
  613. package/dist/test-helpers/queue-multi-instance.mjs.map +1 -0
  614. package/dist/test-helpers/runner-contract.d.mts +0 -2
  615. package/dist/test-helpers/runner-contract.mjs +12 -2
  616. package/dist/test-helpers/runner-contract.mjs.map +1 -1
  617. package/dist/test-helpers/sql-chunks.mjs +25 -2
  618. package/dist/test-helpers/sql-chunks.mjs.map +1 -1
  619. package/dist/test-helpers/storage-contract.d.mts +0 -2
  620. package/dist/test-helpers/storage-contract.mjs +2 -3
  621. package/dist/test-helpers.d.mts +10 -4
  622. package/dist/test-helpers.mjs +9 -3
  623. package/dist/tracing.mjs +36 -6
  624. package/dist/tracing.mjs.map +1 -1
  625. package/dist/types.d.mts +14 -5
  626. package/dist/types.mjs +22 -6
  627. package/dist/types.mjs.map +1 -1
  628. package/dist/urls.d.mts +4 -2
  629. package/dist/urls.mjs +12 -4
  630. package/dist/urls.mjs.map +1 -1
  631. package/dist/utils/adaptive-concurrency.d.mts +64 -0
  632. package/dist/utils/adaptive-concurrency.mjs +148 -0
  633. package/dist/utils/adaptive-concurrency.mjs.map +1 -0
  634. package/dist/utils/connect-retry.d.mts +26 -0
  635. package/dist/utils/connect-retry.mjs +42 -0
  636. package/dist/utils/connect-retry.mjs.map +1 -0
  637. package/dist/utils/encrypt.d.mts +0 -2
  638. package/dist/utils/encrypt.mjs +1 -2
  639. package/dist/utils/environment.d.mts +17 -0
  640. package/dist/utils/environment.mjs +58 -0
  641. package/dist/utils/environment.mjs.map +1 -0
  642. package/dist/utils/hash.d.mts +0 -2
  643. package/dist/utils/hash.mjs +1 -2
  644. package/dist/utils/http.d.mts +29 -3
  645. package/dist/utils/http.mjs +100 -19
  646. package/dist/utils/http.mjs.map +1 -1
  647. package/dist/utils/map-adaptive.d.mts +13 -0
  648. package/dist/utils/map-adaptive.mjs +71 -0
  649. package/dist/utils/map-adaptive.mjs.map +1 -0
  650. package/dist/utils/map-limit.d.mts +8 -0
  651. package/dist/utils/map-limit.mjs +31 -0
  652. package/dist/utils/map-limit.mjs.map +1 -0
  653. package/dist/utils/mime.d.mts +0 -2
  654. package/dist/utils/mime.mjs +1 -2
  655. package/dist/utils/page-limiter.d.mts +35 -0
  656. package/dist/utils/page-limiter.mjs +55 -0
  657. package/dist/utils/page-limiter.mjs.map +1 -0
  658. package/dist/utils/path-security.d.mts +0 -2
  659. package/dist/utils/path-security.mjs +2 -4
  660. package/dist/utils/path-security.mjs.map +1 -1
  661. package/dist/utils/public-origin.d.mts +18 -0
  662. package/dist/utils/public-origin.mjs +74 -0
  663. package/dist/utils/public-origin.mjs.map +1 -0
  664. package/dist/utils/redact.d.mts +0 -2
  665. package/dist/utils/redact.mjs +4 -2
  666. package/dist/utils/redact.mjs.map +1 -1
  667. package/dist/utils/remote-environment.d.mts +76 -0
  668. package/dist/utils/remote-environment.mjs +163 -0
  669. package/dist/utils/remote-environment.mjs.map +1 -0
  670. package/dist/utils/resources.d.mts +62 -0
  671. package/dist/utils/resources.mjs +121 -0
  672. package/dist/utils/resources.mjs.map +1 -0
  673. package/dist/utils/screenshot-store.d.mts +13 -0
  674. package/dist/utils/screenshot-store.mjs +40 -0
  675. package/dist/utils/screenshot-store.mjs.map +1 -0
  676. package/dist/utils/session-gate.d.mts +23 -0
  677. package/dist/utils/session-gate.mjs +69 -0
  678. package/dist/utils/session-gate.mjs.map +1 -0
  679. package/dist/utils/storybook-token.d.mts +89 -0
  680. package/dist/utils/storybook-token.mjs +135 -0
  681. package/dist/utils/storybook-token.mjs.map +1 -0
  682. package/dist/utils/storybook-url.d.mts +13 -0
  683. package/dist/utils/storybook-url.mjs +20 -0
  684. package/dist/utils/storybook-url.mjs.map +1 -0
  685. package/dist/utils/timing.d.mts +0 -2
  686. package/dist/utils/timing.mjs +2 -3
  687. package/dist/utils/timing.mjs.map +1 -1
  688. package/dist/utils/ulid.d.mts +0 -2
  689. package/dist/utils/ulid.mjs +1 -2
  690. package/dist/utils/zip-read.mjs +128 -0
  691. package/dist/utils/zip-read.mjs.map +1 -0
  692. package/dist/utils/zip-write.d.mts +16 -0
  693. package/dist/utils/zip-write.mjs +187 -0
  694. package/dist/utils/zip-write.mjs.map +1 -0
  695. package/dist/utils.d.mts +17 -3
  696. package/dist/utils.mjs +18 -4
  697. package/package.json +35 -26
  698. package/dist/adapter/capture-runner.mjs.map +0 -1
  699. package/dist/adapter/git-host/comments.d.mts +0 -41
  700. package/dist/adapter/git-host/comments.mjs +0 -54
  701. package/dist/adapter/git-host/comments.mjs.map +0 -1
  702. package/dist/adapter/git-host/helpers.d.mts +0 -13
  703. package/dist/adapter/git-host/helpers.mjs +0 -30
  704. package/dist/adapter/git-host/helpers.mjs.map +0 -1
  705. package/dist/adapter/git-host.d.mts +0 -42
  706. package/dist/capture/queue.d.mts +0 -38
  707. package/dist/capture/queue.mjs +0 -98
  708. package/dist/capture/queue.mjs.map +0 -1
  709. package/dist/capture/recovery.d.mts +0 -21
  710. package/dist/capture/recovery.mjs +0 -83
  711. package/dist/capture/recovery.mjs.map +0 -1
  712. package/dist/capture/status-fanout.mjs +0 -72
  713. package/dist/capture/status-fanout.mjs.map +0 -1
  714. package/dist/diff/engine.d.mts +0 -16
  715. package/dist/diff/engine.mjs +0 -87
  716. package/dist/diff/engine.mjs.map +0 -1
  717. package/dist/diff/options.d.mts +0 -42
  718. package/dist/diff/options.mjs +0 -15
  719. package/dist/diff/options.mjs.map +0 -1
  720. package/dist/models/status-config.d.mts +0 -38
  721. package/dist/models/status-config.mjs +0 -63
  722. package/dist/models/status-config.mjs.map +0 -1
  723. package/dist/schema/status-config.d.mts +0 -16
  724. package/dist/test-helpers/git-contract.d.mts +0 -11
  725. package/dist/test-helpers/git-contract.mjs +0 -34
  726. package/dist/test-helpers/git-contract.mjs.map +0 -1
  727. /package/dist/adapter/{git-host.mjs → oauth.mjs} +0 -0
@@ -1,13 +1,20 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
+ import { sanitizeErrorText } from "../../utils/redact.mjs";
4
5
  import { formatNotification, formatSystemNotification } from "./format.mjs";
5
- //#region src/adapters/notifier/events.ts
6
+ import { isStateProvider } from "./provider.mjs";
7
+ // src/adapters/notifier/events.ts
6
8
  /** Check an event against a channel's allowlist (empty = all). */
7
9
  function subscribed(channel, event) {
8
10
  if (!channel.enabled) return false;
9
11
  return channel.events.length === 0 || channel.events.includes(event);
10
12
  }
13
+ /** `state` channels (git hosts) follow build state, never the message fan-out. */
14
+ function isMessageChannel(notifiers, channel) {
15
+ const provider = providerFor(notifiers, channel.provider);
16
+ return provider === void 0 || !isStateProvider(provider);
17
+ }
11
18
  /** Resolve a provider for a channel kind, or undefined when unwired. */
12
19
  function providerFor(notifiers, kind) {
13
20
  return notifiers?.find((candidate) => candidate.metadata.kind === kind);
@@ -16,6 +23,7 @@ function providerFor(notifiers, kind) {
16
23
  async function deliver(notifiers, channel, formatted) {
17
24
  const provider = providerFor(notifiers, channel.provider);
18
25
  if (!provider) throw new Error(`notifier missing: ${channel.provider}`);
26
+ if (isStateProvider(provider)) throw new Error(`notifier ${channel.provider} delivers state, not messages`);
19
27
  await provider.create({
20
28
  config: channel.config,
21
29
  secret: channel.secret
@@ -24,22 +32,33 @@ async function deliver(notifiers, channel, formatted) {
24
32
  formatted
25
33
  });
26
34
  }
35
+ /** Deliver to one channel, report the outcome and swallow the failure (logged). */
36
+ async function deliverReported(options, channel, formatted, failure) {
37
+ let problem;
38
+ try {
39
+ await deliver(options.notifiers, channel, formatted);
40
+ } catch (error) {
41
+ options.logger?.warn({
42
+ err: error,
43
+ channelId: channel.id
44
+ }, failure);
45
+ problem = sanitizeErrorText(error instanceof Error ? error.message : String(error), 500);
46
+ }
47
+ await options.onOutcome?.({
48
+ channelId: channel.id,
49
+ ...problem === void 0 ? {} : { error: problem }
50
+ });
51
+ }
27
52
  /**
28
53
  * Deliver a project event to every subscribed channel.
29
54
  * Inline best-effort: `Promise.allSettled`, failures logged and swallowed.
30
55
  */
31
56
  async function emitNotifications(event, options = {}) {
32
- const targets = (options.channels ?? []).filter((channel) => subscribed(channel, event.event));
57
+ const targets = (options.channels ?? []).filter((channel) => subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel));
33
58
  if (targets.length === 0) return;
59
+ const formatted = formatNotification(event, options.brand);
34
60
  await Promise.allSettled(targets.map(async (channel) => {
35
- try {
36
- await deliver(options.notifiers, channel, formatNotification(event, options.brand));
37
- } catch (error) {
38
- options.logger?.warn({
39
- err: error,
40
- channelId: channel.id
41
- }, "notification failed");
42
- }
61
+ await deliverReported(options, channel, formatted, "notification failed");
43
62
  }));
44
63
  }
45
64
  /**
@@ -47,20 +66,13 @@ async function emitNotifications(event, options = {}) {
47
66
  * (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).
48
67
  */
49
68
  async function emitSystemNotification(event, options = {}) {
50
- const targets = (options.channels ?? []).filter((channel) => channel.projectId === null && subscribed(channel, event.event));
69
+ const targets = (options.channels ?? []).filter((channel) => channel.projectId === null && subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel));
51
70
  if (targets.length === 0) return;
71
+ const formatted = formatSystemNotification(event, options.brand);
52
72
  await Promise.allSettled(targets.map(async (channel) => {
53
- try {
54
- await deliver(options.notifiers, channel, formatSystemNotification(event, options.brand));
55
- } catch (error) {
56
- options.logger?.warn({
57
- err: error,
58
- channelId: channel.id
59
- }, "system notification failed");
60
- }
73
+ await deliverReported(options, channel, formatted, "system notification failed");
61
74
  }));
62
75
  }
63
- //#endregion
64
76
  export { emitNotifications, emitSystemNotification };
65
77
 
66
78
  //# sourceMappingURL=events.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.mjs","names":[],"sources":["../../../src/adapters/notifier/events.ts"],"sourcesContent":["import type { Logger } from \"../../logger.ts\";\nimport { formatNotification, formatSystemNotification } from \"./format.ts\";\nimport type { NotifierProvider } from \"./provider.ts\";\nimport type {\n NotificationBrand,\n NotificationChannel,\n NotificationEvent,\n SystemNotification,\n} from \"./types.ts\";\n\n/** Options for project-event fan-out (inline best-effort, non-fatal). */\nexport interface EmitNotificationsOptions {\n notifiers?: NotifierProvider[];\n channels?: NotificationChannel[];\n brand?: NotificationBrand;\n logger?: Logger;\n}\n\n/** Check an event against a channel's allowlist (empty = all). */\nfunction subscribed(channel: NotificationChannel, event: string): boolean {\n if (!channel.enabled) {\n return false;\n }\n return channel.events.length === 0 || channel.events.includes(event);\n}\n\n/** Resolve a provider for a channel kind, or undefined when unwired. */\nfunction providerFor(\n notifiers: NotifierProvider[] | undefined,\n kind: string,\n): NotifierProvider | undefined {\n return notifiers?.find((candidate) => candidate.metadata.kind === kind);\n}\n\n/** Send one formatted event through a channel's provider (throws on failure). */\nasync function deliver(\n notifiers: NotifierProvider[] | undefined,\n channel: NotificationChannel,\n formatted: ReturnType<typeof formatNotification>,\n): Promise<void> {\n const provider = providerFor(notifiers, channel.provider);\n if (!provider) {\n throw new Error(`notifier missing: ${channel.provider}`);\n }\n const sender = provider.create({ config: channel.config, secret: channel.secret });\n await sender.send({ channel, formatted });\n}\n\n/**\n * Deliver a project event to every subscribed channel.\n * Inline best-effort: `Promise.allSettled`, failures logged and swallowed.\n */\nexport async function emitNotifications(\n event: NotificationEvent,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter((channel) => subscribed(channel, event.event));\n if (targets.length === 0) {\n return;\n }\n await Promise.allSettled(\n targets.map(async (channel) => {\n try {\n await deliver(options.notifiers, channel, formatNotification(event, options.brand));\n } catch (error) {\n options.logger?.warn({ err: error, channelId: channel.id }, \"notification failed\");\n }\n }),\n );\n}\n\n/**\n * Deliver a site-wide admin alert to project-less channels\n * (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).\n */\nexport async function emitSystemNotification(\n event: SystemNotification,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter(\n (channel) => channel.projectId === null && subscribed(channel, event.event),\n );\n if (targets.length === 0) {\n return;\n }\n await Promise.allSettled(\n targets.map(async (channel) => {\n try {\n await deliver(options.notifiers, channel, formatSystemNotification(event, options.brand));\n } catch (error) {\n options.logger?.warn({ err: error, channelId: channel.id }, \"system notification failed\");\n }\n }),\n );\n}\n"],"mappings":";;;;;;AAmBA,SAAS,WAAW,SAA8B,OAAwB;CACxE,IAAI,CAAC,QAAQ,SACX,OAAO;CAET,OAAO,QAAQ,OAAO,WAAW,KAAK,QAAQ,OAAO,SAAS,KAAK;AACrE;;AAGA,SAAS,YACP,WACA,MAC8B;CAC9B,OAAO,WAAW,MAAM,cAAc,UAAU,SAAS,SAAS,IAAI;AACxE;;AAGA,eAAe,QACb,WACA,SACA,WACe;CACf,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ;CACxD,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,qBAAqB,QAAQ,UAAU;CAGzD,MADe,SAAS,OAAO;EAAE,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;CAAO,CACrE,CAAC,CAAC,KAAK;EAAE;EAAS;CAAU,CAAC;AAC1C;;;;;AAMA,eAAsB,kBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QAAQ,YAAY,WAAW,SAAS,MAAM,KAAK,CAAC;CAC7F,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,IAAI;GACF,MAAM,QAAQ,QAAQ,WAAW,SAAS,mBAAmB,OAAO,QAAQ,KAAK,CAAC;EACpF,SAAS,OAAO;GACd,QAAQ,QAAQ,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,qBAAqB;EACnF;CACF,CAAC,CACH;AACF;;;;;AAMA,eAAsB,uBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QACtC,YAAY,QAAQ,cAAc,QAAQ,WAAW,SAAS,MAAM,KAAK,CAC5E;CACA,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,IAAI;GACF,MAAM,QAAQ,QAAQ,WAAW,SAAS,yBAAyB,OAAO,QAAQ,KAAK,CAAC;EAC1F,SAAS,OAAO;GACd,QAAQ,QAAQ,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,4BAA4B;EAC1F;CACF,CAAC,CACH;AACF"}
1
+ {"version":3,"file":"events.mjs","names":[],"sources":["../../../src/adapters/notifier/events.ts"],"sourcesContent":["import type { Logger } from \"../../logger.ts\";\nimport { sanitizeErrorText } from \"../../utils/redact.ts\";\nimport { formatNotification, formatSystemNotification } from \"./format.ts\";\nimport { isStateProvider, type NotifierProvider } from \"./provider.ts\";\nimport type {\n ChannelOutcome,\n NotificationBrand,\n NotificationChannel,\n NotificationEvent,\n SystemNotification,\n} from \"./types.ts\";\n\n/** Options for project-event fan-out (inline best-effort, non-fatal). */\nexport interface EmitNotificationsOptions {\n notifiers?: NotifierProvider[];\n channels?: NotificationChannel[];\n brand?: NotificationBrand;\n logger?: Logger;\n /** Called once per attempted channel so the host can record or clear its last error. */\n onOutcome?: (outcome: ChannelOutcome) => Promise<void> | void;\n}\n\n/** Check an event against a channel's allowlist (empty = all). */\nfunction subscribed(channel: NotificationChannel, event: string): boolean {\n if (!channel.enabled) {\n return false;\n }\n return channel.events.length === 0 || channel.events.includes(event);\n}\n\n/** `state` channels (git hosts) follow build state, never the message fan-out. */\nfunction isMessageChannel(\n notifiers: NotifierProvider[] | undefined,\n channel: NotificationChannel,\n): boolean {\n const provider = providerFor(notifiers, channel.provider);\n return provider === undefined || !isStateProvider(provider);\n}\n\n/** Resolve a provider for a channel kind, or undefined when unwired. */\nfunction providerFor(\n notifiers: NotifierProvider[] | undefined,\n kind: string,\n): NotifierProvider | undefined {\n return notifiers?.find((candidate) => candidate.metadata.kind === kind);\n}\n\n/** Send one formatted event through a channel's provider (throws on failure). */\nasync function deliver(\n notifiers: NotifierProvider[] | undefined,\n channel: NotificationChannel,\n formatted: ReturnType<typeof formatNotification>,\n): Promise<void> {\n const provider = providerFor(notifiers, channel.provider);\n if (!provider) {\n throw new Error(`notifier missing: ${channel.provider}`);\n }\n if (isStateProvider(provider)) {\n throw new Error(`notifier ${channel.provider} delivers state, not messages`);\n }\n const sender = provider.create({ config: channel.config, secret: channel.secret });\n await sender.send({ channel, formatted });\n}\n\n/** Deliver to one channel, report the outcome and swallow the failure (logged). */\nasync function deliverReported(\n options: EmitNotificationsOptions,\n channel: NotificationChannel,\n formatted: ReturnType<typeof formatNotification>,\n failure: string,\n): Promise<void> {\n let problem: string | undefined;\n try {\n await deliver(options.notifiers, channel, formatted);\n } catch (error) {\n options.logger?.warn({ err: error, channelId: channel.id }, failure);\n problem = sanitizeErrorText(error instanceof Error ? error.message : String(error), 500);\n }\n await options.onOutcome?.({\n channelId: channel.id,\n ...(problem === undefined ? {} : { error: problem }),\n });\n}\n\n/**\n * Deliver a project event to every subscribed channel.\n * Inline best-effort: `Promise.allSettled`, failures logged and swallowed.\n */\nexport async function emitNotifications(\n event: NotificationEvent,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter(\n (channel) => subscribed(channel, event.event) && isMessageChannel(options.notifiers, channel),\n );\n if (targets.length === 0) {\n return;\n }\n const formatted = formatNotification(event, options.brand);\n await Promise.allSettled(\n targets.map(async (channel) => {\n await deliverReported(options, channel, formatted, \"notification failed\");\n }),\n );\n}\n\n/**\n * Deliver a site-wide admin alert to project-less channels\n * (e.g. `sys:user-created`, `sys:capture-failed`, `sys:purge-completed`).\n */\nexport async function emitSystemNotification(\n event: SystemNotification,\n options: EmitNotificationsOptions = {},\n): Promise<void> {\n const targets = (options.channels ?? []).filter(\n (channel) =>\n channel.projectId === null &&\n subscribed(channel, event.event) &&\n isMessageChannel(options.notifiers, channel),\n );\n if (targets.length === 0) {\n return;\n }\n const formatted = formatSystemNotification(event, options.brand);\n await Promise.allSettled(\n targets.map(async (channel) => {\n await deliverReported(options, channel, formatted, \"system notification failed\");\n }),\n );\n}\n"],"mappings":";;;;;;;;AAuBA,SAAS,WAAW,SAA8B,OAAwB;CACxE,IAAI,CAAC,QAAQ,SACX,OAAO;CAET,OAAO,QAAQ,OAAO,WAAW,KAAK,QAAQ,OAAO,SAAS,KAAK;AACrE;;AAGA,SAAS,iBACP,WACA,SACS;CACT,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ;CACxD,OAAO,aAAa,KAAA,KAAa,CAAC,gBAAgB,QAAQ;AAC5D;;AAGA,SAAS,YACP,WACA,MAC8B;CAC9B,OAAO,WAAW,MAAM,cAAc,UAAU,SAAS,SAAS,IAAI;AACxE;;AAGA,eAAe,QACb,WACA,SACA,WACe;CACf,MAAM,WAAW,YAAY,WAAW,QAAQ,QAAQ;CACxD,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,qBAAqB,QAAQ,UAAU;CAEzD,IAAI,gBAAgB,QAAQ,GAC1B,MAAM,IAAI,MAAM,YAAY,QAAQ,SAAS,8BAA8B;CAG7E,MADe,SAAS,OAAO;EAAE,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;CAAO,CACrE,CAAC,CAAC,KAAK;EAAE;EAAS;CAAU,CAAC;AAC1C;;AAGA,eAAe,gBACb,SACA,SACA,WACA,SACe;CACf,IAAI;CACJ,IAAI;EACF,MAAM,QAAQ,QAAQ,WAAW,SAAS,SAAS;CACrD,SAAS,OAAO;EACd,QAAQ,QAAQ,KAAK;GAAE,KAAK;GAAO,WAAW,QAAQ;EAAG,GAAG,OAAO;EACnE,UAAU,kBAAkB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,GAAG;CACzF;CACA,MAAM,QAAQ,YAAY;EACxB,WAAW,QAAQ;EACnB,GAAI,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,QAAQ;CACpD,CAAC;AACH;;;;;AAMA,eAAsB,kBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QACtC,YAAY,WAAW,SAAS,MAAM,KAAK,KAAK,iBAAiB,QAAQ,WAAW,OAAO,CAC9F;CACA,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,YAAY,mBAAmB,OAAO,QAAQ,KAAK;CACzD,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,MAAM,gBAAgB,SAAS,SAAS,WAAW,qBAAqB;CAC1E,CAAC,CACH;AACF;;;;;AAMA,eAAsB,uBACpB,OACA,UAAoC,CAAC,GACtB;CACf,MAAM,WAAW,QAAQ,YAAY,CAAC,EAAA,CAAG,QACtC,YACC,QAAQ,cAAc,QACtB,WAAW,SAAS,MAAM,KAAK,KAC/B,iBAAiB,QAAQ,WAAW,OAAO,CAC/C;CACA,IAAI,QAAQ,WAAW,GACrB;CAEF,MAAM,YAAY,yBAAyB,OAAO,QAAQ,KAAK;CAC/D,MAAM,QAAQ,WACZ,QAAQ,IAAI,OAAO,YAAY;EAC7B,MAAM,gBAAgB,SAAS,SAAS,WAAW,4BAA4B;CACjF,CAAC,CACH;AACF"}
@@ -1,7 +1,6 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
3
  import { ChannelToggles, FormattedNotification, NotificationBrand, NotificationEvent, SystemNotification } from "./types.mjs";
4
- //#region src/adapters/notifier/format.d.ts
5
4
  /**
6
5
  * Format a project event into subject/text/markdown/html using brand +
7
6
  * channel toggles. Pure (no I/O) so settings preview and senders share it.
@@ -9,6 +8,5 @@ import { ChannelToggles, FormattedNotification, NotificationBrand, NotificationE
9
8
  declare function formatNotification(event: NotificationEvent, brand?: NotificationBrand, toggles?: ChannelToggles): FormattedNotification;
10
9
  /** Format a site-wide admin alert (no project scope, always verbose). */
11
10
  declare function formatSystemNotification(event: SystemNotification, brand?: NotificationBrand): FormattedNotification;
12
- //#endregion
13
11
  export { formatNotification, formatSystemNotification };
14
12
  //# sourceMappingURL=format.d.mts.map
@@ -1,7 +1,7 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- //#region src/adapters/notifier/format.ts
4
+ // src/adapters/notifier/format.ts
5
5
  /** Escape HTML special chars in free-form values (commit messages, names). */
6
6
  function esc(value) {
7
7
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
@@ -90,7 +90,6 @@ function formatSystemNotification(event, brand) {
90
90
  subjectPrefix: "[Shelf sys]"
91
91
  });
92
92
  }
93
- //#endregion
94
93
  export { formatNotification, formatSystemNotification };
95
94
 
96
95
  //# sourceMappingURL=format.mjs.map
@@ -1,32 +1,76 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- import { FormattedNotification, NotificationChannel } from "./types.mjs";
3
+ import { FormattedNotification, NotificationChannel, NotifierState, NotifierStateTarget } from "./types.mjs";
4
4
  import { Adapter, AdapterMetadata } from "../../adapter/metadata.mjs";
5
5
  import { z } from "zod";
6
6
  import { Logger } from "pino";
7
- //#region src/adapters/notifier/provider.d.ts
7
+ /** How a provider delivers: `message` sends once, `state` makes a host show a named state. */
8
+ type NotifierDelivery = "message" | "state";
8
9
  /** Notifier-specific metadata (adds logo + config validation schema). */
9
10
  interface NotifierMetadata extends AdapterMetadata {
10
11
  readonly category: "notifier";
11
12
  readonly logo?: string;
12
13
  readonly schema: z.ZodType;
14
+ /** Delivery kind; absent means `message` (chat, email). */
15
+ readonly delivery?: NotifierDelivery;
13
16
  }
14
- /** Descriptor — registered at startup, validates per-channel config. */
15
- interface NotifierProvider extends Adapter<NotifierMetadata> {
17
+ /** Metadata of a `message` provider (Slack, Teams, email). */
18
+ interface MessageNotifierMetadata extends NotifierMetadata {
19
+ readonly delivery?: "message";
20
+ }
21
+ /** Metadata of a `state` provider (GitHub, GitLab): `delivery` is mandatory. */
22
+ interface StateNotifierMetadata extends NotifierMetadata {
23
+ readonly delivery: "state";
24
+ }
25
+ /** Descriptor of a `message` provider, registered at startup. */
26
+ interface MessageNotifierProvider extends Adapter<MessageNotifierMetadata> {
16
27
  create(opts: {
17
28
  config: unknown;
18
29
  secret?: string;
19
30
  logger?: Logger;
20
- }): NotifierAdapter;
31
+ }): MessageNotifierAdapter;
21
32
  }
22
- /** Runtime — bound to one channel config + decrypted secret, sends one message. */
23
- interface NotifierAdapter extends Adapter<NotifierMetadata> {
33
+ /** Descriptor of a `state` provider, registered at startup. */
34
+ interface StateNotifierProvider extends Adapter<StateNotifierMetadata> {
35
+ create(opts: {
36
+ config: unknown;
37
+ secret?: string;
38
+ logger?: Logger;
39
+ }): StateNotifierAdapter;
40
+ }
41
+ /** Descriptor — registered at startup, validates per-channel config. */
42
+ type NotifierProvider = MessageNotifierProvider | StateNotifierProvider;
43
+ /** Runtime of a `message` provider — bound to one channel config + secret, sends one message. */
44
+ interface MessageNotifierAdapter extends Adapter<MessageNotifierMetadata> {
24
45
  send(input: {
25
46
  channel: NotificationChannel;
26
47
  formatted: FormattedNotification;
27
48
  logger?: Logger;
28
49
  }): Promise<void>;
29
50
  }
30
- //#endregion
31
- export { NotifierAdapter, NotifierMetadata, NotifierProvider };
51
+ /** Input of one idempotent state write. */
52
+ interface SetStateInput {
53
+ channel: NotificationChannel;
54
+ /** What to make the host show: a commit status or a pull-request comment. */
55
+ target: NotifierStateTarget;
56
+ state: NotifierState;
57
+ /**
58
+ * Link back to the build page; also keys the pull-request comment. Absent while no public origin
59
+ * is known (ADR 0007): a status then has no link and a comment is not written.
60
+ */
61
+ url?: string | undefined;
62
+ logger?: Logger;
63
+ }
64
+ /**
65
+ * Runtime of a `state` provider: idempotent, latest call wins. A provider that
66
+ * cannot show a target kind (no comment support) skips it silently.
67
+ */
68
+ interface StateNotifierAdapter extends Adapter<StateNotifierMetadata> {
69
+ setState(input: SetStateInput): Promise<void>;
70
+ }
71
+ /** Runtime — bound to one channel config + decrypted secret. */
72
+ type NotifierAdapter = MessageNotifierAdapter | StateNotifierAdapter;
73
+ /** True when the provider delivers state (git hosts) rather than messages. */
74
+ declare function isStateProvider(provider: NotifierProvider): provider is StateNotifierProvider;
75
+ export { MessageNotifierAdapter, MessageNotifierMetadata, MessageNotifierProvider, NotifierAdapter, NotifierDelivery, NotifierMetadata, NotifierProvider, SetStateInput, StateNotifierAdapter, StateNotifierMetadata, StateNotifierProvider, isStateProvider };
32
76
  //# sourceMappingURL=provider.d.mts.map
@@ -0,0 +1,11 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ // src/adapters/notifier/provider.ts
5
+ /** True when the provider delivers state (git hosts) rather than messages. */
6
+ function isStateProvider(provider) {
7
+ return provider.metadata.delivery === "state";
8
+ }
9
+ export { isStateProvider };
10
+
11
+ //# sourceMappingURL=provider.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.mjs","names":[],"sources":["../../../src/adapters/notifier/provider.ts"],"sourcesContent":["import type { Logger } from \"pino\";\nimport type { z } from \"zod\";\nimport type { Adapter, AdapterMetadata } from \"../metadata.ts\";\nimport type {\n FormattedNotification,\n NotificationChannel,\n NotifierState,\n NotifierStateTarget,\n} from \"./types.ts\";\n\n/** How a provider delivers: `message` sends once, `state` makes a host show a named state. */\nexport type NotifierDelivery = \"message\" | \"state\";\n\n/** Notifier-specific metadata (adds logo + config validation schema). */\nexport interface NotifierMetadata extends AdapterMetadata {\n readonly category: \"notifier\";\n readonly logo?: string;\n readonly schema: z.ZodType;\n /** Delivery kind; absent means `message` (chat, email). */\n readonly delivery?: NotifierDelivery;\n}\n\n/** Metadata of a `message` provider (Slack, Teams, email). */\nexport interface MessageNotifierMetadata extends NotifierMetadata {\n readonly delivery?: \"message\";\n}\n\n/** Metadata of a `state` provider (GitHub, GitLab): `delivery` is mandatory. */\nexport interface StateNotifierMetadata extends NotifierMetadata {\n readonly delivery: \"state\";\n}\n\n/** Descriptor of a `message` provider, registered at startup. */\nexport interface MessageNotifierProvider extends Adapter<MessageNotifierMetadata> {\n create(opts: { config: unknown; secret?: string; logger?: Logger }): MessageNotifierAdapter;\n}\n\n/** Descriptor of a `state` provider, registered at startup. */\nexport interface StateNotifierProvider extends Adapter<StateNotifierMetadata> {\n create(opts: { config: unknown; secret?: string; logger?: Logger }): StateNotifierAdapter;\n}\n\n/** Descriptor — registered at startup, validates per-channel config. */\nexport type NotifierProvider = MessageNotifierProvider | StateNotifierProvider;\n\n/** Runtime of a `message` provider — bound to one channel config + secret, sends one message. */\nexport interface MessageNotifierAdapter extends Adapter<MessageNotifierMetadata> {\n send(input: {\n channel: NotificationChannel;\n formatted: FormattedNotification;\n logger?: Logger;\n }): Promise<void>;\n}\n\n/** Input of one idempotent state write. */\nexport interface SetStateInput {\n channel: NotificationChannel;\n /** What to make the host show: a commit status or a pull-request comment. */\n target: NotifierStateTarget;\n state: NotifierState;\n /**\n * Link back to the build page; also keys the pull-request comment. Absent while no public origin\n * is known (ADR 0007): a status then has no link and a comment is not written.\n */\n url?: string | undefined;\n logger?: Logger;\n}\n\n/**\n * Runtime of a `state` provider: idempotent, latest call wins. A provider that\n * cannot show a target kind (no comment support) skips it silently.\n */\nexport interface StateNotifierAdapter extends Adapter<StateNotifierMetadata> {\n setState(input: SetStateInput): Promise<void>;\n}\n\n/** Runtime — bound to one channel config + decrypted secret. */\nexport type NotifierAdapter = MessageNotifierAdapter | StateNotifierAdapter;\n\n/** True when the provider delivers state (git hosts) rather than messages. */\nexport function isStateProvider(provider: NotifierProvider): provider is StateNotifierProvider {\n return provider.metadata.delivery === \"state\";\n}\n"],"mappings":";;;;;AAgFA,SAAgB,gBAAgB,UAA+D;CAC7F,OAAO,SAAS,SAAS,aAAa;AACxC"}
@@ -0,0 +1,22 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { Logger } from "../../logger.mjs";
4
+ import { NotificationChannel } from "./types.mjs";
5
+ import { StateNotifierProvider } from "./provider.mjs";
6
+ import { BuildStateSet } from "./build-state.mjs";
7
+ /** Default status-name prefix of a git channel (`<prefix>/testing`). */
8
+ declare const DEFAULT_STATUS_PREFIX = "storyshelf";
9
+ /** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */
10
+ declare function channelPrefix(channel: NotificationChannel): string;
11
+ /**
12
+ * Make the channel's host show `states` for the commit `sha`: every status, then the comment.
13
+ * Each write is idempotent (latest call wins). A failed status write throws so the caller can
14
+ * retry; a failed comment write is logged and never fails the statuses.
15
+ */
16
+ declare function writeBuildState(provider: StateNotifierProvider, channel: NotificationChannel, write: {
17
+ sha: string;
18
+ states: BuildStateSet;
19
+ logger?: Logger | undefined;
20
+ }): Promise<void>;
21
+ export { DEFAULT_STATUS_PREFIX, channelPrefix, writeBuildState };
22
+ //# sourceMappingURL=state.d.mts.map
@@ -0,0 +1,65 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ // src/adapters/notifier/state.ts
5
+ /** Default status-name prefix of a git channel (`<prefix>/testing`). */
6
+ const DEFAULT_STATUS_PREFIX = "storyshelf";
7
+ /** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */
8
+ function channelPrefix(channel) {
9
+ const prefix = channel.config["prefix"];
10
+ return typeof prefix === "string" && prefix.length > 0 ? prefix : DEFAULT_STATUS_PREFIX;
11
+ }
12
+ /**
13
+ * Make the channel's host show `states` for the commit `sha`: every status, then the comment.
14
+ * Each write is idempotent (latest call wins). A failed status write throws so the caller can
15
+ * retry; a failed comment write is logged and never fails the statuses.
16
+ */
17
+ async function writeBuildState(provider, channel, write) {
18
+ const { sha, states, logger } = write;
19
+ const adapter = provider.create({
20
+ config: channel.config,
21
+ secret: channel.secret,
22
+ logger
23
+ });
24
+ const failed = (await Promise.allSettled(states.statuses.map(async (status) => {
25
+ await adapter.setState({
26
+ channel,
27
+ target: {
28
+ kind: "status",
29
+ sha,
30
+ context: status.context,
31
+ description: status.description,
32
+ ...status.informational === true ? { informational: true } : {},
33
+ ...status.progress === void 0 ? {} : { progress: status.progress },
34
+ ...status.annotations === void 0 ? {} : { annotations: status.annotations },
35
+ ...status.omitted === void 0 ? {} : { omitted: status.omitted }
36
+ },
37
+ state: status.state,
38
+ url: status.url,
39
+ logger
40
+ });
41
+ }))).find((result) => result.status === "rejected");
42
+ if (failed?.status === "rejected") throw failed.reason;
43
+ if (states.comment !== null) {
44
+ const { comment } = states;
45
+ await adapter.setState({
46
+ channel,
47
+ target: {
48
+ kind: "comment",
49
+ sha,
50
+ markdown: comment.markdown
51
+ },
52
+ state: comment.state,
53
+ url: comment.url,
54
+ logger
55
+ }).catch((error) => {
56
+ logger?.warn({
57
+ err: error,
58
+ channelId: channel.id
59
+ }, "failed to upsert comment");
60
+ });
61
+ }
62
+ }
63
+ export { DEFAULT_STATUS_PREFIX, channelPrefix, writeBuildState };
64
+
65
+ //# sourceMappingURL=state.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.mjs","names":[],"sources":["../../../src/adapters/notifier/state.ts"],"sourcesContent":["/** Writing a build's desired states to one `state` channel (git hosts); see `build-state.ts` for what they are. */\nimport type { Logger } from \"../../logger.ts\";\nimport type { BuildStateSet } from \"./build-state.ts\";\nimport type { StateNotifierProvider } from \"./provider.ts\";\nimport type { NotificationChannel } from \"./types.ts\";\n\n/** Default status-name prefix of a git channel (`<prefix>/testing`). */\nexport const DEFAULT_STATUS_PREFIX = \"storyshelf\";\n\n/** The channel's status-name prefix: its `prefix` config, else {@link DEFAULT_STATUS_PREFIX}. */\nexport function channelPrefix(channel: NotificationChannel): string {\n const prefix = channel.config[\"prefix\"];\n return typeof prefix === \"string\" && prefix.length > 0 ? prefix : DEFAULT_STATUS_PREFIX;\n}\n\n/**\n * Make the channel's host show `states` for the commit `sha`: every status, then the comment.\n * Each write is idempotent (latest call wins). A failed status write throws so the caller can\n * retry; a failed comment write is logged and never fails the statuses.\n */\nexport async function writeBuildState(\n provider: StateNotifierProvider,\n channel: NotificationChannel,\n write: { sha: string; states: BuildStateSet; logger?: Logger | undefined },\n): Promise<void> {\n const { sha, states, logger } = write;\n const adapter = provider.create({ config: channel.config, secret: channel.secret, logger });\n const results = await Promise.allSettled(\n states.statuses.map(async (status) => {\n await adapter.setState({\n channel,\n target: {\n kind: \"status\",\n sha,\n context: status.context,\n description: status.description,\n ...(status.informational === true ? { informational: true } : {}),\n ...(status.progress === undefined ? {} : { progress: status.progress }),\n ...(status.annotations === undefined ? {} : { annotations: status.annotations }),\n ...(status.omitted === undefined ? {} : { omitted: status.omitted }),\n },\n state: status.state,\n url: status.url,\n logger,\n });\n }),\n );\n const failed = results.find((result) => result.status === \"rejected\");\n if (failed?.status === \"rejected\") {\n throw failed.reason;\n }\n if (states.comment !== null) {\n const { comment } = states;\n await adapter\n .setState({\n channel,\n target: { kind: \"comment\", sha, markdown: comment.markdown },\n state: comment.state,\n url: comment.url,\n logger,\n })\n .catch((error: unknown) => {\n logger?.warn({ err: error, channelId: channel.id }, \"failed to upsert comment\");\n });\n }\n}\n"],"mappings":";;;;;AAOA,MAAa,wBAAwB;;AAGrC,SAAgB,cAAc,SAAsC;CAClE,MAAM,SAAS,QAAQ,OAAO;CAC9B,OAAO,OAAO,WAAW,YAAY,OAAO,SAAS,IAAI,SAAS;AACpE;;;;;;AAOA,eAAsB,gBACpB,UACA,SACA,OACe;CACf,MAAM,EAAE,KAAK,QAAQ,WAAW;CAChC,MAAM,UAAU,SAAS,OAAO;EAAE,QAAQ,QAAQ;EAAQ,QAAQ,QAAQ;EAAQ;CAAO,CAAC;CAqB1F,MAAM,UAAS,MApBO,QAAQ,WAC5B,OAAO,SAAS,IAAI,OAAO,WAAW;EACpC,MAAM,QAAQ,SAAS;GACrB;GACA,QAAQ;IACN,MAAM;IACN;IACA,SAAS,OAAO;IAChB,aAAa,OAAO;IACpB,GAAI,OAAO,kBAAkB,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC/D,GAAI,OAAO,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,UAAU,OAAO,SAAS;IACrE,GAAI,OAAO,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,OAAO,YAAY;IAC9E,GAAI,OAAO,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;GACpE;GACA,OAAO,OAAO;GACd,KAAK,OAAO;GACZ;EACF,CAAC;CACH,CAAC,CACH,EAAA,CACuB,MAAM,WAAW,OAAO,WAAW,UAAU;CACpE,IAAI,QAAQ,WAAW,YACrB,MAAM,OAAO;CAEf,IAAI,OAAO,YAAY,MAAM;EAC3B,MAAM,EAAE,YAAY;EACpB,MAAM,QACH,SAAS;GACR;GACA,QAAQ;IAAE,MAAM;IAAW;IAAK,UAAU,QAAQ;GAAS;GAC3D,OAAO,QAAQ;GACf,KAAK,QAAQ;GACb;EACF,CAAC,CAAC,CACD,OAAO,UAAmB;GACzB,QAAQ,KAAK;IAAE,KAAK;IAAO,WAAW,QAAQ;GAAG,GAAG,0BAA0B;EAChF,CAAC;CACL;AACF"}
@@ -1,6 +1,5 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- //#region src/adapters/notifier/types.d.ts
4
3
  /** Shared event envelope for human-facing notifications. */
5
4
  interface NotificationEvent {
6
5
  event: string;
@@ -42,6 +41,55 @@ interface NotificationChannel {
42
41
  secret?: string;
43
42
  events: string[];
44
43
  enabled: boolean;
44
+ /** Last delivery error, cleared by the next successful delivery. */
45
+ lastError?: string;
46
+ }
47
+ /**
48
+ * What a `state` provider shows for a build: pending, passed, failed, or cancelled by a user
49
+ * (a host without a cancelled state shows it like the nearest failure-class state).
50
+ */
51
+ type NotifierState = "pending" | "success" | "failure" | "cancelled";
52
+ /**
53
+ * One per-story finding a host that supports it (GitHub check runs) shows beside a status: a
54
+ * changed snapshot that deep-links to its review page.
55
+ */
56
+ interface StateAnnotation {
57
+ /** The story file the snapshot belongs to (the host anchors the finding there). */
58
+ path: string;
59
+ /** Short heading, e.g. `Button / Primary (chromium)`. */
60
+ title: string;
61
+ message: string;
62
+ /** Absolute link to the snapshot's review page. */
63
+ url: string;
64
+ level: "notice" | "warning";
65
+ }
66
+ /** Where a `state` provider writes: a commit status or a pull-request comment. */
67
+ type NotifierStateTarget = {
68
+ kind: "status";
69
+ sha: string;
70
+ /** Full status name on the host, e.g. `storyshelf/testing` (the caller owns the prefix). */
71
+ context: string;
72
+ /** Short text beside the status; the provider supplies a default. */
73
+ description?: string;
74
+ /** For a `pending` state: not started (`queued`) or under way (`running`; the default). */
75
+ progress?: "queued" | "running";
76
+ /** Never a merge gate (the Storybook status): a failure is shown as neutral where the host has it. */
77
+ informational?: boolean;
78
+ /** Per-snapshot findings of the build; only a host with annotations shows them. */
79
+ annotations?: StateAnnotation[];
80
+ /** Changed snapshots beyond `annotations` (cut at the cap); the host says "and N more". */
81
+ omitted?: number;
82
+ } | {
83
+ kind: "comment";
84
+ sha: string;
85
+ /** Comment body below the idempotency marker. */
86
+ markdown: string;
87
+ };
88
+ /** Result of one delivery attempt to a channel, reported to the host for health display. */
89
+ interface ChannelOutcome {
90
+ channelId: string;
91
+ /** Sanitized error text, absent on success. */
92
+ error?: string;
45
93
  }
46
94
  /** App-level (site-wide) admin alert — no project scope. */
47
95
  interface SystemNotification {
@@ -50,7 +98,6 @@ interface SystemNotification {
50
98
  timestamp: string;
51
99
  }
52
100
  /** Site-wide events for admins (new users, failures, purge). */
53
- type SystemEventName = "sys:user-created" | "sys:invite-issued" | "sys:auth-failed" | "sys:capture-failed" | "sys:purge-completed";
54
- //#endregion
55
- export { ChannelToggles, FormattedNotification, NotificationBrand, NotificationChannel, NotificationEvent, SystemEventName, SystemNotification };
101
+ type SystemEventName = "sys:user-created" | "sys:invite-issued" | "sys:auth-failed" | "sys:capture-failed" | "sys:purge-completed" | "sys:notify-failed" | "sys:ai-budget";
102
+ export { ChannelOutcome, ChannelToggles, FormattedNotification, NotificationBrand, NotificationChannel, NotificationEvent, NotifierState, NotifierStateTarget, StateAnnotation, SystemEventName, SystemNotification };
56
103
  //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1,168 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { BrowserName, CaptureTarget, TargetReach } from "./capture-target.mjs";
4
+ /** How a runner talks to the service: Playwright's own protocol, or the Chrome DevTools Protocol. */
5
+ type RemoteProtocol = "playwright" | "cdp";
6
+ /** Where and how to connect. A function `connect` is called per connection, so a token can be fresh. */
7
+ interface RemoteConnection {
8
+ /** `ws(s)://…` (CDP also accepts `http(s)://…`). May carry credentials: it is never logged. */
9
+ endpoint: string;
10
+ /** Request headers for the handshake, such as `authorization`. Never logged. */
11
+ headers?: Record<string, string>;
12
+ }
13
+ /** A connection a function `connect` returns, with what `release` needs back. */
14
+ interface RemoteLeasedConnection<TLease = unknown> extends RemoteConnection {
15
+ /** Opaque to the runner, handed to `release` once and never logged (it may carry credentials). */
16
+ lease?: TLease | undefined;
17
+ }
18
+ /** What a run is doing when it connects. */
19
+ type RemotePurpose = "render" | "extract" | "tests";
20
+ /** How a leased connection ended, handed to `release`. */
21
+ type RemoteLeaseOutcome = "finished" | "failed" | "cancelled";
22
+ /** What a function `connect` is told about the connection it is asked for. */
23
+ interface RemoteConnectContext {
24
+ engine: BrowserName;
25
+ /** The StoryShelf build; the same for every shard of it. */
26
+ buildId: string;
27
+ /** The shard's own id; the build id when the render is not sharded. */
28
+ runId: string;
29
+ /** The shard's 1-based position in the build's plan; `undefined` (never 0) when not sharded. */
30
+ shardIndex?: number | undefined;
31
+ /** `render` for a build or shard, `extract` for the parameter pre-pass, `tests` for `.test()` entries. */
32
+ purpose: RemotePurpose;
33
+ /** This connection's attempt, from 1; each retry connects anew. */
34
+ attempt: number;
35
+ /**
36
+ * Aborts while `connect` is pending: on `timeouts.acquireMs`, a cancel (user, build, render
37
+ * budget) and shutdown. Spent once `connect` resolves.
38
+ */
39
+ signal: AbortSignal;
40
+ }
41
+ /** What `release` is told about how the connection's render went. */
42
+ interface RemoteReleaseInfo {
43
+ outcome: RemoteLeaseOutcome;
44
+ /** Why it failed, for `failed`. Carries no credentials, but may carry provider text. */
45
+ error?: unknown;
46
+ }
47
+ /** What {@link defineRemote} takes: what `remote()` exposes to operators. */
48
+ interface RemoteOptions<TLease = unknown> {
49
+ /** The target name half (`chromium@<name>`): lowercase letters, digits and hyphens, at most 32. */
50
+ name: string;
51
+ /** The engines to offer (a subset of what the service has). */
52
+ engines: readonly BrowserName[];
53
+ /** Parallel sessions the plan allows: the page cap of the target, per process (decision 4). A function is read live. */
54
+ sessions: number | (() => number);
55
+ /** Maximum concurrent pages on each browser connection; independent of the shared session gate. */
56
+ maxPagesPerConnection?: number | undefined;
57
+ /**
58
+ * Maximum connections this process holds to the service at once (default: no cap). A separate
59
+ * limit from `sessions` (pages) and `maxPagesPerConnection`: a connection counts from the moment
60
+ * it is requested until its render has ended, a shared one once. Renders over the cap wait, and a
61
+ * cancel or shutdown ends the wait. Per process; the deployment-wide cap is another issue.
62
+ */
63
+ maxConnections?: number | undefined;
64
+ /** Declared, never inferred: how the runner talks to the service. */
65
+ protocol: RemoteProtocol;
66
+ /**
67
+ * Declared, never inferred: `loopback` when the remote browser can route back to this host
68
+ * (Playwright's `exposeNetwork: "<loopback>"`), else `url` (it needs a signed Storybook URL).
69
+ */
70
+ reach: TargetReach;
71
+ /**
72
+ * The connection: an object for a fixed service (validated at creation), or a function called
73
+ * for every connection (sync or async) to wake or start something, pick a server per shard, or
74
+ * mint a token. A throw is retried and ends as a `TargetLaunchError`.
75
+ */
76
+ connect: RemoteConnection | ((context: RemoteConnectContext) => RemoteLeasedConnection<TLease> | Promise<RemoteLeasedConnection<TLease>>);
77
+ /**
78
+ * Called once for every connection `connect` returned a `lease` for, after the render that used
79
+ * it finished, failed or was cancelled (and for leases still held at shutdown, `cancelled`).
80
+ * Only valid with a function `connect`. A throw or a timeout (`timeouts.releaseMs`) is logged and
81
+ * never fails the render.
82
+ */
83
+ release?: ((lease: TLease, info: RemoteReleaseInfo) => Promise<void> | void) | undefined;
84
+ /** OS the service renders on, reported when the page cannot tell (`linux-x64`, `windows`, …). */
85
+ platform?: string | undefined;
86
+ /** Connect retries: `attempts` after the first (default 3), `backoffMs` doubling (default 500). */
87
+ retry?: {
88
+ attempts?: number | undefined;
89
+ backoffMs?: number | undefined;
90
+ } | undefined;
91
+ /**
92
+ * `acquireMs` bounds the `connect` function, `connectMs` the handshake after it (a farm with a
93
+ * client cap queues extra connections, so a busy farm shows up as this timeout), `releaseMs`
94
+ * the `release` hook. All default to 30 000. `probeMs` bounds measuring the browser's
95
+ * environment once connected (default 15 000): a probe that overruns leaves the environment
96
+ * unknown with a warning, and a cancel stops it at once.
97
+ */
98
+ timeouts?: {
99
+ acquireMs?: number | undefined;
100
+ connectMs?: number | undefined;
101
+ releaseMs?: number | undefined;
102
+ probeMs?: number | undefined;
103
+ } | undefined;
104
+ }
105
+ /** One remote service, validated: an entry of a runner's `browsers`. */
106
+ interface RemoteBrowser {
107
+ readonly kind: "remote";
108
+ readonly name: string;
109
+ readonly engines: readonly BrowserName[];
110
+ readonly sessions: number | (() => number);
111
+ readonly maxPagesPerConnection?: number | undefined;
112
+ readonly maxConnections?: number | undefined;
113
+ readonly protocol: RemoteProtocol;
114
+ readonly reach: TargetReach;
115
+ readonly connect: RemoteOptions["connect"];
116
+ readonly release: ((lease: never, info: RemoteReleaseInfo) => Promise<void> | void) | undefined;
117
+ readonly platform: string | undefined;
118
+ readonly retry: {
119
+ readonly attempts: number;
120
+ readonly backoffMs: number;
121
+ };
122
+ readonly timeouts: {
123
+ readonly acquireMs: number;
124
+ readonly connectMs: number;
125
+ readonly releaseMs: number;
126
+ readonly probeMs: number;
127
+ };
128
+ }
129
+ /** What a runner supports, which {@link defineRemote} checks the service against. */
130
+ interface RemoteSupport {
131
+ /** Engines the runner can drive. */
132
+ engines: readonly BrowserName[];
133
+ /** Protocols the runner can speak. */
134
+ protocols: readonly RemoteProtocol[];
135
+ /** Shown in errors, for example `remote()`. */
136
+ label: string;
137
+ }
138
+ /** One target a remote service offers. */
139
+ interface RemoteTarget {
140
+ kind: "remote";
141
+ target: CaptureTarget;
142
+ engine: BrowserName;
143
+ remote: RemoteBrowser;
144
+ /** How the browser reaches the Storybook. */
145
+ reach: TargetReach;
146
+ }
147
+ /**
148
+ * Validate a remote service eagerly, so a mistake fails when the runner is created and not when the
149
+ * first build runs: unknown or moved options, the name, the sessions, the engines against what the
150
+ * runner drives, the protocol, the reach, and a fixed connection (endpoint scheme).
151
+ */
152
+ declare function defineRemote<TLease = unknown>(options: RemoteOptions<TLease>, support: RemoteSupport): RemoteBrowser;
153
+ /** The targets a service offers, in the order of its `engines`. */
154
+ declare function remoteTargetsOf(remote: RemoteBrowser): RemoteTarget[];
155
+ /** Whether a value is a remote service entry. */
156
+ declare function isRemoteBrowser(value: unknown): value is RemoteBrowser;
157
+ /** Whether `endpoint` has a scheme `protocol` can open. */
158
+ declare function hasSchemeFor(protocol: RemoteProtocol, endpoint: string): boolean;
159
+ /**
160
+ * Remove what identifies the connection from text surfaced to operators: the endpoint (it can carry
161
+ * a key in its path or query), its host and path, its query values, every header value and every
162
+ * value inside the lease (non-strings are stringified).
163
+ */
164
+ declare function scrubConnection(text: string, connection: RemoteConnection & {
165
+ lease?: unknown;
166
+ }): string;
167
+ export { RemoteBrowser, RemoteConnectContext, RemoteConnection, RemoteLeaseOutcome, RemoteLeasedConnection, RemoteOptions, RemoteProtocol, RemotePurpose, RemoteReleaseInfo, RemoteSupport, RemoteTarget, defineRemote, hasSchemeFor, isRemoteBrowser, remoteTargetsOf, scrubConnection };
168
+ //# sourceMappingURL=remote-browser.d.mts.map