@storyshelf/core 0.3.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. package/README.md +38 -31
  2. package/dist/adapter/capture-queue.d.mts +29 -1
  3. package/dist/adapter/capture-runner.d.mts +18 -2
  4. package/dist/adapter/capture-runner.mjs +12 -1
  5. package/dist/adapter/capture-runner.mjs.map +1 -0
  6. package/dist/adapter/database.d.mts +67 -17
  7. package/dist/adapter/database.mjs +22 -55
  8. package/dist/adapter/database.mjs.map +1 -1
  9. package/dist/adapter/email-sender.d.mts +27 -0
  10. package/dist/adapter/email-sender.mjs +4 -0
  11. package/dist/adapter/metadata.d.mts +21 -15
  12. package/dist/adapter/notifier.d.mts +7 -0
  13. package/dist/adapter/notifier.mjs +6 -0
  14. package/dist/adapter/setup.d.mts +61 -0
  15. package/dist/adapter/setup.mjs +29 -0
  16. package/dist/adapter/setup.mjs.map +1 -0
  17. package/dist/adapter/webhook-events.d.mts +29 -0
  18. package/dist/adapter/webhook-events.mjs +83 -0
  19. package/dist/adapter/webhook-events.mjs.map +1 -0
  20. package/dist/adapters/notifier/events.d.mts +26 -0
  21. package/dist/adapters/notifier/events.mjs +66 -0
  22. package/dist/adapters/notifier/events.mjs.map +1 -0
  23. package/dist/adapters/notifier/format.d.mts +14 -0
  24. package/dist/adapters/notifier/format.mjs +96 -0
  25. package/dist/adapters/notifier/format.mjs.map +1 -0
  26. package/dist/adapters/notifier/provider.d.mts +32 -0
  27. package/dist/adapters/notifier/types.d.mts +56 -0
  28. package/dist/adapters/setup-runner.d.mts +23 -0
  29. package/dist/adapters/setup-runner.mjs +149 -0
  30. package/dist/adapters/setup-runner.mjs.map +1 -0
  31. package/dist/adapters/validate.d.mts +30 -0
  32. package/dist/adapters/validate.mjs +313 -0
  33. package/dist/adapters/validate.mjs.map +1 -0
  34. package/dist/auth.d.mts +94 -0
  35. package/dist/auth.mjs +4 -0
  36. package/dist/brand-packs.d.mts +16 -0
  37. package/dist/brand-packs.mjs +130 -0
  38. package/dist/brand-packs.mjs.map +1 -0
  39. package/dist/capture/adapter.d.mts +51 -1
  40. package/dist/capture/adapter.mjs.map +1 -1
  41. package/dist/capture/affected.d.mts +16 -0
  42. package/dist/capture/affected.mjs +64 -0
  43. package/dist/capture/affected.mjs.map +1 -0
  44. package/dist/capture/diff-record.mjs +30 -0
  45. package/dist/capture/diff-record.mjs.map +1 -0
  46. package/dist/capture/dispatch.d.mts +36 -0
  47. package/dist/capture/dispatch.mjs +88 -31
  48. package/dist/capture/dispatch.mjs.map +1 -1
  49. package/dist/capture/guards.mjs +31 -0
  50. package/dist/capture/guards.mjs.map +1 -0
  51. package/dist/capture/orchestrator.d.mts +41 -6
  52. package/dist/capture/orchestrator.mjs +151 -28
  53. package/dist/capture/orchestrator.mjs.map +1 -1
  54. package/dist/capture/pipeline.d.mts +30 -16
  55. package/dist/capture/pipeline.mjs +143 -39
  56. package/dist/capture/pipeline.mjs.map +1 -1
  57. package/dist/capture/recovery.d.mts +21 -0
  58. package/dist/capture/recovery.mjs +83 -0
  59. package/dist/capture/recovery.mjs.map +1 -0
  60. package/dist/capture/rediff.d.mts +35 -0
  61. package/dist/capture/rediff.mjs +77 -0
  62. package/dist/capture/rediff.mjs.map +1 -0
  63. package/dist/capture/sizing.d.mts +58 -0
  64. package/dist/capture/sizing.mjs +119 -0
  65. package/dist/capture/sizing.mjs.map +1 -0
  66. package/dist/capture/skip-checks.mjs +3 -3
  67. package/dist/capture/skip-checks.mjs.map +1 -1
  68. package/dist/capture/statics.d.mts +38 -0
  69. package/dist/capture/statics.mjs +38 -4
  70. package/dist/capture/statics.mjs.map +1 -1
  71. package/dist/capture/status-fanout.mjs +7 -2
  72. package/dist/capture/status-fanout.mjs.map +1 -1
  73. package/dist/capture/storybook.d.mts +31 -2
  74. package/dist/capture/storybook.mjs +77 -2
  75. package/dist/capture/storybook.mjs.map +1 -1
  76. package/dist/capture.d.mts +10 -4
  77. package/dist/capture.mjs +7 -2
  78. package/dist/config.d.mts +121 -4
  79. package/dist/config.mjs +55 -8
  80. package/dist/config.mjs.map +1 -1
  81. package/dist/index.d.mts +5 -56
  82. package/dist/index.mjs +4 -284
  83. package/dist/logger.d.mts +26 -17
  84. package/dist/logger.mjs +10 -5
  85. package/dist/logger.mjs.map +1 -1
  86. package/dist/models/baseline-status.d.mts +29 -0
  87. package/dist/models/baseline-status.mjs +26 -0
  88. package/dist/models/baseline-status.mjs.map +1 -0
  89. package/dist/models/baseline.d.mts +33 -0
  90. package/dist/models/baseline.mjs +35 -13
  91. package/dist/models/baseline.mjs.map +1 -1
  92. package/dist/models/build.d.mts +87 -0
  93. package/dist/models/build.mjs +83 -35
  94. package/dist/models/build.mjs.map +1 -1
  95. package/dist/models/capture-attempt.d.mts +40 -0
  96. package/dist/models/capture-attempt.mjs +85 -0
  97. package/dist/models/capture-attempt.mjs.map +1 -0
  98. package/dist/models/capture-log.d.mts +21 -0
  99. package/dist/models/capture-log.mjs +44 -0
  100. package/dist/models/capture-log.mjs.map +1 -0
  101. package/dist/models/comment.d.mts +29 -0
  102. package/dist/models/comment.mjs +11 -8
  103. package/dist/models/comment.mjs.map +1 -1
  104. package/dist/models/content-ref.d.mts +21 -0
  105. package/dist/models/content-ref.mjs +49 -0
  106. package/dist/models/content-ref.mjs.map +1 -0
  107. package/dist/models/credentials.d.mts +36 -0
  108. package/dist/models/credentials.mjs +103 -0
  109. package/dist/models/credentials.mjs.map +1 -0
  110. package/dist/models/label.d.mts +58 -0
  111. package/dist/models/label.mjs +32 -27
  112. package/dist/models/label.mjs.map +1 -1
  113. package/dist/models/member.d.mts +34 -0
  114. package/dist/models/member.mjs +20 -11
  115. package/dist/models/member.mjs.map +1 -1
  116. package/dist/models/notification-channel.d.mts +52 -0
  117. package/dist/models/notification-channel.mjs +93 -0
  118. package/dist/models/notification-channel.mjs.map +1 -0
  119. package/dist/models/notification-subscription.d.mts +44 -0
  120. package/dist/models/notification-subscription.mjs +89 -0
  121. package/dist/models/notification-subscription.mjs.map +1 -0
  122. package/dist/models/project-group-mapping.d.mts +30 -0
  123. package/dist/models/project-group-mapping.mjs +46 -0
  124. package/dist/models/project-group-mapping.mjs.map +1 -0
  125. package/dist/models/project.d.mts +54 -0
  126. package/dist/models/project.mjs +15 -11
  127. package/dist/models/project.mjs.map +1 -1
  128. package/dist/models/snapshot.d.mts +58 -0
  129. package/dist/models/snapshot.mjs +13 -7
  130. package/dist/models/snapshot.mjs.map +1 -1
  131. package/dist/models/status-config.d.mts +38 -0
  132. package/dist/models/status-config.mjs +12 -11
  133. package/dist/models/status-config.mjs.map +1 -1
  134. package/dist/models/token.d.mts +44 -0
  135. package/dist/models/token.mjs +18 -15
  136. package/dist/models/token.mjs.map +1 -1
  137. package/dist/models/user.d.mts +42 -0
  138. package/dist/models/user.mjs +65 -0
  139. package/dist/models/user.mjs.map +1 -0
  140. package/dist/models/webhook.d.mts +50 -0
  141. package/dist/models/webhook.mjs +12 -10
  142. package/dist/models/webhook.mjs.map +1 -1
  143. package/dist/models.d.mts +22 -0
  144. package/dist/models.mjs +23 -0
  145. package/dist/paths.mjs +29 -0
  146. package/dist/paths.mjs.map +1 -1
  147. package/dist/retention.d.mts +45 -0
  148. package/dist/retention.mjs +145 -0
  149. package/dist/retention.mjs.map +1 -0
  150. package/dist/schema/baseline.d.mts +1 -0
  151. package/dist/schema/build.d.mts +8 -0
  152. package/dist/schema/capture-attempt.d.mts +38 -0
  153. package/dist/schema/comment.d.mts +1 -1
  154. package/dist/schema/content-ref.d.mts +13 -0
  155. package/dist/schema/member.d.mts +2 -0
  156. package/dist/schema/notification.d.mts +35 -0
  157. package/dist/schema/project-group-mapping.d.mts +15 -0
  158. package/dist/schema/project.d.mts +4 -0
  159. package/dist/schema/snapshot.d.mts +7 -0
  160. package/dist/schema/token.d.mts +2 -0
  161. package/dist/schema/user.d.mts +11 -1
  162. package/dist/schema.d.mts +9 -46
  163. package/dist/schema.mjs +1 -55
  164. package/dist/test-helpers/create-project.d.mts +15 -0
  165. package/dist/test-helpers/create-project.mjs +28 -0
  166. package/dist/test-helpers/create-project.mjs.map +1 -0
  167. package/dist/test-helpers/database-contract.d.mts +13 -0
  168. package/dist/test-helpers/database-contract.mjs +58 -0
  169. package/dist/test-helpers/database-contract.mjs.map +1 -0
  170. package/dist/test-helpers/fake-adapters.d.mts +14 -0
  171. package/dist/test-helpers/fake-adapters.mjs +20 -0
  172. package/dist/test-helpers/fake-adapters.mjs.map +1 -0
  173. package/dist/test-helpers/fake-database.d.mts +11 -0
  174. package/dist/test-helpers/fake-database.mjs +104 -0
  175. package/dist/test-helpers/fake-database.mjs.map +1 -0
  176. package/dist/test-helpers/fake-storage.d.mts +14 -0
  177. package/dist/test-helpers/fake-storage.mjs +49 -0
  178. package/dist/test-helpers/fake-storage.mjs.map +1 -0
  179. package/dist/test-helpers/fake-tables.mjs +276 -0
  180. package/dist/test-helpers/fake-tables.mjs.map +1 -0
  181. package/dist/test-helpers/git-contract.d.mts +11 -0
  182. package/dist/test-helpers/git-contract.mjs +34 -0
  183. package/dist/test-helpers/git-contract.mjs.map +1 -0
  184. package/dist/test-helpers/notifier-contract.d.mts +11 -0
  185. package/dist/test-helpers/notifier-contract.mjs +34 -0
  186. package/dist/test-helpers/notifier-contract.mjs.map +1 -0
  187. package/dist/test-helpers/queue-contract.d.mts +11 -0
  188. package/dist/test-helpers/queue-contract.mjs +64 -0
  189. package/dist/test-helpers/queue-contract.mjs.map +1 -0
  190. package/dist/test-helpers/runner-contract.d.mts +11 -0
  191. package/dist/test-helpers/runner-contract.mjs +32 -0
  192. package/dist/test-helpers/runner-contract.mjs.map +1 -0
  193. package/dist/test-helpers/sql-chunks.mjs +138 -0
  194. package/dist/test-helpers/sql-chunks.mjs.map +1 -0
  195. package/dist/test-helpers/storage-contract.d.mts +11 -0
  196. package/dist/test-helpers/storage-contract.mjs +87 -0
  197. package/dist/test-helpers/storage-contract.mjs.map +1 -0
  198. package/dist/test-helpers.d.mts +13 -0
  199. package/dist/test-helpers.mjs +14 -0
  200. package/dist/tracing.mjs +63 -0
  201. package/dist/tracing.mjs.map +1 -0
  202. package/dist/types.d.mts +38 -5
  203. package/dist/types.mjs +18 -5
  204. package/dist/types.mjs.map +1 -1
  205. package/dist/urls.d.mts +12 -1
  206. package/dist/urls.mjs +22 -3
  207. package/dist/urls.mjs.map +1 -1
  208. package/dist/utils/encrypt.d.mts +48 -0
  209. package/dist/utils/encrypt.mjs +67 -13
  210. package/dist/utils/encrypt.mjs.map +1 -1
  211. package/dist/utils/hash.d.mts +17 -0
  212. package/dist/utils/hash.mjs +8 -2
  213. package/dist/utils/hash.mjs.map +1 -1
  214. package/dist/utils/http.d.mts +58 -0
  215. package/dist/utils/http.mjs +147 -0
  216. package/dist/utils/http.mjs.map +1 -0
  217. package/dist/utils/mime.d.mts +9 -0
  218. package/dist/utils/mime.mjs +33 -0
  219. package/dist/utils/mime.mjs.map +1 -0
  220. package/dist/utils/path-security.d.mts +12 -0
  221. package/dist/utils/path-security.mjs +24 -0
  222. package/dist/utils/path-security.mjs.map +1 -0
  223. package/dist/utils/redact.d.mts +17 -0
  224. package/dist/utils/redact.mjs +42 -0
  225. package/dist/utils/redact.mjs.map +1 -0
  226. package/dist/utils/timing.d.mts +19 -0
  227. package/dist/utils/timing.mjs +46 -0
  228. package/dist/utils/timing.mjs.map +1 -0
  229. package/dist/utils/ulid.d.mts +10 -0
  230. package/dist/utils/ulid.mjs +8 -8
  231. package/dist/utils/ulid.mjs.map +1 -1
  232. package/dist/utils.d.mts +12 -0
  233. package/dist/utils.mjs +13 -0
  234. package/package.json +69 -28
  235. package/dist/adapter/auth.d.mts +0 -50
  236. package/dist/adapter/auth.mjs +0 -10
  237. package/dist/adapter/auth.mjs.map +0 -1
  238. package/dist/adapter/init.d.mts +0 -58
  239. package/dist/adapter/init.mjs +0 -93
  240. package/dist/adapter/init.mjs.map +0 -1
  241. package/dist/adapters/webhook-events.mjs +0 -55
  242. package/dist/adapters/webhook-events.mjs.map +0 -1
  243. package/dist/ddl.d.mts +0 -8
  244. package/dist/ddl.mjs +0 -158
  245. package/dist/ddl.mjs.map +0 -1
  246. package/dist/index.mjs.map +0 -1
  247. package/dist/middleware/auth-gate.mjs +0 -36
  248. package/dist/middleware/auth-gate.mjs.map +0 -1
  249. package/dist/middleware/csrf.mjs +0 -40
  250. package/dist/middleware/csrf.mjs.map +0 -1
  251. package/dist/middleware/rate-limit.mjs +0 -39
  252. package/dist/middleware/rate-limit.mjs.map +0 -1
  253. package/dist/middleware/request-log.mjs +0 -28
  254. package/dist/middleware/request-log.mjs.map +0 -1
  255. package/dist/middleware/store-scope.mjs +0 -29
  256. package/dist/middleware/store-scope.mjs.map +0 -1
  257. package/dist/pages/build-detail.mjs +0 -339
  258. package/dist/pages/build-detail.mjs.map +0 -1
  259. package/dist/pages/build-diff-comments.mjs +0 -113
  260. package/dist/pages/build-diff-comments.mjs.map +0 -1
  261. package/dist/pages/build-diff-header.mjs +0 -163
  262. package/dist/pages/build-diff-header.mjs.map +0 -1
  263. package/dist/pages/build-diff-nav.mjs +0 -66
  264. package/dist/pages/build-diff-nav.mjs.map +0 -1
  265. package/dist/pages/build-diff-viewer.mjs +0 -197
  266. package/dist/pages/build-diff-viewer.mjs.map +0 -1
  267. package/dist/pages/build-diff.mjs +0 -90
  268. package/dist/pages/build-diff.mjs.map +0 -1
  269. package/dist/pages/compute-jobs.mjs +0 -198
  270. package/dist/pages/compute-jobs.mjs.map +0 -1
  271. package/dist/pages/label-detail.mjs +0 -228
  272. package/dist/pages/label-detail.mjs.map +0 -1
  273. package/dist/pages/login.mjs +0 -78
  274. package/dist/pages/login.mjs.map +0 -1
  275. package/dist/pages/project-builds.mjs +0 -231
  276. package/dist/pages/project-builds.mjs.map +0 -1
  277. package/dist/pages/project-create.mjs +0 -169
  278. package/dist/pages/project-create.mjs.map +0 -1
  279. package/dist/pages/project-settings.mjs +0 -102
  280. package/dist/pages/project-settings.mjs.map +0 -1
  281. package/dist/pages/projects.mjs +0 -184
  282. package/dist/pages/projects.mjs.map +0 -1
  283. package/dist/pages/root.mjs +0 -94
  284. package/dist/pages/root.mjs.map +0 -1
  285. package/dist/pages/settings-general.mjs +0 -192
  286. package/dist/pages/settings-general.mjs.map +0 -1
  287. package/dist/pages/settings-labels.mjs +0 -150
  288. package/dist/pages/settings-labels.mjs.map +0 -1
  289. package/dist/pages/settings-members.mjs +0 -125
  290. package/dist/pages/settings-members.mjs.map +0 -1
  291. package/dist/pages/settings-status.mjs +0 -152
  292. package/dist/pages/settings-status.mjs.map +0 -1
  293. package/dist/pages/settings-tests.mjs +0 -149
  294. package/dist/pages/settings-tests.mjs.map +0 -1
  295. package/dist/pages/settings-tokens.mjs +0 -96
  296. package/dist/pages/settings-tokens.mjs.map +0 -1
  297. package/dist/pages/settings-webhooks.mjs +0 -150
  298. package/dist/pages/settings-webhooks.mjs.map +0 -1
  299. package/dist/pages/storybook.mjs +0 -96
  300. package/dist/pages/storybook.mjs.map +0 -1
  301. package/dist/retention/purge.mjs +0 -67
  302. package/dist/retention/purge.mjs.map +0 -1
  303. package/dist/routers/admin.mjs +0 -42
  304. package/dist/routers/admin.mjs.map +0 -1
  305. package/dist/routers/assets.mjs +0 -25
  306. package/dist/routers/assets.mjs.map +0 -1
  307. package/dist/routers/auth.mjs +0 -78
  308. package/dist/routers/auth.mjs.map +0 -1
  309. package/dist/routers/builds.handlers.mjs +0 -184
  310. package/dist/routers/builds.handlers.mjs.map +0 -1
  311. package/dist/routers/builds.mjs +0 -185
  312. package/dist/routers/builds.mjs.map +0 -1
  313. package/dist/routers/comments.mjs +0 -90
  314. package/dist/routers/comments.mjs.map +0 -1
  315. package/dist/routers/health.mjs +0 -137
  316. package/dist/routers/health.mjs.map +0 -1
  317. package/dist/routers/helpers.mjs +0 -82
  318. package/dist/routers/helpers.mjs.map +0 -1
  319. package/dist/routers/htmx.mjs +0 -20
  320. package/dist/routers/htmx.mjs.map +0 -1
  321. package/dist/routers/labels.mjs +0 -110
  322. package/dist/routers/labels.mjs.map +0 -1
  323. package/dist/routers/media.mjs +0 -55
  324. package/dist/routers/media.mjs.map +0 -1
  325. package/dist/routers/members.mjs +0 -102
  326. package/dist/routers/members.mjs.map +0 -1
  327. package/dist/routers/projects.mjs +0 -122
  328. package/dist/routers/projects.mjs.map +0 -1
  329. package/dist/routers/schemas.mjs +0 -224
  330. package/dist/routers/schemas.mjs.map +0 -1
  331. package/dist/routers/settings-general.mjs +0 -95
  332. package/dist/routers/settings-general.mjs.map +0 -1
  333. package/dist/routers/settings-labels.mjs +0 -49
  334. package/dist/routers/settings-labels.mjs.map +0 -1
  335. package/dist/routers/settings-members.mjs +0 -30
  336. package/dist/routers/settings-members.mjs.map +0 -1
  337. package/dist/routers/settings-status.mjs +0 -73
  338. package/dist/routers/settings-status.mjs.map +0 -1
  339. package/dist/routers/settings-tokens.mjs +0 -40
  340. package/dist/routers/settings-tokens.mjs.map +0 -1
  341. package/dist/routers/settings-webhooks.mjs +0 -63
  342. package/dist/routers/settings-webhooks.mjs.map +0 -1
  343. package/dist/routers/settings.handlers.mjs +0 -93
  344. package/dist/routers/settings.handlers.mjs.map +0 -1
  345. package/dist/routers/settings.mjs +0 -23
  346. package/dist/routers/settings.mjs.map +0 -1
  347. package/dist/routers/snapshots.mjs +0 -144
  348. package/dist/routers/snapshots.mjs.map +0 -1
  349. package/dist/routers/status-configs.mjs +0 -101
  350. package/dist/routers/status-configs.mjs.map +0 -1
  351. package/dist/routers/storybook.mjs +0 -120
  352. package/dist/routers/storybook.mjs.map +0 -1
  353. package/dist/routers/tokens.mjs +0 -81
  354. package/dist/routers/tokens.mjs.map +0 -1
  355. package/dist/routers/ui.mjs +0 -165
  356. package/dist/routers/ui.mjs.map +0 -1
  357. package/dist/routers/webhooks.mjs +0 -90
  358. package/dist/routers/webhooks.mjs.map +0 -1
  359. package/dist/schema/baseline.mjs +0 -22
  360. package/dist/schema/baseline.mjs.map +0 -1
  361. package/dist/schema/build.mjs +0 -29
  362. package/dist/schema/build.mjs.map +0 -1
  363. package/dist/schema/comment.mjs +0 -26
  364. package/dist/schema/comment.mjs.map +0 -1
  365. package/dist/schema/label.mjs +0 -30
  366. package/dist/schema/label.mjs.map +0 -1
  367. package/dist/schema/member.mjs +0 -19
  368. package/dist/schema/member.mjs.map +0 -1
  369. package/dist/schema/project.mjs +0 -25
  370. package/dist/schema/project.mjs.map +0 -1
  371. package/dist/schema/snapshot.mjs +0 -34
  372. package/dist/schema/snapshot.mjs.map +0 -1
  373. package/dist/schema/status-config.mjs +0 -20
  374. package/dist/schema/status-config.mjs.map +0 -1
  375. package/dist/schema/token.mjs +0 -19
  376. package/dist/schema/token.mjs.map +0 -1
  377. package/dist/schema/user.mjs +0 -19
  378. package/dist/schema/user.mjs.map +0 -1
  379. package/dist/schema/webhook.mjs +0 -20
  380. package/dist/schema/webhook.mjs.map +0 -1
  381. package/dist/schema.mjs.map +0 -1
  382. package/dist/store.mjs +0 -20
  383. package/dist/store.mjs.map +0 -1
  384. package/dist/ui/document.mjs +0 -348
  385. package/dist/ui/document.mjs.map +0 -1
  386. package/dist/ui/feedback.mjs +0 -24
  387. package/dist/ui/feedback.mjs.map +0 -1
  388. package/dist/ui/forms.mjs +0 -117
  389. package/dist/ui/forms.mjs.map +0 -1
  390. package/dist/ui/styles.mjs +0 -174
  391. package/dist/ui/styles.mjs.map +0 -1
  392. package/dist/ui/theme.mjs +0 -44
  393. package/dist/ui/theme.mjs.map +0 -1
