@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,20 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { projects } from "./project.mjs";
5
- import { sqliteTable, text } from "drizzle-orm/sqlite-core";
6
- //#region src/schema/webhook.ts
7
- /** Narrow `webhooks` table definition. */
8
- const webhooks = sqliteTable("webhooks", {
9
- id: text("id").primaryKey(),
10
- projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
11
- url: text("url").notNull(),
12
- secretEncrypted: text("secret_encrypted").notNull(),
13
- events: text("events"),
14
- createdAt: text("created_at").notNull(),
15
- updatedAt: text("updated_at").notNull()
16
- });
17
- //#endregion
18
- export { webhooks };
19
-
20
- //# sourceMappingURL=webhook.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhook.mjs","names":[],"sources":["../../src/schema/webhook.ts"],"sourcesContent":["import { sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { projects } from \"./project.ts\";\n\n/** Narrow `webhooks` table definition. */\nexport const webhooks = sqliteTable(\"webhooks\", {\n id: text(\"id\").primaryKey(),\n projectId: text(\"project_id\")\n .notNull()\n .references(() => projects.id, { onDelete: \"cascade\" }),\n url: text(\"url\").notNull(),\n secretEncrypted: text(\"secret_encrypted\").notNull(),\n events: text(\"events\"),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/** A webhook subscription row. */\nexport interface Webhook {\n id: string;\n projectId: string;\n url: string;\n secretEncrypted: string;\n events: string | null;\n createdAt: string;\n updatedAt: string;\n}\n"],"mappings":";;;;;;;AAIA,MAAa,WAAW,YAAY,YAAY;CAC9C,IAAI,KAAK,IAAI,CAAC,CAAC,WAAW;CAC1B,WAAW,KAAK,YAAY,CAAC,CAC1B,QAAQ,CAAC,CACT,iBAAiB,SAAS,IAAI,EAAE,UAAU,UAAU,CAAC;CACxD,KAAK,KAAK,KAAK,CAAC,CAAC,QAAQ;CACzB,iBAAiB,KAAK,kBAAkB,CAAC,CAAC,QAAQ;CAClD,QAAQ,KAAK,QAAQ;CACrB,WAAW,KAAK,YAAY,CAAC,CAAC,QAAQ;CACtC,WAAW,KAAK,YAAY,CAAC,CAAC,QAAQ;AACxC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.mjs","names":["projectsTable","projectStatusConfigsTable","buildsTable","snapshotsTable","baselinesTable","commentsTable","labelTypesTable","buildLabelsTable","tokensTable","webhooksTable","usersTable","projectMembersTable"],"sources":["../src/schema/index.ts"],"sourcesContent":["/**\n * Database schema: table handles, row types, and the schema object passed\n * to the database client.\n */\nimport type { AnySQLiteTable } from \"drizzle-orm/sqlite-core\";\n\nimport { baselines as baselinesTable } from \"./baseline.ts\";\nimport { buildLabels as buildLabelsTable, labelTypes as labelTypesTable } from \"./label.ts\";\nimport { builds as buildsTable } from \"./build.ts\";\nimport { comments as commentsTable } from \"./comment.ts\";\nimport { projectMembers as projectMembersTable } from \"./member.ts\";\nimport { projects as projectsTable } from \"./project.ts\";\nimport { projectStatusConfigs as projectStatusConfigsTable } from \"./status-config.ts\";\nimport { snapshots as snapshotsTable } from \"./snapshot.ts\";\nimport { tokens as tokensTable } from \"./token.ts\";\nimport { users as usersTable } from \"./user.ts\";\nimport { webhooks as webhooksTable } from \"./webhook.ts\";\n\n/**\n * Database schema: table handles, row types, and the schema object passed\n * to the database client.\n *\n * Table handles are explicitly typed (JSR fast-check); exact column types\n * live on the narrow per-entity definitions, and the row interfaces are\n * pinned to them by `schema-types.test.ts`.\n */\nexport type { Baseline } from \"./baseline.ts\";\nexport type { Build } from \"./build.ts\";\nexport type { Comment } from \"./comment.ts\";\nexport type { BuildLabel, LabelType } from \"./label.ts\";\nexport type { ProjectMember } from \"./member.ts\";\nexport type { Project, StorybookMeta } from \"./project.ts\";\nexport type { ProjectStatusConfig } from \"./status-config.ts\";\nexport type { Snapshot } from \"./snapshot.ts\";\nexport type { Token } from \"./token.ts\";\nexport type { User } from \"./user.ts\";\nexport type { Webhook } from \"./webhook.ts\";\n\n/** Projects table (one row per Storybook project). */\nexport const projects: AnySQLiteTable = projectsTable;\n/** Project status-configs table (merge-gate configurations). */\nexport const projectStatusConfigs: AnySQLiteTable = projectStatusConfigsTable;\n/** Builds table (one row per uploaded Storybook build). */\nexport const builds: AnySQLiteTable = buildsTable;\n/** Snapshots table (one row per captured story screenshot). */\nexport const snapshots: AnySQLiteTable = snapshotsTable;\n/** Baselines table (accepted reference snapshots per branch). */\nexport const baselines: AnySQLiteTable = baselinesTable;\n/** Comments table (review comments on snapshots). */\nexport const comments: AnySQLiteTable = commentsTable;\n/** Label-types table (project-defined build label vocabularies). */\nexport const labelTypes: AnySQLiteTable = labelTypesTable;\n/** Build-labels table (labels attached to builds). */\nexport const buildLabels: AnySQLiteTable = buildLabelsTable;\n/** Tokens table (CI token hashes per project). */\nexport const tokens: AnySQLiteTable = tokensTable;\n/** Webhooks table (outgoing build-event subscriptions). */\nexport const webhooks: AnySQLiteTable = webhooksTable;\n/** Users table (dashboard members). */\nexport const users: AnySQLiteTable = usersTable;\n/** Project-members table (per-project memberships and roles). */\nexport const projectMembers: AnySQLiteTable = projectMembersTable;\n\n/** Full Drizzle schema object passed to the database client. */\nexport const schema = {\n projects,\n projectStatusConfigs,\n builds,\n snapshots,\n baselines,\n comments,\n labelTypes,\n buildLabels,\n tokens,\n webhooks,\n users,\n projectMembers,\n};\n\n/** The full database schema type. */\nexport type Schema = typeof schema;\n"],"mappings":";;;;;;;;;;;;;;;;AAuCA,MAAa,WAA2BA;;AAExC,MAAa,uBAAuCC;;AAEpD,MAAa,SAAyBC;;AAEtC,MAAa,YAA4BC;;AAEzC,MAAa,YAA4BC;;AAEzC,MAAa,WAA2BC;;AAExC,MAAa,aAA6BC;;AAE1C,MAAa,cAA8BC;;AAE3C,MAAa,SAAyBC;;AAEtC,MAAa,WAA2BC;;AAExC,MAAa,QAAwBC;;AAErC,MAAa,iBAAiCC;;AAG9C,MAAa,SAAS;CACpB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
package/dist/store.mjs DELETED
@@ -1,20 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { AsyncLocalStorage } from "node:async_hooks";
5
- //#region src/store.ts
6
- const storage = new AsyncLocalStorage();
7
- /** Run a function with the given request store in scope. */
8
- function runWithStore(store, fn) {
9
- return storage.run(store, fn);
10
- }
11
- /** Return the current request store, throwing outside a request scope. */
12
- function getStore() {
13
- const store = storage.getStore();
14
- if (!store) throw new Error("Store not available. Use runWithStore().");
15
- return store;
16
- }
17
- //#endregion
18
- export { getStore, runWithStore };
19
-
20
- //# sourceMappingURL=store.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.mjs","names":[],"sources":["../src/store.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Logger } from \"pino\";\nimport type { AuthUser } from \"./adapters/auth.ts\";\nimport type { CaptureQueue } from \"./adapters/capture-queue.ts\";\nimport type { DatabaseAdapter } from \"./adapters/database.ts\";\nimport type { GitHostProvider } from \"./adapters/git-host/index.ts\";\nimport type { StorageAdapter } from \"./adapters/storage.ts\";\nimport type { ShelfConfig, UIConfig } from \"./config.ts\";\n\n/** Request-scoped dependencies and session state. */\nexport interface Store {\n db: DatabaseAdapter;\n storage: StorageAdapter;\n config: ShelfConfig;\n ui: UIConfig;\n logger: Logger;\n user: AuthUser | null;\n authEnabled: boolean;\n enqueueCapture?: (buildId: string, reqId?: string) => Promise<void>;\n captureQueue?: CaptureQueue | null;\n gitHosts: GitHostProvider[];\n}\n\nconst storage = new AsyncLocalStorage<Store>();\n\n/** Run a function with the given request store in scope. */\nexport function runWithStore<T>(store: Store, fn: () => T): T {\n return storage.run(store, fn);\n}\n\n/** Return the current request store, throwing outside a request scope. */\nexport function getStore(): Store {\n const store = storage.getStore();\n if (!store) {\n throw new Error(\"Store not available. Use runWithStore().\");\n }\n return store;\n}\n"],"mappings":";;;;;AAuBA,MAAM,UAAU,IAAI,kBAAyB;;AAG7C,SAAgB,aAAgB,OAAc,IAAgB;CAC5D,OAAO,QAAQ,IAAI,OAAO,EAAE;AAC9B;;AAGA,SAAgB,WAAkB;CAChC,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,0CAA0C;CAE5D,OAAO;AACT"}
@@ -1,348 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { getStore } from "../store.mjs";
5
- import { baseStyle } from "./styles.mjs";
6
- import { DARK_THEME, LIGHT_THEME } from "./theme.mjs";
7
- import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
8
- //#region src/ui/document.tsx
9
- /** Full HTML document shell with top bar, sidebar, theme, and HTMX. */
10
- const DocumentLayout = ({ title, nav, children }) => {
11
- const { ui } = getStore();
12
- const name = ui.name ?? "StoryShelf";
13
- const light = ui.lightTheme ?? LIGHT_THEME;
14
- const dark = ui.darkTheme ?? DARK_THEME;
15
- return /* @__PURE__ */ jsxs("html", {
16
- lang: "en",
17
- "data-theme": "system",
18
- children: [/* @__PURE__ */ jsxs("head", { children: [
19
- /* @__PURE__ */ jsx("meta", { charset: "utf-8" }),
20
- /* @__PURE__ */ jsx("meta", {
21
- name: "viewport",
22
- content: "width=device-width, initial-scale=1"
23
- }),
24
- /* @__PURE__ */ jsx("meta", {
25
- name: "color-scheme",
26
- content: "light dark"
27
- }),
28
- ui.favicon ? /* @__PURE__ */ jsx("link", {
29
- rel: "icon",
30
- href: ui.favicon
31
- }) : null,
32
- /* @__PURE__ */ jsxs("title", { children: [
33
- title,
34
- " · ",
35
- name
36
- ] }),
37
- /* @__PURE__ */ jsx("style", { children: baseStyle(light, dark) }),
38
- /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: themeScript() } })
39
- ] }), /* @__PURE__ */ jsxs("body", { children: [
40
- /* @__PURE__ */ jsx("a", {
41
- class: "skip-link",
42
- href: "#main-content",
43
- children: "Skip to content"
44
- }),
45
- /* @__PURE__ */ jsx(TopBar, {
46
- name,
47
- logo: ui.logo,
48
- nav
49
- }),
50
- /* @__PURE__ */ jsxs("div", {
51
- class: "shell",
52
- children: [/* @__PURE__ */ jsx(Sidebar, { nav }), /* @__PURE__ */ jsx("main", {
53
- id: "main-content",
54
- class: "content",
55
- tabindex: -1,
56
- children
57
- })]
58
- }),
59
- /* @__PURE__ */ jsx("script", { src: "/assets/htmx.js" }),
60
- /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: clientScript() } })
61
- ] })]
62
- });
63
- };
64
- const TopBar = ({ name, logo, nav }) => {
65
- return /* @__PURE__ */ jsx("header", {
66
- class: "topbar",
67
- role: "banner",
68
- children: /* @__PURE__ */ jsxs("div", {
69
- class: "topbar__inner",
70
- children: [/* @__PURE__ */ jsxs("div", {
71
- class: "topbar__left",
72
- children: [
73
- /* @__PURE__ */ jsx("button", {
74
- class: "topbar__menu",
75
- type: "button",
76
- "aria-label": "Toggle navigation",
77
- "aria-expanded": "false",
78
- "aria-controls": "sidebar",
79
- "data-sidebar-toggle": true,
80
- children: /* @__PURE__ */ jsx("span", {
81
- "aria-hidden": "true",
82
- children: "☰"
83
- })
84
- }),
85
- /* @__PURE__ */ jsxs("a", {
86
- class: "brand",
87
- href: "/",
88
- children: [logo ? /* @__PURE__ */ jsx("img", {
89
- class: "logo",
90
- src: logo,
91
- alt: name,
92
- width: "28",
93
- height: "28"
94
- }) : /* @__PURE__ */ jsx("span", {
95
- class: "brand__mark",
96
- "aria-hidden": "true",
97
- children: "◆"
98
- }), /* @__PURE__ */ jsx("span", {
99
- class: "brand__name",
100
- children: name
101
- })]
102
- }),
103
- nav?.projectSlug ? /* @__PURE__ */ jsxs("nav", {
104
- class: "project-crumb",
105
- "aria-label": "Project",
106
- children: [/* @__PURE__ */ jsx("span", {
107
- class: "project-crumb__sep",
108
- "aria-hidden": "true",
109
- children: "/"
110
- }), /* @__PURE__ */ jsx("a", {
111
- href: `/projects/${nav.projectSlug}/builds`,
112
- children: nav.projectName ?? nav.projectSlug
113
- })]
114
- }) : null
115
- ]
116
- }), /* @__PURE__ */ jsxs("div", {
117
- class: "topbar__right",
118
- children: [/* @__PURE__ */ jsx(ThemeToggle, {}), /* @__PURE__ */ jsx(AuthMenu, {})]
119
- })]
120
- })
121
- });
122
- };
123
- const ThemeToggle = () => {
124
- return /* @__PURE__ */ jsxs("button", {
125
- class: "topbar__theme",
126
- type: "button",
127
- "aria-label": "Toggle theme",
128
- "data-theme-toggle": true,
129
- children: [
130
- /* @__PURE__ */ jsx("span", {
131
- "data-theme-icon": "light",
132
- "aria-hidden": "true",
133
- children: "☀"
134
- }),
135
- /* @__PURE__ */ jsx("span", {
136
- "data-theme-icon": "dark",
137
- "aria-hidden": "true",
138
- children: "☾"
139
- }),
140
- /* @__PURE__ */ jsx("span", {
141
- "data-theme-icon": "system",
142
- "aria-hidden": "true",
143
- children: "◐"
144
- })
145
- ]
146
- });
147
- };
148
- const AuthMenu = () => {
149
- const { user, authEnabled } = getStore();
150
- if (!authEnabled) return null;
151
- if (!user) return /* @__PURE__ */ jsx("a", {
152
- class: "topbar__login",
153
- href: "/auth/login",
154
- children: "Sign in"
155
- });
156
- return /* @__PURE__ */ jsxs("div", {
157
- class: "user-menu",
158
- children: [
159
- user.avatarUrl ? /* @__PURE__ */ jsx("img", {
160
- class: "user-menu__avatar",
161
- src: user.avatarUrl,
162
- alt: "",
163
- width: "28",
164
- height: "28"
165
- }) : /* @__PURE__ */ jsx("span", {
166
- class: "user-menu__avatar user-menu__avatar--fallback",
167
- "aria-hidden": "true",
168
- children: user.name.slice(0, 1).toUpperCase()
169
- }),
170
- /* @__PURE__ */ jsx("span", {
171
- class: "user-menu__name",
172
- children: user.name
173
- }),
174
- /* @__PURE__ */ jsx("span", {
175
- class: `user-menu__role user-menu__role--${user.role}`,
176
- children: user.role
177
- }),
178
- /* @__PURE__ */ jsx("form", {
179
- method: "post",
180
- action: "/auth/logout",
181
- children: /* @__PURE__ */ jsx("button", {
182
- class: "user-menu__logout",
183
- type: "submit",
184
- children: "Sign out"
185
- })
186
- })
187
- ]
188
- });
189
- };
190
- const Sidebar = ({ nav }) => {
191
- return /* @__PURE__ */ jsx("aside", {
192
- id: "sidebar",
193
- class: "sidebar",
194
- "aria-label": "Primary",
195
- children: /* @__PURE__ */ jsxs("nav", {
196
- class: "sidebar__nav",
197
- children: [
198
- /* @__PURE__ */ jsxs("a", {
199
- class: `sidebar__link ${nav?.active === "projects" ? "sidebar__link--active" : ""}`,
200
- href: "/projects",
201
- "aria-current": nav?.active === "projects" ? "page" : void 0,
202
- children: [/* @__PURE__ */ jsx("span", {
203
- "aria-hidden": "true",
204
- children: "▦"
205
- }), " Projects"]
206
- }),
207
- nav?.projectSlug ? /* @__PURE__ */ jsxs(Fragment, { children: [
208
- /* @__PURE__ */ jsx("div", {
209
- class: "sidebar__section",
210
- children: "Project"
211
- }),
212
- /* @__PURE__ */ jsxs("a", {
213
- class: `sidebar__link ${nav.active === "builds" ? "sidebar__link--active" : ""}`,
214
- href: `/projects/${nav.projectSlug}/builds`,
215
- "aria-current": nav.active === "builds" ? "page" : void 0,
216
- children: [/* @__PURE__ */ jsx("span", {
217
- "aria-hidden": "true",
218
- children: "◧"
219
- }), " Builds"]
220
- }),
221
- /* @__PURE__ */ jsxs("a", {
222
- class: `sidebar__link ${nav.active === "jobs" ? "sidebar__link--active" : ""}`,
223
- href: `/projects/${nav.projectSlug}/jobs`,
224
- "aria-current": nav.active === "jobs" ? "page" : void 0,
225
- children: [/* @__PURE__ */ jsx("span", {
226
- "aria-hidden": "true",
227
- children: "◫"
228
- }), " Jobs"]
229
- }),
230
- /* @__PURE__ */ jsxs("a", {
231
- class: `sidebar__link ${nav.active === "labels" ? "sidebar__link--active" : ""}`,
232
- href: `/projects/${nav.projectSlug}/labels`,
233
- "aria-current": nav.active === "labels" ? "page" : void 0,
234
- children: [/* @__PURE__ */ jsx("span", {
235
- "aria-hidden": "true",
236
- children: "⌗"
237
- }), " Labels"]
238
- }),
239
- /* @__PURE__ */ jsxs("a", {
240
- class: `sidebar__link ${nav.active === "settings" ? "sidebar__link--active" : ""}`,
241
- href: `/projects/${nav.projectSlug}/settings`,
242
- "aria-current": nav.active === "settings" ? "page" : void 0,
243
- children: [/* @__PURE__ */ jsx("span", {
244
- "aria-hidden": "true",
245
- children: "⚙"
246
- }), " Settings"]
247
- })
248
- ] }) : null,
249
- /* @__PURE__ */ jsx("div", {
250
- class: "sidebar__section",
251
- children: "Resources"
252
- }),
253
- /* @__PURE__ */ jsxs("a", {
254
- class: "sidebar__link",
255
- href: "/api/v1/projects",
256
- "aria-label": "API (JSON)",
257
- children: [/* @__PURE__ */ jsx("span", {
258
- "aria-hidden": "true",
259
- children: "{} "
260
- }), " API"]
261
- })
262
- ]
263
- })
264
- });
265
- };
266
- function themeScript() {
267
- return `
268
- (function(){
269
- var cookieName='storyshelf_theme';
270
- function readCookie(n){
271
- var m=document.cookie.match(new RegExp('(?:^|; )'+n.replace(/([.$?*|{}\\[\\]\\\\/\\+^])/gu,'\\\\$1')+'=([^;]*)'));
272
- return m?decodeURIComponent(m[1]):null;
273
- }
274
- function writeCookie(n,v){
275
- document.cookie=n+'='+encodeURIComponent(v)+'; Path=/; Max-Age=31536000; SameSite=Lax';
276
- }
277
- function applyTheme(v){
278
- var html=document.documentElement;
279
- if(v==='light'||v==='dark'||v==='system'){ html.setAttribute('data-theme',v); }
280
- else { html.setAttribute('data-theme','system'); }
281
- }
282
- var initial=readCookie(cookieName);
283
- if(initial){ applyTheme(initial); }
284
- window.__storyshelfTheme={readCookie:readCookie,writeCookie:writeCookie,applyTheme:applyTheme,cookieName:cookieName};
285
- })();
286
- `.trim();
287
- }
288
- function clientScript() {
289
- return `
290
- (function(){
291
- var theme=window.__storyshelfTheme;
292
- var toggle=document.querySelector('[data-theme-toggle]');
293
- if(toggle&&theme){
294
- toggle.addEventListener('click',function(){
295
- var cur=document.documentElement.getAttribute('data-theme')||'system';
296
- var next=cur==='system'?'light':cur==='light'?'dark':'system';
297
- theme.applyTheme(next);
298
- theme.writeCookie(theme.cookieName,next);
299
- });
300
- }
301
- var menuBtn=document.querySelector('[data-sidebar-toggle]');
302
- var sidebar=document.getElementById('sidebar');
303
- if(menuBtn&&sidebar){
304
- menuBtn.addEventListener('click',function(){
305
- var open=sidebar.classList.toggle('sidebar--open');
306
- menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false');
307
- });
308
- }
309
- document.addEventListener('keydown',function(e){
310
- if(e.key==='Escape'&&sidebar&&sidebar.classList.contains('sidebar--open')){
311
- sidebar.classList.remove('sidebar--open');
312
- if(menuBtn) menuBtn.setAttribute('aria-expanded','false');
313
- menuBtn && menuBtn.focus();
314
- }
315
- });
316
- // HTMX after swap focus management
317
- document.body.addEventListener('htmx:afterSwap',function(e){
318
- var target=e.detail && e.detail.target;
319
- if(target&&target.querySelector){
320
- var focusable=target.querySelector('[autofocus], input, select, textarea, button');
321
- if(focusable) try{ focusable.focus(); }catch(_){}
322
- }
323
- });
324
- // Diff keyboard shortcuts
325
- document.addEventListener('keydown',function(e){
326
- if(e.target instanceof HTMLElement && (e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA'||e.target.isContentEditable)) return;
327
- var diffRoot=document.querySelector('[data-diff-nav]');
328
- if(!diffRoot) return;
329
- if(e.key==='ArrowLeft' || e.key==='ArrowRight'){
330
- var links=Array.from(diffRoot.querySelectorAll('[data-snapshot-link]'));
331
- if(links.length===0) return;
332
- var active=document.activeElement;
333
- var idx=links.indexOf(active);
334
- if(idx===-1){
335
- var current=diffRoot.getAttribute('data-current');
336
- idx=links.findIndex(function(a){ return a.getAttribute('data-snapshot-id')===current; });
337
- }
338
- var nextIdx=e.key==='ArrowRight' ? Math.min(links.length-1, idx+1) : Math.max(0, idx-1);
339
- if(links[nextIdx]){ e.preventDefault(); links[nextIdx].focus(); links[nextIdx].click(); }
340
- }
341
- });
342
- })();
343
- `.trim();
344
- }
345
- //#endregion
346
- export { DocumentLayout };
347
-
348
- //# sourceMappingURL=document.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"document.mjs","names":[],"sources":["../../src/ui/document.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\nimport { getStore } from \"../store.ts\";\nimport { baseStyle } from \"./styles.ts\";\nimport { DARK_THEME, LIGHT_THEME } from \"./theme.ts\";\n\n/** Rendered HTML content returned by page components. */\nexport type RenderedContent = string | Promise<string>;\n\ninterface NavConfig {\n active?: string;\n projectSlug?: string;\n projectName?: string;\n}\n\n// Hono's JSX.Element is typed as `HtmlEscapedString | Promise<...>`, so JSX-returning\n// Functions can legitimately return a promise; the rule is a false positive here.\n/** Full HTML document shell with top bar, sidebar, theme, and HTMX. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const DocumentLayout: FC<{ title: string; nav?: NavConfig; children?: unknown }> = ({\n title,\n nav,\n children,\n}) => {\n const { ui } = getStore();\n const name = ui.name ?? \"StoryShelf\";\n const light = ui.lightTheme ?? LIGHT_THEME;\n const dark = ui.darkTheme ?? DARK_THEME;\n\n return (\n <html lang=\"en\" data-theme=\"system\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"color-scheme\" content=\"light dark\" />\n {ui.favicon ? <link rel=\"icon\" href={ui.favicon} /> : null}\n <title>\n {title} · {name}\n </title>\n <style>{baseStyle(light, dark)}</style>\n <script dangerouslySetInnerHTML={{ __html: themeScript() }} />\n </head>\n <body>\n <a class=\"skip-link\" href=\"#main-content\">\n Skip to content\n </a>\n <TopBar name={name} logo={ui.logo} nav={nav} />\n <div class=\"shell\">\n <Sidebar nav={nav} />\n <main id=\"main-content\" class=\"content\" tabindex={-1}>\n {children}\n </main>\n </div>\n <script src=\"/assets/htmx.js\" />\n <script dangerouslySetInnerHTML={{ __html: clientScript() }} />\n </body>\n </html>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst TopBar: FC<{ name: string; logo?: string; nav?: NavConfig }> = ({ name, logo, nav }) => {\n return (\n <header class=\"topbar\" role=\"banner\">\n <div class=\"topbar__inner\">\n <div class=\"topbar__left\">\n <button\n class=\"topbar__menu\"\n type=\"button\"\n aria-label=\"Toggle navigation\"\n aria-expanded=\"false\"\n aria-controls=\"sidebar\"\n data-sidebar-toggle\n >\n <span aria-hidden=\"true\">☰</span>\n </button>\n <a class=\"brand\" href=\"/\">\n {logo ? (\n <img class=\"logo\" src={logo} alt={name} width=\"28\" height=\"28\" />\n ) : (\n <span class=\"brand__mark\" aria-hidden=\"true\">\n ◆\n </span>\n )}\n <span class=\"brand__name\">{name}</span>\n </a>\n {nav?.projectSlug ? (\n <nav class=\"project-crumb\" aria-label=\"Project\">\n <span class=\"project-crumb__sep\" aria-hidden=\"true\">\n /\n </span>\n <a href={`/projects/${nav.projectSlug}/builds`}>\n {nav.projectName ?? nav.projectSlug}\n </a>\n </nav>\n ) : null}\n </div>\n <div class=\"topbar__right\">\n <ThemeToggle />\n <AuthMenu />\n </div>\n </div>\n </header>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst ThemeToggle: FC = () => {\n return (\n <button class=\"topbar__theme\" type=\"button\" aria-label=\"Toggle theme\" data-theme-toggle>\n <span data-theme-icon=\"light\" aria-hidden=\"true\">\n ☀\n </span>\n <span data-theme-icon=\"dark\" aria-hidden=\"true\">\n ☾\n </span>\n <span data-theme-icon=\"system\" aria-hidden=\"true\">\n ◐\n </span>\n </button>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst AuthMenu: FC = () => {\n const { user, authEnabled } = getStore();\n if (!authEnabled) {\n return null;\n }\n if (!user) {\n return (\n <a class=\"topbar__login\" href=\"/auth/login\">\n Sign in\n </a>\n );\n }\n return (\n <div class=\"user-menu\">\n {user.avatarUrl ? (\n <img class=\"user-menu__avatar\" src={user.avatarUrl} alt=\"\" width=\"28\" height=\"28\" />\n ) : (\n <span class=\"user-menu__avatar user-menu__avatar--fallback\" aria-hidden=\"true\">\n {user.name.slice(0, 1).toUpperCase()}\n </span>\n )}\n <span class=\"user-menu__name\">{user.name}</span>\n <span class={`user-menu__role user-menu__role--${user.role}`}>{user.role}</span>\n <form method=\"post\" action=\"/auth/logout\">\n <button class=\"user-menu__logout\" type=\"submit\">\n Sign out\n </button>\n </form>\n </div>\n );\n};\n\n// eslint-disable-next-line promise-function-async -- JSX component return type\nconst Sidebar: FC<{ nav?: NavConfig }> = ({ nav }) => {\n return (\n <aside id=\"sidebar\" class=\"sidebar\" aria-label=\"Primary\">\n <nav class=\"sidebar__nav\">\n <a\n class={`sidebar__link ${nav?.active === \"projects\" ? \"sidebar__link--active\" : \"\"}`}\n href=\"/projects\"\n aria-current={nav?.active === \"projects\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">▦</span> Projects\n </a>\n {nav?.projectSlug ? (\n <>\n <div class=\"sidebar__section\">Project</div>\n <a\n class={`sidebar__link ${nav.active === \"builds\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/builds`}\n aria-current={nav.active === \"builds\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">◧</span> Builds\n </a>\n <a\n class={`sidebar__link ${nav.active === \"jobs\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/jobs`}\n aria-current={nav.active === \"jobs\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">◫</span> Jobs\n </a>\n <a\n class={`sidebar__link ${nav.active === \"labels\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/labels`}\n aria-current={nav.active === \"labels\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">⌗</span> Labels\n </a>\n <a\n class={`sidebar__link ${nav.active === \"settings\" ? \"sidebar__link--active\" : \"\"}`}\n href={`/projects/${nav.projectSlug}/settings`}\n aria-current={nav.active === \"settings\" ? \"page\" : undefined}\n >\n <span aria-hidden=\"true\">⚙</span> Settings\n </a>\n </>\n ) : null}\n <div class=\"sidebar__section\">Resources</div>\n <a class=\"sidebar__link\" href=\"/api/v1/projects\" aria-label=\"API (JSON)\">\n <span aria-hidden=\"true\">{\"{} \"}</span> API\n </a>\n </nav>\n </aside>\n );\n};\n\nfunction themeScript(): string {\n return `\n (function(){\n var cookieName='storyshelf_theme';\n function readCookie(n){\n var m=document.cookie.match(new RegExp('(?:^|; )'+n.replace(/([.$?*|{}\\\\[\\\\]\\\\\\\\/\\\\+^])/gu,'\\\\\\\\$1')+'=([^;]*)'));\n return m?decodeURIComponent(m[1]):null;\n }\n function writeCookie(n,v){\n document.cookie=n+'='+encodeURIComponent(v)+'; Path=/; Max-Age=31536000; SameSite=Lax';\n }\n function applyTheme(v){\n var html=document.documentElement;\n if(v==='light'||v==='dark'||v==='system'){ html.setAttribute('data-theme',v); }\n else { html.setAttribute('data-theme','system'); }\n }\n var initial=readCookie(cookieName);\n if(initial){ applyTheme(initial); }\n window.__storyshelfTheme={readCookie:readCookie,writeCookie:writeCookie,applyTheme:applyTheme,cookieName:cookieName};\n })();\n `.trim();\n}\n\nfunction clientScript(): string {\n return `\n (function(){\n var theme=window.__storyshelfTheme;\n var toggle=document.querySelector('[data-theme-toggle]');\n if(toggle&&theme){\n toggle.addEventListener('click',function(){\n var cur=document.documentElement.getAttribute('data-theme')||'system';\n var next=cur==='system'?'light':cur==='light'?'dark':'system';\n theme.applyTheme(next);\n theme.writeCookie(theme.cookieName,next);\n });\n }\n var menuBtn=document.querySelector('[data-sidebar-toggle]');\n var sidebar=document.getElementById('sidebar');\n if(menuBtn&&sidebar){\n menuBtn.addEventListener('click',function(){\n var open=sidebar.classList.toggle('sidebar--open');\n menuBtn.setAttribute('aria-expanded', open ? 'true' : 'false');\n });\n }\n document.addEventListener('keydown',function(e){\n if(e.key==='Escape'&&sidebar&&sidebar.classList.contains('sidebar--open')){\n sidebar.classList.remove('sidebar--open');\n if(menuBtn) menuBtn.setAttribute('aria-expanded','false');\n menuBtn && menuBtn.focus();\n }\n });\n // HTMX after swap focus management\n document.body.addEventListener('htmx:afterSwap',function(e){\n var target=e.detail && e.detail.target;\n if(target&&target.querySelector){\n var focusable=target.querySelector('[autofocus], input, select, textarea, button');\n if(focusable) try{ focusable.focus(); }catch(_){}\n }\n });\n // Diff keyboard shortcuts\n document.addEventListener('keydown',function(e){\n if(e.target instanceof HTMLElement && (e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA'||e.target.isContentEditable)) return;\n var diffRoot=document.querySelector('[data-diff-nav]');\n if(!diffRoot) return;\n if(e.key==='ArrowLeft' || e.key==='ArrowRight'){\n var links=Array.from(diffRoot.querySelectorAll('[data-snapshot-link]'));\n if(links.length===0) return;\n var active=document.activeElement;\n var idx=links.indexOf(active);\n if(idx===-1){\n var current=diffRoot.getAttribute('data-current');\n idx=links.findIndex(function(a){ return a.getAttribute('data-snapshot-id')===current; });\n }\n var nextIdx=e.key==='ArrowRight' ? Math.min(links.length-1, idx+1) : Math.max(0, idx-1);\n if(links[nextIdx]){ e.preventDefault(); links[nextIdx].focus(); links[nextIdx].click(); }\n }\n });\n })();\n `.trim();\n}\n"],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { jsx } from "hono/jsx/jsx-runtime";
5
- //#region src/ui/feedback.tsx
6
- /** Small status pill with a color tone. */
7
- const Badge = ({ tone = "neutral", children }) => {
8
- return /* @__PURE__ */ jsx("span", {
9
- class: `badge badge--${tone}`,
10
- children
11
- });
12
- };
13
- /** Map a build or snapshot status string to its badge tone. */
14
- function statusTone(status) {
15
- if (status === "approved" || status === "unchanged") return "success";
16
- if (status === "rejected" || status === "failed") return "danger";
17
- if (status === "changed" || status === "new" || status === "reviewing") return "warning";
18
- if (status === "capturing" || status === "comparing" || status === "pending") return "info";
19
- return "neutral";
20
- }
21
- //#endregion
22
- export { Badge, statusTone };
23
-
24
- //# sourceMappingURL=feedback.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"feedback.mjs","names":[],"sources":["../../src/ui/feedback.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\ntype BadgeTone = \"neutral\" | \"success\" | \"warning\" | \"danger\" | \"info\";\n\n/** Small status pill with a color tone. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Badge: FC<{ tone?: BadgeTone; children?: unknown }> = ({\n tone = \"neutral\",\n children,\n}) => {\n return <span class={`badge badge--${tone}`}>{children}</span>;\n};\n\n/** Map a build or snapshot status string to its badge tone. */\nexport function statusTone(status: string): BadgeTone {\n if (status === \"approved\" || status === \"unchanged\") {\n return \"success\";\n }\n if (status === \"rejected\" || status === \"failed\") {\n return \"danger\";\n }\n if (status === \"changed\" || status === \"new\" || status === \"reviewing\") {\n return \"warning\";\n }\n if (status === \"capturing\" || status === \"comparing\" || status === \"pending\") {\n return \"info\";\n }\n return \"neutral\";\n}\n\n/** Alert banner with an optional title. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Alert: FC<{ tone?: BadgeTone; title?: string; children?: unknown }> = ({\n tone = \"info\",\n title,\n children,\n}) => {\n return (\n <div class={`alert alert--${tone}`} role=\"alert\">\n {title ? <strong class=\"alert__title\">{title}</strong> : null}\n <div class=\"alert__body\">{children}</div>\n </div>\n );\n};\n\n/** Centered empty state with an optional call-to-action. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const EmptyState: FC<{ title: string; description?: string; action?: unknown }> = ({\n title,\n description,\n action,\n}) => {\n return (\n <div class=\"empty\">\n <h2 class=\"empty__title\">{title}</h2>\n {description ? <p class=\"empty__desc\">{description}</p> : null}\n {action ? <div class=\"empty__action\">{action}</div> : null}\n </div>\n );\n};\n\n/** Centered statistic value with a label. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Stat: FC<{ label: string; value: string | number }> = ({ label, value }) => {\n return (\n <div class=\"stat\">\n <div class=\"stat__value\">{String(value)}</div>\n <div class=\"stat__label\">{label}</div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAQA,MAAa,SAAuD,EAClE,OAAO,WACP,eACI;CACJ,OAAO,oBAAC,QAAD;EAAM,OAAO,gBAAgB;EAAS;CAAe,CAAA;AAC9D;;AAGA,SAAgB,WAAW,QAA2B;CACpD,IAAI,WAAW,cAAc,WAAW,aACtC,OAAO;CAET,IAAI,WAAW,cAAc,WAAW,UACtC,OAAO;CAET,IAAI,WAAW,aAAa,WAAW,SAAS,WAAW,aACzD,OAAO;CAET,IAAI,WAAW,eAAe,WAAW,eAAe,WAAW,WACjE,OAAO;CAET,OAAO;AACT"}
package/dist/ui/forms.mjs DELETED
@@ -1,117 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { jsx, jsxs } from "hono/jsx/jsx-runtime";
5
- //#region src/ui/forms.tsx
6
- const FieldAssistant = ({ name, error, hint }) => {
7
- if (error) return /* @__PURE__ */ jsx("p", {
8
- class: "field__error",
9
- id: `${name}-error`,
10
- role: "alert",
11
- children: error
12
- });
13
- if (hint) return /* @__PURE__ */ jsx("p", {
14
- class: "field__hint",
15
- id: `${name}-hint`,
16
- children: hint
17
- });
18
- return null;
19
- };
20
- function fieldDescribedBy(name, error, hint) {
21
- if (error) return `${name}-error`;
22
- if (hint) return `${name}-hint`;
23
- }
24
- /** Labeled text input with error and hint states. */
25
- const Field = ({ label, name, type = "text", value, placeholder, required, error, hint, autocomplete }) => {
26
- return /* @__PURE__ */ jsxs("div", {
27
- class: "field",
28
- children: [
29
- /* @__PURE__ */ jsxs("label", {
30
- class: "field__label",
31
- for: name,
32
- children: [label, required ? /* @__PURE__ */ jsx("span", {
33
- "aria-hidden": "true",
34
- children: " *"
35
- }) : null]
36
- }),
37
- /* @__PURE__ */ jsx("input", {
38
- class: `field__input ${error ? "field__input--error" : ""}`,
39
- id: name,
40
- name,
41
- type,
42
- value,
43
- placeholder,
44
- required,
45
- "aria-invalid": error ? "true" : void 0,
46
- "aria-describedby": fieldDescribedBy(name, error, hint),
47
- autocomplete
48
- }),
49
- /* @__PURE__ */ jsx(FieldAssistant, {
50
- name,
51
- error,
52
- hint
53
- })
54
- ]
55
- });
56
- };
57
- /** Labeled textarea with error and hint states. */
58
- const TextareaField = ({ label, name, value, placeholder, rows = 3, hint, error }) => {
59
- return /* @__PURE__ */ jsxs("div", {
60
- class: "field",
61
- children: [
62
- /* @__PURE__ */ jsx("label", {
63
- class: "field__label",
64
- for: name,
65
- children: label
66
- }),
67
- /* @__PURE__ */ jsx("textarea", {
68
- class: `field__input field__input--textarea ${error ? "field__input--error" : ""}`,
69
- id: name,
70
- name,
71
- placeholder,
72
- rows,
73
- "aria-invalid": error ? "true" : void 0,
74
- "aria-describedby": fieldDescribedBy(name, error, hint),
75
- children: value
76
- }),
77
- /* @__PURE__ */ jsx(FieldAssistant, {
78
- name,
79
- error,
80
- hint
81
- })
82
- ]
83
- });
84
- };
85
- /** Labeled select dropdown with an optional hint. */
86
- const SelectField = ({ label, name, value, options, hint }) => {
87
- return /* @__PURE__ */ jsxs("div", {
88
- class: "field",
89
- children: [
90
- /* @__PURE__ */ jsx("label", {
91
- class: "field__label",
92
- for: name,
93
- children: label
94
- }),
95
- /* @__PURE__ */ jsx("select", {
96
- class: "field__input",
97
- id: name,
98
- name,
99
- "aria-describedby": hint ? `${name}-hint` : void 0,
100
- children: options.map((opt) => /* @__PURE__ */ jsx("option", {
101
- value: opt.value,
102
- selected: opt.value === value,
103
- children: opt.label
104
- }))
105
- }),
106
- hint ? /* @__PURE__ */ jsx("p", {
107
- class: "field__hint",
108
- id: `${name}-hint`,
109
- children: hint
110
- }) : null
111
- ]
112
- });
113
- };
114
- //#endregion
115
- export { Field, SelectField, TextareaField };
116
-
117
- //# sourceMappingURL=forms.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"forms.mjs","names":[],"sources":["../../src/ui/forms.tsx"],"sourcesContent":["import type { FC } from \"hono/jsx\";\n\n/* eslint-disable promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString> */\n\n// eslint-disable-next-line promise-function-async -- Hono JSX components return HtmlEscapedString | Promise<HtmlEscapedString>\nconst FieldAssistant: FC<{ name: string; error: string | undefined; hint: string | undefined }> = ({\n name,\n error,\n hint,\n}) => {\n if (error) {\n return (\n <p class=\"field__error\" id={`${name}-error`} role=\"alert\">\n {error}\n </p>\n );\n }\n if (hint) {\n return (\n <p class=\"field__hint\" id={`${name}-hint`}>\n {hint}\n </p>\n );\n }\n return null;\n};\n\nfunction fieldDescribedBy(\n name: string,\n error: string | undefined,\n hint: string | undefined,\n): string | undefined {\n if (error) {\n return `${name}-error`;\n }\n if (hint) {\n return `${name}-hint`;\n }\n return undefined;\n}\n\n/** Labeled text input with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const Field: FC<{\n label: string;\n name: string;\n type?: string;\n value?: string;\n placeholder?: string;\n required?: boolean;\n error?: string;\n hint?: string;\n autocomplete?: string;\n}> = ({ label, name, type = \"text\", value, placeholder, required, error, hint, autocomplete }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n {required ? <span aria-hidden=\"true\"> *</span> : null}\n </label>\n <input\n class={`field__input ${error ? \"field__input--error\" : \"\"}`}\n id={name}\n name={name}\n type={type}\n value={value}\n placeholder={placeholder}\n required={required}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n autocomplete={autocomplete}\n />\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled textarea with error and hint states. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const TextareaField: FC<{\n label: string;\n name: string;\n value?: string;\n placeholder?: string;\n rows?: number;\n hint?: string;\n error?: string;\n}> = ({ label, name, value, placeholder, rows = 3, hint, error }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n </label>\n <textarea\n class={`field__input field__input--textarea ${error ? \"field__input--error\" : \"\"}`}\n id={name}\n name={name}\n placeholder={placeholder}\n rows={rows}\n aria-invalid={error ? \"true\" : undefined}\n aria-describedby={fieldDescribedBy(name, error, hint)}\n >\n {value}\n </textarea>\n <FieldAssistant name={name} error={error} hint={hint} />\n </div>\n );\n};\n\n/** Labeled select dropdown with an optional hint. */\n// eslint-disable-next-line promise-function-async -- JSX component return type\nexport const SelectField: FC<{\n label: string;\n name: string;\n value?: string;\n options: { value: string; label: string }[];\n hint?: string;\n}> = ({ label, name, value, options, hint }) => {\n return (\n <div class=\"field\">\n <label class=\"field__label\" for={name}>\n {label}\n </label>\n <select\n class=\"field__input\"\n id={name}\n name={name}\n aria-describedby={hint ? `${name}-hint` : undefined}\n >\n {options.map((opt) => (\n <option value={opt.value} selected={opt.value === value}>\n {opt.label}\n </option>\n ))}\n </select>\n {hint ? (\n <p class=\"field__hint\" id={`${name}-hint`}>\n {hint}\n </p>\n ) : null}\n </div>\n );\n};\n"],"mappings":";;;;;AAKA,MAAM,kBAA6F,EACjG,MACA,OACA,WACI;CACJ,IAAI,OACF,OACE,oBAAC,KAAD;EAAG,OAAM;EAAe,IAAI,GAAG,KAAK;EAAS,MAAK;EAC/C,UAAA;CACA,CAAA;CAGP,IAAI,MACF,OACE,oBAAC,KAAD;EAAG,OAAM;EAAc,IAAI,GAAG,KAAK;EAChC,UAAA;CACA,CAAA;CAGP,OAAO;AACT;AAEA,SAAS,iBACP,MACA,OACA,MACoB;CACpB,IAAI,OACF,OAAO,GAAG,KAAK;CAEjB,IAAI,MACF,OAAO,GAAG,KAAK;AAGnB;;AAIA,MAAa,SAUP,EAAE,OAAO,MAAM,OAAO,QAAQ,OAAO,aAAa,UAAU,OAAO,MAAM,mBAAmB;CAChG,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,qBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAAjC,UAAA,CACG,OACA,WAAW,oBAAC,QAAD;KAAM,eAAY;KAAO,UAAA;IAAQ,CAAA,IAAI,IAC5C;;GACP,oBAAC,SAAD;IACE,OAAO,gBAAgB,QAAQ,wBAAwB;IACvD,IAAI;IACE;IACA;IACC;IACM;IACH;IACV,gBAAc,QAAQ,SAAS,KAAA;IAC/B,oBAAkB,iBAAiB,MAAM,OAAO,IAAI;IACtC;GACf,CAAA;GACD,oBAAC,gBAAD;IAAsB;IAAa;IAAa;GAAO,CAAA;EACpD;;AAET;;AAIA,MAAa,iBAQP,EAAE,OAAO,MAAM,OAAO,aAAa,OAAO,GAAG,MAAM,YAAY;CACnE,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,oBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAC9B,UAAA;GACI,CAAA;GACP,oBAAC,YAAD;IACE,OAAO,uCAAuC,QAAQ,wBAAwB;IAC9E,IAAI;IACE;IACO;IACP;IACN,gBAAc,QAAQ,SAAS,KAAA;IAC/B,oBAAkB,iBAAiB,MAAM,OAAO,IAAI;IAEnD,UAAA;GACO,CAAA;GACV,oBAAC,gBAAD;IAAsB;IAAa;IAAa;GAAO,CAAA;EACpD;;AAET;;AAIA,MAAa,eAMP,EAAE,OAAO,MAAM,OAAO,SAAS,WAAW;CAC9C,OACE,qBAAC,OAAD;EAAK,OAAM;EAAX,UAAA;GACE,oBAAC,SAAD;IAAO,OAAM;IAAe,KAAK;IAC9B,UAAA;GACI,CAAA;GACP,oBAAC,UAAD;IACE,OAAM;IACN,IAAI;IACE;IACN,oBAAkB,OAAO,GAAG,KAAK,SAAS,KAAA;IAEzC,UAAA,QAAQ,KAAK,QACZ,oBAAC,UAAD;KAAQ,OAAO,IAAI;KAAO,UAAU,IAAI,UAAU;KAC/C,UAAA,IAAI;IACC,CAAA,CACT;GACK,CAAA;GACP,OACC,oBAAC,KAAD;IAAG,OAAM;IAAc,IAAI,GAAG,KAAK;IAChC,UAAA;GACA,CAAA,IACD;EACD;;AAET"}