@@ -1,16 +1,83 @@
1
1
  import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
- import { readFile } from "node:fs/promises";
4
+ import { STATS_FILENAME, loadDepGraph } from "@storyshelf/affected";
5
5
  import { join } from "node:path";
6
+ import { readFile } from "node:fs/promises";
6
7
  //#region src/capture/storybook.ts
8
+ /** Merge the `chromatic` and `storyshelf` parameter layers (`storyshelf` wins). */
7
9
  function mergeParameters(entry) {
8
10
  const merged = {
9
11
  ...entry.parameters?.chromatic,
10
12
  ...entry.parameters?.storyshelf
11
13
  };
14
+ if (entry.parameters?.viewport) merged.viewport = entry.parameters.viewport;
12
15
  return Object.keys(merged).length > 0 ? merged : void 0;
13
16
  }
17
+ /**
18
+ * The Storybook `MINIMAL_VIEWPORTS` snapshot used to resolve a story's
19
+ * `defaultViewport` name at capture time. Dimensions are the documented
20
+ * stable set; inline `parameters.viewport.viewports` always win over these.
21
+ */
22
+ const STORYBOOK_BUILTIN_VIEWPORTS = {
23
+ mobile1: {
24
+ name: "mobile1",
25
+ width: 320,
26
+ height: 568
27
+ },
28
+ mobile2: {
29
+ name: "mobile2",
30
+ width: 414,
31
+ height: 896
32
+ },
33
+ tablet: {
34
+ name: "tablet",
35
+ width: 834,
36
+ height: 1112
37
+ },
38
+ desktop: {
39
+ name: "desktop",
40
+ width: 1024,
41
+ height: 1280
42
+ }
43
+ };
44
+ /**
45
+ * Resolve the viewports a story should be captured at: the project's global
46
+ * list plus the story's Storybook default viewport (union), deduplicated by
47
+ * name. An unresolvable or duplicate default contributes nothing extra.
48
+ */
49
+ function resolveStoryViewports(entry, globalViewports) {
50
+ const resolved = storyViewport(entry);
51
+ if (resolved && !globalViewports.some((v) => v.name === resolved.name)) return [...globalViewports, resolved];
52
+ return [...globalViewports];
53
+ }
54
+ function storyViewport(entry) {
55
+ const config = entry.parameters?.viewport;
56
+ const name = config?.defaultViewport;
57
+ const inline = name ? config?.viewports?.[name] : void 0;
58
+ return name && inline ? viewportFromInline(name, inline) : name ? STORYBOOK_BUILTIN_VIEWPORTS[name] : void 0;
59
+ }
60
+ function viewportFromInline(defaultName, inline) {
61
+ const dims = viewportDims(inline.styles);
62
+ return dims ? {
63
+ name: inline.name ?? defaultName,
64
+ ...dims
65
+ } : void 0;
66
+ }
67
+ function viewportDims(styles) {
68
+ const width = pxOf(styles?.width);
69
+ const height = pxOf(styles?.height);
70
+ return width !== void 0 && height !== void 0 ? {
71
+ width,
72
+ height
73
+ } : void 0;
74
+ }
75
+ function pxOf(value) {
76
+ if (typeof value === "number") return Math.round(value);
77
+ const bare = typeof value === "string" ? value.trim() : "";
78
+ const match = /^(\d+(?:\.\d+)?)px$/u.exec(bare);
79
+ return match ? Number(match[1]) : void 0;
80
+ }
14
81
  /** Discovers stories from a built Storybook via its index file. */
15
82
  var StorybookAdapter = class {
16
83
  name = "storybook";
@@ -30,6 +97,14 @@ var StorybookAdapter = class {
30
97
  buildUrl(baseUrl, storyId) {
31
98
  return `${baseUrl}/iframe.html?id=${encodeURIComponent(storyId)}&viewMode=story`;
32
99
  }
100
+ /**
101
+ * Load the Vite stats dependency graph of an extracted build for affected
102
+ * capture. Resolves `null` when the build ships no usable stats, in which
103
+ * case the orchestrator renders every story.
104
+ */
105
+ async loadDependencyGraph(source) {
106
+ return await loadDepGraph(join(source, STATS_FILENAME));
107
+ }
33
108
  async readIndex(source) {
34
109
  const found = (await Promise.all(["stories.json", "index.json"].map(async (name) => {
35
110
  try {
@@ -44,6 +119,6 @@ var StorybookAdapter = class {
44
119
  }
45
120
  };
46
121
  //#endregion
47
- export { StorybookAdapter };
122
+ export { STORYBOOK_BUILTIN_VIEWPORTS, StorybookAdapter, mergeParameters, resolveStoryViewports };
48
123
 
49
124
  //# sourceMappingURL=storybook.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"storybook.mjs","names":[],"sources":["../../src/capture/storybook.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { StoryEntry, StoryParameters, StorySourceAdapter } from \"./adapter.ts\";\n\ninterface StorybookIndex {\n v: number;\n entries: Record<\n string,\n {\n id: string;\n name: string;\n title: string;\n importPath?: string;\n tags?: string[];\n type: string;\n subtype?: string;\n parameters?: { chromatic?: StoryParameters; storyshelf?: StoryParameters };\n }\n >;\n}\n\nfunction mergeParameters(entry: {\n parameters?: { chromatic?: StoryParameters; storyshelf?: StoryParameters };\n}): StoryParameters | undefined {\n const merged: StoryParameters = {\n ...entry.parameters?.chromatic,\n ...entry.parameters?.storyshelf,\n };\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/** Discovers stories from a built Storybook via its index file. */\nexport class StorybookAdapter implements StorySourceAdapter {\n readonly name = \"storybook\";\n readonly screenshotSelector = \"#storybook-root\";\n\n async discover(source: string): Promise<StoryEntry[]> {\n const index = await this.readIndex(source);\n return Object.values(index.entries)\n .filter((entry) => entry.type !== \"docs\" && entry.subtype !== \"test\")\n .map((entry) => ({\n id: entry.id,\n title: entry.title,\n name: entry.name,\n importPath: entry.importPath,\n tags: entry.tags,\n type: entry.type === \"docs\" ? \"docs\" : \"story\",\n parameters: mergeParameters(entry),\n }));\n }\n\n // eslint-disable-next-line class-methods-use-this\n buildUrl(baseUrl: string, storyId: string): string {\n return `${baseUrl}/iframe.html?id=${encodeURIComponent(storyId)}&viewMode=story`;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private async readIndex(source: string): Promise<StorybookIndex> {\n const candidates: string[] = [\"stories.json\", \"index.json\"];\n const results = await Promise.all(\n candidates.map(async (name) => {\n try {\n const raw = await readFile(join(source, name), \"utf8\");\n return JSON.parse(raw) as StorybookIndex;\n } catch {\n return null;\n }\n }),\n );\n const found = results.find((index) => index !== null);\n if (found) {\n return found;\n }\n throw new Error(`No Storybook index found in ${source}`);\n }\n}\n"],"mappings":";;;;;;AAqBA,SAAS,gBAAgB,OAEO;CAC9B,MAAM,SAA0B;EAC9B,GAAG,MAAM,YAAY;EACrB,GAAG,MAAM,YAAY;CACvB;CACA,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA;AACnD;;AAGA,IAAa,mBAAb,MAA4D;CAC1D,OAAgB;CAChB,qBAA8B;CAE9B,MAAM,SAAS,QAAuC;EACpD,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM;EACzC,OAAO,OAAO,OAAO,MAAM,OAAO,CAAC,CAChC,QAAQ,UAAU,MAAM,SAAS,UAAU,MAAM,YAAY,MAAM,CAAC,CACpE,KAAK,WAAW;GACf,IAAI,MAAM;GACV,OAAO,MAAM;GACb,MAAM,MAAM;GACZ,YAAY,MAAM;GAClB,MAAM,MAAM;GACZ,MAAM,MAAM,SAAS,SAAS,SAAS;GACvC,YAAY,gBAAgB,KAAK;EACnC,EAAE;CACN;CAGA,SAAS,SAAiB,SAAyB;EACjD,OAAO,GAAG,QAAQ,kBAAkB,mBAAmB,OAAO,EAAE;CAClE;CAGA,MAAc,UAAU,QAAyC;EAY/D,MAAM,SAAQ,MAVQ,QAAQ,IAC5B,CAF4B,gBAAgB,YAEnC,CAAC,CAAC,IAAI,OAAO,SAAS;GAC7B,IAAI;IACF,MAAM,MAAM,MAAM,SAAS,KAAK,QAAQ,IAAI,GAAG,MAAM;IACrD,OAAO,KAAK,MAAM,GAAG;GACvB,QAAQ;IACN,OAAO;GACT;EACF,CAAC,CACH,EAAA,CACsB,MAAM,UAAU,UAAU,IAAI;EACpD,IAAI,OACF,OAAO;EAET,MAAM,IAAI,MAAM,+BAA+B,QAAQ;CACzD;AACF"}
1
+ {"version":3,"file":"storybook.mjs","names":[],"sources":["../../src/capture/storybook.ts"],"sourcesContent":["import { loadDepGraph, STATS_FILENAME, type DepGraph } from \"@storyshelf/affected\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type {\n StoryEntry,\n StoryParameters,\n StorySourceAdapter,\n StoryViewportConfig,\n StoryViewportDefinition,\n Viewport,\n} from \"./adapter.ts\";\n\ninterface StorybookIndex {\n v: number;\n entries: Record<\n string,\n {\n id: string;\n name: string;\n title: string;\n importPath?: string;\n tags?: string[];\n type: string;\n subtype?: string;\n parameters?: StorybookParameters;\n }\n >;\n}\n\n/** Story parameters as serialized by the Storybook index. */\ninterface StorybookParameters {\n chromatic?: StoryParameters;\n storyshelf?: StoryParameters;\n viewport?: StoryViewportConfig;\n}\n\n/** Merge the `chromatic` and `storyshelf` parameter layers (`storyshelf` wins). */\nexport function mergeParameters(entry: {\n parameters?: StorybookParameters;\n}): StoryParameters | undefined {\n const merged: StoryParameters = {\n ...entry.parameters?.chromatic,\n ...entry.parameters?.storyshelf,\n };\n if (entry.parameters?.viewport) merged.viewport = entry.parameters.viewport;\n return Object.keys(merged).length > 0 ? merged : undefined;\n}\n\n/**\n * The Storybook `MINIMAL_VIEWPORTS` snapshot used to resolve a story's\n * `defaultViewport` name at capture time. Dimensions are the documented\n * stable set; inline `parameters.viewport.viewports` always win over these.\n */\nexport const STORYBOOK_BUILTIN_VIEWPORTS: Readonly<Record<string, Viewport>> = {\n mobile1: { name: \"mobile1\", width: 320, height: 568 },\n mobile2: { name: \"mobile2\", width: 414, height: 896 },\n tablet: { name: \"tablet\", width: 834, height: 1112 },\n desktop: { name: \"desktop\", width: 1024, height: 1280 },\n};\n\n/**\n * Resolve the viewports a story should be captured at: the project's global\n * list plus the story's Storybook default viewport (union), deduplicated by\n * name. An unresolvable or duplicate default contributes nothing extra.\n */\nexport function resolveStoryViewports(\n entry: Pick<StoryEntry, \"parameters\">,\n globalViewports: Viewport[],\n): Viewport[] {\n const resolved = storyViewport(entry);\n if (resolved && !globalViewports.some((v) => v.name === resolved.name)) {\n return [...globalViewports, resolved];\n }\n return [...globalViewports];\n}\n\nfunction storyViewport(entry: Pick<StoryEntry, \"parameters\">): Viewport | undefined {\n const config = entry.parameters?.viewport;\n const name = config?.defaultViewport;\n const inline = name ? config?.viewports?.[name] : undefined;\n const resolved =\n name && inline\n ? viewportFromInline(name, inline)\n : name\n ? STORYBOOK_BUILTIN_VIEWPORTS[name]\n : undefined;\n return resolved;\n}\n\nfunction viewportFromInline(\n defaultName: string,\n inline: StoryViewportDefinition,\n): Viewport | undefined {\n const dims = viewportDims(inline.styles);\n return dims ? { name: inline.name ?? defaultName, ...dims } : undefined;\n}\n\nfunction viewportDims(\n styles: StoryViewportDefinition[\"styles\"] | undefined,\n): { width: number; height: number } | undefined {\n const width = pxOf(styles?.width);\n const height = pxOf(styles?.height);\n return width !== undefined && height !== undefined ? { width, height } : undefined;\n}\n\nfunction pxOf(value: string | number | undefined): number | undefined {\n if (typeof value === \"number\") return Math.round(value);\n const bare = typeof value === \"string\" ? value.trim() : \"\";\n const match = /^(\\d+(?:\\.\\d+)?)px$/u.exec(bare);\n return match ? Number(match[1]) : undefined;\n}\n\n/** Discovers stories from a built Storybook via its index file. */\nexport class StorybookAdapter implements StorySourceAdapter {\n readonly name = \"storybook\";\n readonly screenshotSelector = \"#storybook-root\";\n\n async discover(source: string): Promise<StoryEntry[]> {\n const index = await this.readIndex(source);\n return Object.values(index.entries)\n .filter((entry) => entry.type !== \"docs\" && entry.subtype !== \"test\")\n .map((entry) => ({\n id: entry.id,\n title: entry.title,\n name: entry.name,\n importPath: entry.importPath,\n tags: entry.tags,\n type: entry.type === \"docs\" ? \"docs\" : \"story\",\n parameters: mergeParameters(entry),\n }));\n }\n\n // eslint-disable-next-line class-methods-use-this\n buildUrl(baseUrl: string, storyId: string): string {\n return `${baseUrl}/iframe.html?id=${encodeURIComponent(storyId)}&viewMode=story`;\n }\n\n /**\n * Load the Vite stats dependency graph of an extracted build for affected\n * capture. Resolves `null` when the build ships no usable stats, in which\n * case the orchestrator renders every story.\n */\n // eslint-disable-next-line class-methods-use-this\n async loadDependencyGraph(source: string): Promise<DepGraph | null> {\n return await loadDepGraph(join(source, STATS_FILENAME));\n }\n\n // eslint-disable-next-line class-methods-use-this\n private async readIndex(source: string): Promise<StorybookIndex> {\n const candidates: string[] = [\"stories.json\", \"index.json\"];\n const results = await Promise.all(\n candidates.map(async (name) => {\n try {\n const raw = await readFile(join(source, name), \"utf8\");\n return JSON.parse(raw) as StorybookIndex;\n } catch {\n return null;\n }\n }),\n );\n const found = results.find((index) => index !== null);\n if (found) {\n return found;\n }\n throw new Error(`No Storybook index found in ${source}`);\n }\n}\n"],"mappings":";;;;;;;;AAqCA,SAAgB,gBAAgB,OAEA;CAC9B,MAAM,SAA0B;EAC9B,GAAG,MAAM,YAAY;EACrB,GAAG,MAAM,YAAY;CACvB;CACA,IAAI,MAAM,YAAY,UAAU,OAAO,WAAW,MAAM,WAAW;CACnE,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,SAAS,KAAA;AACnD;;;;;;AAOA,MAAa,8BAAkE;CAC7E,SAAS;EAAE,MAAM;EAAW,OAAO;EAAK,QAAQ;CAAI;CACpD,SAAS;EAAE,MAAM;EAAW,OAAO;EAAK,QAAQ;CAAI;CACpD,QAAQ;EAAE,MAAM;EAAU,OAAO;EAAK,QAAQ;CAAK;CACnD,SAAS;EAAE,MAAM;EAAW,OAAO;EAAM,QAAQ;CAAK;AACxD;;;;;;AAOA,SAAgB,sBACd,OACA,iBACY;CACZ,MAAM,WAAW,cAAc,KAAK;CACpC,IAAI,YAAY,CAAC,gBAAgB,MAAM,MAAM,EAAE,SAAS,SAAS,IAAI,GACnE,OAAO,CAAC,GAAG,iBAAiB,QAAQ;CAEtC,OAAO,CAAC,GAAG,eAAe;AAC5B;AAEA,SAAS,cAAc,OAA6D;CAClF,MAAM,SAAS,MAAM,YAAY;CACjC,MAAM,OAAO,QAAQ;CACrB,MAAM,SAAS,OAAO,QAAQ,YAAY,QAAQ,KAAA;CAOlD,OALE,QAAQ,SACJ,mBAAmB,MAAM,MAAM,IAC/B,OACE,4BAA4B,QAC5B,KAAA;AAEV;AAEA,SAAS,mBACP,aACA,QACsB;CACtB,MAAM,OAAO,aAAa,OAAO,MAAM;CACvC,OAAO,OAAO;EAAE,MAAM,OAAO,QAAQ;EAAa,GAAG;CAAK,IAAI,KAAA;AAChE;AAEA,SAAS,aACP,QAC+C;CAC/C,MAAM,QAAQ,KAAK,QAAQ,KAAK;CAChC,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,OAAO,UAAU,KAAA,KAAa,WAAW,KAAA,IAAY;EAAE;EAAO;CAAO,IAAI,KAAA;AAC3E;AAEA,SAAS,KAAK,OAAwD;CACpE,IAAI,OAAO,UAAU,UAAU,OAAO,KAAK,MAAM,KAAK;CACtD,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI;CACxD,MAAM,QAAQ,uBAAuB,KAAK,IAAI;CAC9C,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,KAAA;AACpC;;AAGA,IAAa,mBAAb,MAA4D;CAC1D,OAAgB;CAChB,qBAA8B;CAE9B,MAAM,SAAS,QAAuC;EACpD,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM;EACzC,OAAO,OAAO,OAAO,MAAM,OAAO,CAAC,CAChC,QAAQ,UAAU,MAAM,SAAS,UAAU,MAAM,YAAY,MAAM,CAAC,CACpE,KAAK,WAAW;GACf,IAAI,MAAM;GACV,OAAO,MAAM;GACb,MAAM,MAAM;GACZ,YAAY,MAAM;GAClB,MAAM,MAAM;GACZ,MAAM,MAAM,SAAS,SAAS,SAAS;GACvC,YAAY,gBAAgB,KAAK;EACnC,EAAE;CACN;CAGA,SAAS,SAAiB,SAAyB;EACjD,OAAO,GAAG,QAAQ,kBAAkB,mBAAmB,OAAO,EAAE;CAClE;;;;;;CAQA,MAAM,oBAAoB,QAA0C;EAClE,OAAO,MAAM,aAAa,KAAK,QAAQ,cAAc,CAAC;CACxD;CAGA,MAAc,UAAU,QAAyC;EAY/D,MAAM,SAAQ,MAVQ,QAAQ,IAC5B,CAF4B,gBAAgB,YAEnC,CAAC,CAAC,IAAI,OAAO,SAAS;GAC7B,IAAI;IACF,MAAM,MAAM,MAAM,SAAS,KAAK,QAAQ,IAAI,GAAG,MAAM;IACrD,OAAO,KAAK,MAAM,GAAG;GACvB,QAAQ;IACN,OAAO;GACT;EACF,CAAC,CACH,EAAA,CACsB,MAAM,UAAU,UAAU,IAAI;EACpD,IAAI,OACF,OAAO;EAET,MAAM,IAAI,MAAM,+BAA+B,QAAQ;CACzD;AACF"}
@@ -1,8 +1,14 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- import { DEFAULT_VIEWPORTS, StoryEntry, StoryParameters, StorySourceAdapter, Viewport, isDisabledStory, isFlakyStory } from "./capture/adapter.mjs";
4
- import { CaptureJobOptions, executeCaptureJob } from "./capture/orchestrator.mjs";
3
+ import { DEFAULT_VIEWPORTS, StoryEntry, StoryParameters, StorySourceAdapter, StoryViewportConfig, StoryViewportDefinition, Viewport, isDisabledStory, isFlakyStory } from "./capture/adapter.mjs";
4
+ import { PollableCaptureQueue, PollableJob } from "./adapter/capture-queue.mjs";
5
5
  import { CaptureContext, persistCapture } from "./capture/pipeline.mjs";
6
+ import { CaptureAttemptRef, CaptureJobInput, CaptureJobOptions, executeCaptureJob } from "./capture/orchestrator.mjs";
7
+ import { REDIFFABLE_BUILD_STATUSES, RediffDeps, RediffResult, rediffBuild } from "./capture/rediff.mjs";
8
+ import { CaptureDispatchJob, DispatchDeps, createDispatchJob } from "./capture/dispatch.mjs";
9
+ import { INTERRUPTED_ERROR, RecoveryDeps, RecoveryResult, recoverStuckCaptures } from "./capture/recovery.mjs";
6
10
  import { InMemoryCaptureQueue, InMemoryCaptureQueueOptions } from "./capture/queue.mjs";
7
- import { StorybookAdapter } from "./capture/storybook.mjs";
8
- export { type CaptureContext, type CaptureJobOptions, DEFAULT_VIEWPORTS, InMemoryCaptureQueue, type InMemoryCaptureQueueOptions, type StoryEntry, type StoryParameters, type StorySourceAdapter, StorybookAdapter, type Viewport, executeCaptureJob, isDisabledStory, isFlakyStory, persistCapture };
11
+ import { STORYBOOK_BUILTIN_VIEWPORTS, StorybookAdapter, mergeParameters, resolveStoryViewports } from "./capture/storybook.mjs";
12
+ import { extractStorybookToScratch, persistStorybookStatics } from "./capture/statics.mjs";
13
+ import { BoundingBox, SIZING_DEFAULTS, ScreenshotPlan, SizingOptions, getScreenshotPlan, resolveViewports } from "./capture/sizing.mjs";
14
+ export { type BoundingBox, type CaptureAttemptRef, type CaptureContext, type CaptureDispatchJob, type CaptureJobInput, type CaptureJobOptions, DEFAULT_VIEWPORTS, type DispatchDeps, INTERRUPTED_ERROR, InMemoryCaptureQueue, type InMemoryCaptureQueueOptions, type PollableCaptureQueue, type PollableJob, REDIFFABLE_BUILD_STATUSES, type RecoveryDeps, type RecoveryResult, type RediffDeps, type RediffResult, SIZING_DEFAULTS, STORYBOOK_BUILTIN_VIEWPORTS, type ScreenshotPlan, type SizingOptions, type StoryEntry, type StoryParameters, type StorySourceAdapter, type StoryViewportConfig, type StoryViewportDefinition, StorybookAdapter, type Viewport, createDispatchJob, executeCaptureJob, extractStorybookToScratch, getScreenshotPlan, isDisabledStory, isFlakyStory, mergeParameters, persistCapture, persistStorybookStatics, recoverStuckCaptures, rediffBuild, resolveViewports as resolveCaptureViewports, resolveStoryViewports };
package/dist/capture.mjs CHANGED
@@ -2,8 +2,13 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { DEFAULT_VIEWPORTS, isDisabledStory, isFlakyStory } from "./capture/adapter.mjs";
5
+ import { STORYBOOK_BUILTIN_VIEWPORTS, StorybookAdapter, mergeParameters, resolveStoryViewports } from "./capture/storybook.mjs";
6
+ import { SIZING_DEFAULTS, getScreenshotPlan, resolveViewports } from "./capture/sizing.mjs";
5
7
  import { persistCapture } from "./capture/pipeline.mjs";
6
- import { StorybookAdapter } from "./capture/storybook.mjs";
8
+ import { extractStorybookToScratch, persistStorybookStatics } from "./capture/statics.mjs";
7
9
  import { executeCaptureJob } from "./capture/orchestrator.mjs";
10
+ import { REDIFFABLE_BUILD_STATUSES, rediffBuild } from "./capture/rediff.mjs";
11
+ import { INTERRUPTED_ERROR, recoverStuckCaptures } from "./capture/recovery.mjs";
8
12
  import { InMemoryCaptureQueue } from "./capture/queue.mjs";
9
- export { DEFAULT_VIEWPORTS, InMemoryCaptureQueue, StorybookAdapter, executeCaptureJob, isDisabledStory, isFlakyStory, persistCapture };
13
+ import { createDispatchJob } from "./capture/dispatch.mjs";
14
+ export { DEFAULT_VIEWPORTS, INTERRUPTED_ERROR, InMemoryCaptureQueue, REDIFFABLE_BUILD_STATUSES, SIZING_DEFAULTS, STORYBOOK_BUILTIN_VIEWPORTS, StorybookAdapter, createDispatchJob, executeCaptureJob, extractStorybookToScratch, getScreenshotPlan, isDisabledStory, isFlakyStory, mergeParameters, persistCapture, persistStorybookStatics, recoverStuckCaptures, rediffBuild, resolveViewports as resolveCaptureViewports, resolveStoryViewports };
package/dist/config.d.mts CHANGED
@@ -1,41 +1,83 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- import { CaptureQueue } from "./adapter/capture-queue.mjs";
4
3
  import { CaptureRunner } from "./adapter/capture-runner.mjs";
5
4
  import { DatabaseAdapter } from "./adapter/database.mjs";
5
+ import { EmailSender } from "./adapter/email-sender.mjs";
6
6
  import { GitHostProvider } from "./adapter/git-host.mjs";
7
+ import { NotifierProvider } from "./adapters/notifier/provider.mjs";
7
8
  import { StorageAdapter } from "./adapter/storage.mjs";
9
+ import { Auth } from "./auth.mjs";
8
10
  import { AdapterCategory } from "./adapter/metadata.mjs";
9
- import { AuthAdapter } from "./adapter/auth.mjs";
11
+ import { CaptureQueue } from "./adapter/capture-queue.mjs";
10
12
  import { z } from "zod";
11
13
  import { Logger } from "pino";
12
14
  //#region src/config.d.ts
13
15
  /** Brand color theme for the server-rendered UI. */
14
16
  interface BrandTheme {
15
17
  accent: string;
18
+ accentContrast?: string;
19
+ ring?: string;
16
20
  surface: {
17
21
  base: string;
18
22
  card: string;
23
+ muted?: string;
24
+ subtle?: string;
19
25
  };
20
26
  text: {
21
27
  primary: string;
22
28
  secondary: string;
29
+ muted?: string;
23
30
  };
24
31
  border: string;
32
+ borderSubtle?: string;
25
33
  status: {
26
34
  approved: string;
27
35
  new: string;
28
36
  rejected: string;
29
37
  };
38
+ sidebarBg?: string;
39
+ topbarBg?: string;
40
+ radius?: string;
41
+ radiusSm?: string;
42
+ shadow?: string;
43
+ }
44
+ /** Text overrides for the auth (login) UI. */
45
+ interface AuthUiConfig {
46
+ /** Page title, default "Sign in". */
47
+ title?: string;
48
+ /** Optional subtitle under the title. */
49
+ subtitle?: string;
50
+ /** Password field label, default "Password". */
51
+ passwordLabel?: string;
52
+ /** Password field placeholder. */
53
+ passwordPlaceholder?: string;
54
+ /** Submit button label, default "Sign in". */
55
+ submitLabel?: string;
56
+ /**
57
+ * Template for SSO buttons, default "Sign in with {label}".
58
+ * Must contain "{label}" which is replaced with the provider label.
59
+ */
60
+ ssoLabelTemplate?: string;
61
+ /** Help text shown under the form. */
62
+ helpText?: string;
63
+ /** Footer text shown at the bottom of the card. */
64
+ footerText?: string;
30
65
  }
31
66
  /** Branding overrides for the server-rendered UI. */
32
67
  interface UIConfig {
33
68
  name?: string;
34
69
  logo?: string;
70
+ /**
71
+ * @deprecated Ignored. The favicon is the product's own mark, served by the
72
+ * app itself; set `logo` to rebrand the sidebar instead.
73
+ */
35
74
  favicon?: string;
36
75
  lightTheme?: BrandTheme;
37
76
  darkTheme?: BrandTheme;
77
+ auth?: AuthUiConfig;
38
78
  }
79
+ /** Default cap for a single Storybook zip upload (1 GiB). */
80
+ declare const DEFAULT_MAX_UPLOAD_BYTES: number;
39
81
  /** A viewport in which stories are captured. */
40
82
  interface ShelfViewport {
41
83
  name: string;
@@ -50,14 +92,54 @@ interface AdapterSnapshot {
50
92
  kind: string;
51
93
  category: AdapterCategory;
52
94
  }
95
+ /** Site-wide notification defaults (brand + sender identity for admin alerts). */
96
+ interface NotificationsConfig {
97
+ fromEmail?: string;
98
+ fromName?: string;
99
+ footerText?: string;
100
+ slackUsername?: string;
101
+ }
53
102
  /** Shelf-level configuration (validated by {@link shelfConfigSchema}). */
54
103
  interface ShelfConfig {
55
104
  secret?: string;
105
+ /**
106
+ * The secret `secret` replaced. Used only to decrypt stored credentials
107
+ * (webhook, git-token, and notification secrets) written before a rotation;
108
+ * new writes always use `secret`. Remove once credentials are re-encrypted.
109
+ */
110
+ previousSecret?: string;
111
+ /**
112
+ * Re-encrypt credentials still under `previousSecret` at boot. Default false:
113
+ * site admins can run it from the System page instead. No effect without
114
+ * `previousSecret`.
115
+ */
116
+ migrateCredentialsOnBoot?: boolean;
117
+ /**
118
+ * Bootstrap site-admin bearer token (`STORYSHELF_ADMIN_TOKEN`/`ADMIN_TOKEN`).
119
+ * Grants site-admin API access when no admin user exists yet; never
120
+ * mint sessions from it. Distinct from `secret` (session signing).
121
+ */
122
+ adminToken?: string;
56
123
  publishedBaseDomain?: string;
124
+ /**
125
+ * Public base URL of this deployment (e.g. `https://shelf.example.com`).
126
+ * Used as the issuer in the `/.well-known/openid-configuration` relying-party
127
+ * helper document; falls back to the request origin when unset.
128
+ */
129
+ publicBaseUrl?: string;
57
130
  captureConcurrency?: number;
58
131
  scratchDir?: string;
59
132
  purgeTtlDays?: number;
133
+ /** Branch baseline TTL, days; null disables branch GC (default 30). */
134
+ branchTtlDays?: number | null;
135
+ /** Branch GC interval, ms; daily sweep via interval clock (default 86_400_000). */
136
+ branchGcIntervalMs?: number;
60
137
  maxUploadBytes?: number;
138
+ /**
139
+ * Emit `Server-Timing` response headers (total + db/storage roll-ups).
140
+ * Opt-in, off by default — some deployments prefer no timing headers.
141
+ */
142
+ serverTiming?: boolean;
61
143
  /**
62
144
  * Max zip size (bytes) eligible for inline statics extraction at upload.
63
145
  * Unset (or 0) disables inline extraction — statics land via capture.
@@ -65,19 +147,54 @@ interface ShelfConfig {
65
147
  maxInlineUnzipSize?: number;
66
148
  viewports?: ShelfViewport[];
67
149
  adapters?: Record<string, AdapterSnapshot>;
150
+ notifications?: NotificationsConfig;
68
151
  }
152
+ /** Zod schema validating the shelf-level configuration. */
153
+ declare const shelfConfigSchema: z.ZodType<ShelfConfig>;
154
+ /** Zod schema validating the UI branding configuration. */
155
+ declare const uiConfigSchema: z.ZodType<UIConfig>;
156
+ /**
157
+ * Parse and validate a raw shelf-level configuration object.
158
+ *
159
+ * @param config - Unvalidated configuration record.
160
+ * @returns The validated shelf configuration.
161
+ */
162
+ declare function validateConfig(config: Record<string, unknown>): ShelfConfig;
163
+ /**
164
+ * Parse and validate a raw UI branding configuration object.
165
+ *
166
+ * @param config - Unvalidated UI configuration record.
167
+ * @returns The validated UI configuration.
168
+ */
169
+ declare function validateUiConfig(config: Record<string, unknown>): UIConfig;
69
170
  /** Adapter and configuration options for creating the shelf router. */
70
171
  interface ShelfOptions {
71
172
  database: DatabaseAdapter;
72
173
  storage: StorageAdapter;
73
174
  captureRunner?: CaptureRunner;
74
175
  captureQueue?: CaptureQueue;
75
- auth?: AuthAdapter;
176
+ auth?: Auth;
76
177
  gitHosts?: GitHostProvider[];
178
+ notifiers?: NotifierProvider[];
179
+ emailSender?: EmailSender;
77
180
  logger?: Logger;
78
181
  ui?: UIConfig;
79
182
  config?: ShelfConfig;
183
+ /**
184
+ * Externally-managed observability SDK handle (e.g. from
185
+ * `initObservabilityFromEnv`). Structural — core never imports the
186
+ * observability package. Flushed on `app.lifecycle.teardown()`.
187
+ */
188
+ observability?: ObservabilityHandle;
189
+ }
190
+ /**
191
+ * Shutdown hook for an externally-managed observability SDK.
192
+ * Structural so core stays dependency-free.
193
+ */
194
+ interface ObservabilityHandle {
195
+ /** Flush exporters and release SDK resources. Must be idempotent. */
196
+ shutdown(): Promise<void>;
80
197
  }
81
198
  //#endregion
82
- export { AdapterSnapshot, BrandTheme, ShelfConfig, ShelfOptions, ShelfViewport, UIConfig };
199
+ export { AdapterSnapshot, AuthUiConfig, BrandTheme, DEFAULT_MAX_UPLOAD_BYTES, NotificationsConfig, ObservabilityHandle, ShelfConfig, ShelfOptions, ShelfViewport, UIConfig, shelfConfigSchema, uiConfigSchema, validateConfig, validateUiConfig };
83
200
  //# sourceMappingURL=config.d.mts.map
package/dist/config.mjs CHANGED
@@ -12,20 +12,31 @@ const viewportSchema = z.object({
12
12
  });
13
13
  const brandThemeSchema = z.object({
14
14
  accent: z.string(),
15
+ accentContrast: z.string().optional(),
16
+ ring: z.string().optional(),
15
17
  surface: z.object({
16
18
  base: z.string(),
17
- card: z.string()
19
+ card: z.string(),
20
+ muted: z.string().optional(),
21
+ subtle: z.string().optional()
18
22
  }),
19
23
  text: z.object({
20
24
  primary: z.string(),
21
- secondary: z.string()
25
+ secondary: z.string(),
26
+ muted: z.string().optional()
22
27
  }),
23
28
  border: z.string(),
29
+ borderSubtle: z.string().optional(),
24
30
  status: z.object({
25
31
  approved: z.string(),
26
32
  new: z.string(),
27
33
  rejected: z.string()
28
- })
34
+ }),
35
+ sidebarBg: z.string().optional(),
36
+ topbarBg: z.string().optional(),
37
+ radius: z.string().optional(),
38
+ radiusSm: z.string().optional(),
39
+ shadow: z.string().optional()
29
40
  });
30
41
  const adapterSnapshotSchema = z.object({
31
42
  name: z.string(),
@@ -35,31 +46,67 @@ const adapterSnapshotSchema = z.object({
35
46
  category: z.enum([
36
47
  "database",
37
48
  "storage",
38
- "auth",
39
49
  "capture-runner",
40
50
  "capture-queue",
41
- "git-host"
51
+ "git-host",
52
+ "notifier"
42
53
  ])
43
54
  });
55
+ const authUiConfigSchema = z.object({
56
+ title: z.string().min(1).optional(),
57
+ subtitle: z.string().optional(),
58
+ passwordLabel: z.string().min(1).optional(),
59
+ passwordPlaceholder: z.string().optional(),
60
+ submitLabel: z.string().min(1).optional(),
61
+ ssoLabelTemplate: z.string().min(1).optional(),
62
+ helpText: z.string().optional(),
63
+ footerText: z.string().optional()
64
+ });
65
+ const notificationsConfigSchema = z.object({
66
+ fromEmail: z.string().min(1).optional(),
67
+ fromName: z.string().min(1).optional(),
68
+ footerText: z.string().min(1).optional(),
69
+ slackUsername: z.string().min(1).optional()
70
+ });
44
71
  /** Zod schema validating the shelf-level configuration. */
45
72
  const shelfConfigSchema = z.object({
46
73
  secret: z.string().min(1).optional(),
74
+ previousSecret: z.string().min(1).optional(),
75
+ migrateCredentialsOnBoot: z.boolean().optional(),
76
+ adminToken: z.string().min(1).optional(),
47
77
  publishedBaseDomain: z.string().optional(),
78
+ publicBaseUrl: z.string().url().optional(),
48
79
  captureConcurrency: z.number().int().positive().optional(),
49
80
  scratchDir: z.string().optional(),
50
81
  purgeTtlDays: z.number().int().positive().optional(),
82
+ branchTtlDays: z.number().int().positive().nullable().optional(),
83
+ branchGcIntervalMs: z.number().int().positive().optional(),
51
84
  maxUploadBytes: z.number().int().positive().optional(),
85
+ serverTiming: z.boolean().optional(),
52
86
  maxInlineUnzipSize: z.number().int().positive().optional(),
53
87
  viewports: z.array(viewportSchema).min(1, "at least one viewport required").optional(),
54
- adapters: z.record(z.string(), adapterSnapshotSchema).optional()
55
- }).strict();
88
+ adapters: z.record(z.string(), adapterSnapshotSchema).optional(),
89
+ notifications: notificationsConfigSchema.optional()
90
+ }).strict().superRefine((config, ctx) => {
91
+ if (config.previousSecret !== void 0 && config.secret === void 0) ctx.addIssue({
92
+ code: "custom",
93
+ path: ["previousSecret"],
94
+ message: "previousSecret requires secret"
95
+ });
96
+ if (config.previousSecret !== void 0 && config.previousSecret === config.secret) ctx.addIssue({
97
+ code: "custom",
98
+ path: ["previousSecret"],
99
+ message: "previousSecret must differ from secret"
100
+ });
101
+ });
56
102
  /** Zod schema validating the UI branding configuration. */
57
103
  const uiConfigSchema = z.object({
58
104
  name: z.string().optional(),
59
105
  logo: z.string().url().optional(),
60
106
  favicon: z.string().url().optional(),
61
107
  lightTheme: brandThemeSchema.optional(),
62
- darkTheme: brandThemeSchema.optional()
108
+ darkTheme: brandThemeSchema.optional(),
109
+ auth: authUiConfigSchema.optional()
63
110
  }).strict();
64
111
  /**
65
112
  * Parse and validate a raw shelf-level configuration object.
@@ -1 +1 @@
1
- {"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { Logger } from \"pino\";\nimport { z } from \"zod\";\nimport type { AuthAdapter } from \"./adapters/auth.ts\";\nimport type { CaptureQueue } from \"./adapters/capture-queue.ts\";\nimport type { CaptureRunner } from \"./adapters/capture-runner.ts\";\nimport type { DatabaseAdapter } from \"./adapters/database.ts\";\nimport type { GitHostProvider } from \"./adapters/git-host/index.ts\";\nimport type { AdapterCategory } from \"./adapters/metadata.ts\";\nimport type { StorageAdapter } from \"./adapters/storage.ts\";\n\n/** Brand color theme for the server-rendered UI. */\nexport interface BrandTheme {\n accent: string;\n surface: { base: string; card: string };\n text: { primary: string; secondary: string };\n border: string;\n status: { approved: string; new: string; rejected: string };\n}\n\n/** Branding overrides for the server-rendered UI. */\nexport interface UIConfig {\n name?: string;\n logo?: string;\n favicon?: string;\n lightTheme?: BrandTheme;\n darkTheme?: BrandTheme;\n}\n\n/** Default cap for a single Storybook zip upload (1 GiB). */\nexport const DEFAULT_MAX_UPLOAD_BYTES = 1024 * 1024 * 1024;\n\n/** A viewport in which stories are captured. */\nexport interface ShelfViewport {\n name: string;\n width: number;\n height: number;\n}\n\n/** Metadata snapshot of a configured adapter. */\nexport interface AdapterSnapshot {\n name: string;\n version: string;\n description?: string;\n kind: string;\n category: AdapterCategory;\n}\n\n/** Shelf-level configuration (validated by {@link shelfConfigSchema}). */\nexport interface ShelfConfig {\n secret?: string;\n publishedBaseDomain?: string;\n captureConcurrency?: number;\n scratchDir?: string;\n purgeTtlDays?: number;\n maxUploadBytes?: number;\n /**\n * Max zip size (bytes) eligible for inline statics extraction at upload.\n * Unset (or 0) disables inline extraction — statics land via capture.\n */\n maxInlineUnzipSize?: number;\n viewports?: ShelfViewport[];\n adapters?: Record<string, AdapterSnapshot>;\n}\n\nconst viewportSchema: z.ZodType<ShelfViewport> = z.object({\n name: z.string().min(1),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n});\n\nconst brandThemeSchema = z.object({\n accent: z.string(),\n surface: z.object({ base: z.string(), card: z.string() }),\n text: z.object({ primary: z.string(), secondary: z.string() }),\n border: z.string(),\n status: z.object({ approved: z.string(), new: z.string(), rejected: z.string() }),\n});\n\nconst adapterSnapshotSchema: z.ZodType<AdapterSnapshot> = z.object({\n name: z.string(),\n version: z.string(),\n description: z.string().optional(),\n kind: z.string(),\n category: z.enum([\"database\", \"storage\", \"auth\", \"capture-runner\", \"capture-queue\", \"git-host\"]),\n});\n\n/** Zod schema validating the shelf-level configuration. */\nexport const shelfConfigSchema: z.ZodType<ShelfConfig> = z\n .object({\n secret: z.string().min(1).optional(),\n publishedBaseDomain: z.string().optional(),\n captureConcurrency: z.number().int().positive().optional(),\n scratchDir: z.string().optional(),\n purgeTtlDays: z.number().int().positive().optional(),\n maxUploadBytes: z.number().int().positive().optional(),\n maxInlineUnzipSize: z.number().int().positive().optional(),\n viewports: z.array(viewportSchema).min(1, \"at least one viewport required\").optional(),\n adapters: z.record(z.string(), adapterSnapshotSchema).optional(),\n })\n .strict();\n\n/** Zod schema validating the UI branding configuration. */\nexport const uiConfigSchema = z\n .object({\n name: z.string().optional(),\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n logo: z.string().url().optional(),\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n favicon: z.string().url().optional(),\n lightTheme: brandThemeSchema.optional(),\n darkTheme: brandThemeSchema.optional(),\n })\n .strict();\n\n/**\n * Parse and validate a raw shelf-level configuration object.\n *\n * @param config - Unvalidated configuration record.\n * @returns The validated shelf configuration.\n */\nexport function validateConfig(config: Record<string, unknown>): ShelfConfig {\n const result = shelfConfigSchema.safeParse(config);\n if (!result.success) {\n const issues = result.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`Invalid ShelfConfig: ${issues}`);\n }\n return result.data;\n}\n\n/**\n * Parse and validate a raw UI branding configuration object.\n *\n * @param config - Unvalidated UI configuration record.\n * @returns The validated UI configuration.\n */\nexport function validateUiConfig(config: Record<string, unknown>): UIConfig {\n const result = uiConfigSchema.safeParse(config);\n if (!result.success) {\n const issues = result.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`Invalid UIConfig: ${issues}`);\n }\n return result.data;\n}\n\n/** Adapter and configuration options for creating the shelf router. */\nexport interface ShelfOptions {\n database: DatabaseAdapter;\n storage: StorageAdapter;\n captureRunner?: CaptureRunner;\n captureQueue?: CaptureQueue;\n auth?: AuthAdapter;\n gitHosts?: GitHostProvider[];\n logger?: Logger;\n ui?: UIConfig;\n config?: ShelfConfig;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.mjs","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { Logger } from \"pino\";\nimport { z } from \"zod\";\nimport type { CaptureQueue } from \"./adapters/capture-queue.ts\";\nimport type { CaptureRunner } from \"./adapters/capture-runner.ts\";\nimport type { DatabaseAdapter } from \"./adapters/database.ts\";\nimport type { EmailSender } from \"./adapters/email-sender.ts\";\nimport type { GitHostProvider } from \"./adapters/git-host/index.ts\";\nimport type { AdapterCategory } from \"./adapters/metadata.ts\";\nimport type { NotifierProvider } from \"./adapters/notifier/provider.ts\";\nimport type { StorageAdapter } from \"./adapters/storage.ts\";\nimport type { Auth } from \"./auth.ts\";\n\n/** Brand color theme for the server-rendered UI. */\nexport interface BrandTheme {\n accent: string;\n accentContrast?: string;\n ring?: string;\n surface: { base: string; card: string; muted?: string; subtle?: string };\n text: { primary: string; secondary: string; muted?: string };\n border: string;\n borderSubtle?: string;\n status: { approved: string; new: string; rejected: string };\n sidebarBg?: string;\n topbarBg?: string;\n radius?: string;\n radiusSm?: string;\n shadow?: string;\n}\n\n/** Text overrides for the auth (login) UI. */\nexport interface AuthUiConfig {\n /** Page title, default \"Sign in\". */\n title?: string;\n /** Optional subtitle under the title. */\n subtitle?: string;\n /** Password field label, default \"Password\". */\n passwordLabel?: string;\n /** Password field placeholder. */\n passwordPlaceholder?: string;\n /** Submit button label, default \"Sign in\". */\n submitLabel?: string;\n /**\n * Template for SSO buttons, default \"Sign in with {label}\".\n * Must contain \"{label}\" which is replaced with the provider label.\n */\n ssoLabelTemplate?: string;\n /** Help text shown under the form. */\n helpText?: string;\n /** Footer text shown at the bottom of the card. */\n footerText?: string;\n}\n\n/** Branding overrides for the server-rendered UI. */\nexport interface UIConfig {\n name?: string;\n logo?: string;\n /**\n * @deprecated Ignored. The favicon is the product's own mark, served by the\n * app itself; set `logo` to rebrand the sidebar instead.\n */\n favicon?: string;\n lightTheme?: BrandTheme;\n darkTheme?: BrandTheme;\n auth?: AuthUiConfig;\n}\n\n/** Default cap for a single Storybook zip upload (1 GiB). */\nexport const DEFAULT_MAX_UPLOAD_BYTES = 1024 * 1024 * 1024;\n\n/** A viewport in which stories are captured. */\nexport interface ShelfViewport {\n name: string;\n width: number;\n height: number;\n}\n\n/** Metadata snapshot of a configured adapter. */\nexport interface AdapterSnapshot {\n name: string;\n version: string;\n description?: string;\n kind: string;\n category: AdapterCategory;\n}\n\n/** Site-wide notification defaults (brand + sender identity for admin alerts). */\nexport interface NotificationsConfig {\n fromEmail?: string;\n fromName?: string;\n footerText?: string;\n slackUsername?: string;\n}\n/** Shelf-level configuration (validated by {@link shelfConfigSchema}). */\nexport interface ShelfConfig {\n secret?: string;\n /**\n * The secret `secret` replaced. Used only to decrypt stored credentials\n * (webhook, git-token, and notification secrets) written before a rotation;\n * new writes always use `secret`. Remove once credentials are re-encrypted.\n */\n previousSecret?: string;\n /**\n * Re-encrypt credentials still under `previousSecret` at boot. Default false:\n * site admins can run it from the System page instead. No effect without\n * `previousSecret`.\n */\n migrateCredentialsOnBoot?: boolean;\n /**\n * Bootstrap site-admin bearer token (`STORYSHELF_ADMIN_TOKEN`/`ADMIN_TOKEN`).\n * Grants site-admin API access when no admin user exists yet; never\n * mint sessions from it. Distinct from `secret` (session signing).\n */\n adminToken?: string;\n publishedBaseDomain?: string;\n /**\n * Public base URL of this deployment (e.g. `https://shelf.example.com`).\n * Used as the issuer in the `/.well-known/openid-configuration` relying-party\n * helper document; falls back to the request origin when unset.\n */\n publicBaseUrl?: string;\n captureConcurrency?: number;\n scratchDir?: string;\n purgeTtlDays?: number;\n /** Branch baseline TTL, days; null disables branch GC (default 30). */\n branchTtlDays?: number | null;\n /** Branch GC interval, ms; daily sweep via interval clock (default 86_400_000). */\n branchGcIntervalMs?: number;\n maxUploadBytes?: number;\n /**\n * Emit `Server-Timing` response headers (total + db/storage roll-ups).\n * Opt-in, off by default — some deployments prefer no timing headers.\n */\n serverTiming?: boolean;\n /**\n * Max zip size (bytes) eligible for inline statics extraction at upload.\n * Unset (or 0) disables inline extraction — statics land via capture.\n */\n maxInlineUnzipSize?: number;\n viewports?: ShelfViewport[];\n adapters?: Record<string, AdapterSnapshot>;\n notifications?: NotificationsConfig;\n}\n\nconst viewportSchema: z.ZodType<ShelfViewport> = z.object({\n name: z.string().min(1),\n width: z.number().int().positive(),\n height: z.number().int().positive(),\n});\n\nconst brandThemeSchema: z.ZodType<BrandTheme> = z.object({\n accent: z.string(),\n accentContrast: z.string().optional(),\n ring: z.string().optional(),\n surface: z.object({\n base: z.string(),\n card: z.string(),\n muted: z.string().optional(),\n subtle: z.string().optional(),\n }),\n text: z.object({ primary: z.string(), secondary: z.string(), muted: z.string().optional() }),\n border: z.string(),\n borderSubtle: z.string().optional(),\n status: z.object({ approved: z.string(), new: z.string(), rejected: z.string() }),\n sidebarBg: z.string().optional(),\n topbarBg: z.string().optional(),\n radius: z.string().optional(),\n radiusSm: z.string().optional(),\n shadow: z.string().optional(),\n});\n\nconst adapterSnapshotSchema: z.ZodType<AdapterSnapshot> = z.object({\n name: z.string(),\n version: z.string(),\n description: z.string().optional(),\n kind: z.string(),\n category: z.enum([\n \"database\",\n \"storage\",\n \"capture-runner\",\n \"capture-queue\",\n \"git-host\",\n \"notifier\",\n ]),\n});\n\nconst authUiConfigSchema: z.ZodType<AuthUiConfig> = z.object({\n title: z.string().min(1).optional(),\n subtitle: z.string().optional(),\n passwordLabel: z.string().min(1).optional(),\n passwordPlaceholder: z.string().optional(),\n submitLabel: z.string().min(1).optional(),\n ssoLabelTemplate: z.string().min(1).optional(),\n helpText: z.string().optional(),\n footerText: z.string().optional(),\n});\n\nconst notificationsConfigSchema: z.ZodType<NotificationsConfig> = z.object({\n fromEmail: z.string().min(1).optional(),\n fromName: z.string().min(1).optional(),\n footerText: z.string().min(1).optional(),\n slackUsername: z.string().min(1).optional(),\n});\n\n/** Zod schema validating the shelf-level configuration. */\nexport const shelfConfigSchema: z.ZodType<ShelfConfig> = z\n .object({\n secret: z.string().min(1).optional(),\n previousSecret: z.string().min(1).optional(),\n migrateCredentialsOnBoot: z.boolean().optional(),\n adminToken: z.string().min(1).optional(),\n publishedBaseDomain: z.string().optional(),\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n publicBaseUrl: z.string().url().optional(),\n captureConcurrency: z.number().int().positive().optional(),\n scratchDir: z.string().optional(),\n purgeTtlDays: z.number().int().positive().optional(),\n branchTtlDays: z.number().int().positive().nullable().optional(),\n branchGcIntervalMs: z.number().int().positive().optional(),\n maxUploadBytes: z.number().int().positive().optional(),\n serverTiming: z.boolean().optional(),\n maxInlineUnzipSize: z.number().int().positive().optional(),\n viewports: z.array(viewportSchema).min(1, \"at least one viewport required\").optional(),\n adapters: z.record(z.string(), adapterSnapshotSchema).optional(),\n notifications: notificationsConfigSchema.optional(),\n })\n .strict()\n .superRefine((config, ctx) => {\n if (config.previousSecret !== undefined && config.secret === undefined) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"previousSecret\"],\n message: \"previousSecret requires secret\",\n });\n }\n if (config.previousSecret !== undefined && config.previousSecret === config.secret) {\n ctx.addIssue({\n code: \"custom\",\n path: [\"previousSecret\"],\n message: \"previousSecret must differ from secret\",\n });\n }\n });\n\n/** Zod schema validating the UI branding configuration. */\nexport const uiConfigSchema: z.ZodType<UIConfig> = z\n .object({\n name: z.string().optional(),\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n logo: z.string().url().optional(),\n // Accepted but ignored (see UIConfig.favicon) so existing configs keep\n // validating under .strict().\n // oxlint-disable-next-line typescript/no-deprecated -- z.string().url() kept for zod v3 API compat\n favicon: z.string().url().optional(),\n lightTheme: brandThemeSchema.optional(),\n darkTheme: brandThemeSchema.optional(),\n auth: authUiConfigSchema.optional(),\n })\n .strict();\n\n/**\n * Parse and validate a raw shelf-level configuration object.\n *\n * @param config - Unvalidated configuration record.\n * @returns The validated shelf configuration.\n */\nexport function validateConfig(config: Record<string, unknown>): ShelfConfig {\n const result = shelfConfigSchema.safeParse(config);\n if (!result.success) {\n const issues = result.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`Invalid ShelfConfig: ${issues}`);\n }\n return result.data;\n}\n\n/**\n * Parse and validate a raw UI branding configuration object.\n *\n * @param config - Unvalidated UI configuration record.\n * @returns The validated UI configuration.\n */\nexport function validateUiConfig(config: Record<string, unknown>): UIConfig {\n const result = uiConfigSchema.safeParse(config);\n if (!result.success) {\n const issues = result.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \");\n throw new Error(`Invalid UIConfig: ${issues}`);\n }\n return result.data;\n}\n\n/** Adapter and configuration options for creating the shelf router. */\nexport interface ShelfOptions {\n database: DatabaseAdapter;\n storage: StorageAdapter;\n captureRunner?: CaptureRunner;\n captureQueue?: CaptureQueue;\n auth?: Auth;\n gitHosts?: GitHostProvider[];\n notifiers?: NotifierProvider[];\n emailSender?: EmailSender;\n logger?: Logger;\n ui?: UIConfig;\n config?: ShelfConfig;\n /**\n * Externally-managed observability SDK handle (e.g. from\n * `initObservabilityFromEnv`). Structural — core never imports the\n * observability package. Flushed on `app.lifecycle.teardown()`.\n */\n observability?: ObservabilityHandle;\n}\n\n/**\n * Shutdown hook for an externally-managed observability SDK.\n * Structural so core stays dependency-free.\n */\nexport interface ObservabilityHandle {\n /** Flush exporters and release SDK resources. Must be idempotent. */\n shutdown(): Promise<void>;\n}\n"],"mappings":";;;;;;AAmEA,MAAa,2BAA2B;AA4ExC,MAAM,iBAA2C,EAAE,OAAO;CACxD,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;CACtB,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CACjC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;AACpC,CAAC;AAED,MAAM,mBAA0C,EAAE,OAAO;CACvD,QAAQ,EAAE,OAAO;CACjB,gBAAgB,EAAE,OAAO,CAAC,CAAC,SAAS;CACpC,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;CAC1B,SAAS,EAAE,OAAO;EAChB,MAAM,EAAE,OAAO;EACf,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;EAC3B,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,CAAC;CACD,MAAM,EAAE,OAAO;EAAE,SAAS,EAAE,OAAO;EAAG,WAAW,EAAE,OAAO;EAAG,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAAE,CAAC;CAC3F,QAAQ,EAAE,OAAO;CACjB,cAAc,EAAE,OAAO,CAAC,CAAC,SAAS;CAClC,QAAQ,EAAE,OAAO;EAAE,UAAU,EAAE,OAAO;EAAG,KAAK,EAAE,OAAO;EAAG,UAAU,EAAE,OAAO;CAAE,CAAC;CAChF,WAAW,EAAE,OAAO,CAAC,CAAC,SAAS;CAC/B,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;CAC5B,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;AAC9B,CAAC;AAED,MAAM,wBAAoD,EAAE,OAAO;CACjE,MAAM,EAAE,OAAO;CACf,SAAS,EAAE,OAAO;CAClB,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS;CACjC,MAAM,EAAE,OAAO;CACf,UAAU,EAAE,KAAK;EACf;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;AACH,CAAC;AAED,MAAM,qBAA8C,EAAE,OAAO;CAC3D,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CAClC,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CAC1C,qBAAqB,EAAE,OAAO,CAAC,CAAC,SAAS;CACzC,aAAa,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACxC,kBAAkB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CAC7C,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;CAC9B,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS;AAClC,CAAC;AAED,MAAM,4BAA4D,EAAE,OAAO;CACzE,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACtC,UAAU,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACrC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACvC,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;AAC5C,CAAC;;AAGD,MAAa,oBAA4C,EACtD,OAAO;CACN,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACnC,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CAC3C,0BAA0B,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC/C,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;CACvC,qBAAqB,EAAE,OAAO,CAAC,CAAC,SAAS;CAEzC,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CACzC,oBAAoB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACzD,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS;CAChC,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACnD,eAAe,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CAC/D,oBAAoB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACzD,gBAAgB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACrD,cAAc,EAAE,QAAQ,CAAC,CAAC,SAAS;CACnC,oBAAoB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS;CACzD,WAAW,EAAE,MAAM,cAAc,CAAC,CAAC,IAAI,GAAG,gCAAgC,CAAC,CAAC,SAAS;CACrF,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,qBAAqB,CAAC,CAAC,SAAS;CAC/D,eAAe,0BAA0B,SAAS;AACpD,CAAC,CAAC,CACD,OAAO,CAAC,CACR,aAAa,QAAQ,QAAQ;CAC5B,IAAI,OAAO,mBAAmB,KAAA,KAAa,OAAO,WAAW,KAAA,GAC3D,IAAI,SAAS;EACX,MAAM;EACN,MAAM,CAAC,gBAAgB;EACvB,SAAS;CACX,CAAC;CAEH,IAAI,OAAO,mBAAmB,KAAA,KAAa,OAAO,mBAAmB,OAAO,QAC1E,IAAI,SAAS;EACX,MAAM;EACN,MAAM,CAAC,gBAAgB;EACvB,SAAS;CACX,CAAC;AAEL,CAAC;;AAGH,MAAa,iBAAsC,EAChD,OAAO;CACN,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;CAE1B,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CAIhC,SAAS,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS;CACnC,YAAY,iBAAiB,SAAS;CACtC,WAAW,iBAAiB,SAAS;CACrC,MAAM,mBAAmB,SAAS;AACpC,CAAC,CAAC,CACD,OAAO;;;;;;;AAQV,SAAgB,eAAe,QAA8C;CAC3E,MAAM,SAAS,kBAAkB,UAAU,MAAM;CACjD,IAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,OAAO,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI;EAC5F,MAAM,IAAI,MAAM,wBAAwB,QAAQ;CAClD;CACA,OAAO,OAAO;AAChB;;;;;;;AAQA,SAAgB,iBAAiB,QAA2C;CAC1E,MAAM,SAAS,eAAe,UAAU,MAAM;CAC9C,IAAI,CAAC,OAAO,SAAS;EACnB,MAAM,SAAS,OAAO,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,KAAK,IAAI;EAC5F,MAAM,IAAI,MAAM,qBAAqB,QAAQ;CAC/C;CACA,OAAO,OAAO;AAChB"}
package/dist/index.d.mts CHANGED
@@ -1,58 +1,7 @@
1
1
  import __tsdown_shims_path from 'node:path';
2
2
  import __tsdown_shims_url from 'node:url';
3
- import { CaptureQueue } from "./adapter/capture-queue.mjs";
4
- import { DatabaseAdapter } from "./adapter/database.mjs";
5
- import { GitHostProvider } from "./adapter/git-host.mjs";
6
- import { StorageAdapter } from "./adapter/storage.mjs";
7
- import { BrandTheme, ShelfConfig, ShelfOptions, UIConfig } from "./config.mjs";
8
- import { createShelfLogger } from "./logger.mjs";
9
- import { AuthUser } from "./adapter/auth.mjs";
10
- import { AdapterInitResult } from "./adapter/init.mjs";
11
- import { OpenAPIHono } from "@hono/zod-openapi";
12
- //#region src/index.d.ts
13
- /** Per-request shelf context (adapters, config, user, capture queue). */
14
- interface ShelfContext {
15
- requestId?: string;
16
- db: DatabaseAdapter;
17
- storage: StorageAdapter;
18
- config: ShelfConfig;
19
- ui: UIConfig;
20
- logger: ReturnType<typeof createShelfLogger>;
21
- user: AuthUser | null;
22
- authEnabled: boolean;
23
- enqueueCapture?: (buildId: string, reqId?: string) => Promise<void>;
24
- captureQueue: CaptureQueue | null;
25
- gitHosts: GitHostProvider[];
26
- }
27
- /** Hono application type carrying the shelf context variables. */
28
- type ShelfApp = OpenAPIHono<{
29
- Variables: ShelfContext;
30
- }>;
31
- /** App-scoped adapter lifecycle namespace (single `lifecycle` prop avoids Hono collisions). */
32
- interface ShelfLifecycle {
33
- /** Settled summary of the eager background init run; never rejects. */
34
- readonly ready: Promise<AdapterInitResult>;
35
- /**
36
- * Fail-fast await for server startup (`await app.lifecycle.init()`).
37
- * Re-runs init so transient failures are retryable; throws AdapterLifecycleError.
38
- * Optional — when skipped, the first request gates on `ready` instead.
39
- */
40
- init(): Promise<void>;
41
- /** Graceful teardown for SIGTERM/SIGINT (`await app.lifecycle.close()`). Idempotent. */
42
- close(): Promise<void>;
43
- }
44
- /** Hono app with the shelf lifecycle namespace attached. */
45
- type ShelfRouter = ShelfApp & {
46
- readonly lifecycle: ShelfLifecycle;
47
- };
48
- /**
49
- * Create the StoryShelf Hono router with all API routes and HTML pages.
50
- *
51
- * Adapter `init` hooks kick off eagerly in the background (the constructor
52
- * stays synchronous). Await `app.lifecycle.init()` before serving for
53
- * fail-fast startup, or let the first request gate on settlement.
54
- */
55
- declare function createShelfRouter(options: ShelfOptions): ShelfRouter;
56
- //#endregion
57
- export { type BrandTheme, ShelfApp, type ShelfConfig, ShelfContext, ShelfLifecycle, type ShelfOptions, ShelfRouter, type UIConfig, createShelfRouter };
58
- //# sourceMappingURL=index.d.mts.map
3
+ import { BUILD_STATUSES, BuildStatus, ProjectRole, SNAPSHOT_STATUSES, SiteRole, SnapshotStatus, TERMINAL_BUILD_STATUSES } from "./types.mjs";
4
+ import { AdapterSnapshot, BrandTheme, DEFAULT_MAX_UPLOAD_BYTES, ShelfConfig, ShelfOptions, ShelfViewport, UIConfig, shelfConfigSchema, uiConfigSchema, validateConfig, validateUiConfig } from "./config.mjs";
5
+ import { Logger, LoggerOptions, PinoTransport, createShelfLogger } from "./logger.mjs";
6
+ import { BrandPack, brandPack, brandPacks } from "./brand-packs.mjs";
7
+ export { type AdapterSnapshot, BUILD_STATUSES, type BrandPack, type BrandTheme, type BuildStatus, DEFAULT_MAX_UPLOAD_BYTES, type Logger, type LoggerOptions, type PinoTransport, type ProjectRole, SNAPSHOT_STATUSES, type ShelfConfig, type ShelfOptions, type ShelfViewport, type SiteRole, type SnapshotStatus, TERMINAL_BUILD_STATUSES, type UIConfig, brandPack, brandPacks, createShelfLogger, shelfConfigSchema, uiConfigSchema, validateConfig, validateUiConfig };