@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,228 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { BuildModel } from "../models/build.mjs";
5
- import { ProjectModel } from "../models/project.mjs";
6
- import { getStore } from "../store.mjs";
7
- import { LabelModel } from "../models/label.mjs";
8
- import { DocumentLayout } from "../ui/document.mjs";
9
- import { Badge, statusTone } from "../ui/feedback.mjs";
10
- import { Fragment, jsx, jsxs } from "hono/jsx/jsx-runtime";
11
- //#region src/pages/label-detail.tsx
12
- /** Resolve a label type's `link_template` against a build, or return null. */
13
- function resolveLabelLink(template, project, build, value) {
14
- if (!template) return null;
15
- const repo = project.gitRepository ?? "";
16
- return template.replaceAll("{value}", value).replaceAll("{repo}", repo).replaceAll("{branch}", build.gitBranch);
17
- }
18
- /** Label page: every build bearing `key=value`, latest first (ADR 0013). */
19
- async function renderLabelDetailPage(slug, key, value) {
20
- const project = (await new ProjectModel(getStore().db).list()).find((item) => item.slug === slug);
21
- if (!project) return null;
22
- const [builds, labelType] = await Promise.all([new BuildModel(getStore().db).list(project.id, {
23
- labelKey: key,
24
- labelValue: value
25
- }), new LabelModel(getStore().db).getType(project.id, key)]);
26
- return /* @__PURE__ */ jsxs(DocumentLayout, {
27
- title: `${key}: ${value}`,
28
- nav: {
29
- active: "labels",
30
- projectSlug: project.slug,
31
- projectName: project.name
32
- },
33
- children: [/* @__PURE__ */ jsxs("div", {
34
- class: "page-header",
35
- children: [/* @__PURE__ */ jsx("nav", {
36
- class: "breadcrumbs",
37
- "aria-label": "Breadcrumb",
38
- children: /* @__PURE__ */ jsxs("ol", { children: [
39
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
40
- href: "/projects",
41
- children: "Projects"
42
- }) }),
43
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
44
- href: `/projects/${project.slug}/builds`,
45
- children: project.name
46
- }) }),
47
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("span", {
48
- "aria-current": "page",
49
- children: [
50
- labelType ? labelType.name : key,
51
- ": ",
52
- value
53
- ]
54
- }) })
55
- ] })
56
- }), /* @__PURE__ */ jsxs("div", {
57
- class: "page-header__row",
58
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h1", {
59
- class: "page-header__title",
60
- children: [
61
- labelType ? labelType.name : key,
62
- ": ",
63
- value
64
- ]
65
- }), /* @__PURE__ */ jsxs("p", {
66
- class: "page-header__desc",
67
- children: [
68
- /* @__PURE__ */ jsx(Badge, {
69
- tone: "neutral",
70
- children: key
71
- }),
72
- " Builds bearing this",
73
- " ",
74
- labelType ? labelType.name.toLowerCase() : "label",
75
- ", latest first."
76
- ]
77
- })] }), /* @__PURE__ */ jsx("div", {
78
- class: "page-header__actions",
79
- children: /* @__PURE__ */ jsx("a", {
80
- class: "btn btn--ghost",
81
- href: `/projects/${project.slug}/labels`,
82
- children: "All labels"
83
- })
84
- })]
85
- })]
86
- }), builds.length === 0 ? /* @__PURE__ */ jsxs("div", {
87
- class: "empty",
88
- children: [/* @__PURE__ */ jsx("h2", {
89
- class: "empty__title",
90
- children: "No builds"
91
- }), /* @__PURE__ */ jsxs("p", {
92
- class: "empty__desc",
93
- children: [
94
- "No build currently bears the label ",
95
- key,
96
- ": ",
97
- value,
98
- "."
99
- ]
100
- })]
101
- }) : /* @__PURE__ */ jsx("div", {
102
- class: "table-wrap",
103
- children: /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
104
- /* @__PURE__ */ jsx("th", { children: "Build" }),
105
- /* @__PURE__ */ jsx("th", { children: "Status" }),
106
- /* @__PURE__ */ jsx("th", { children: "Author" }),
107
- /* @__PURE__ */ jsx("th", { children: "Created" }),
108
- /* @__PURE__ */ jsx("th", {})
109
- ] }) }), /* @__PURE__ */ jsx("tbody", { children: builds.map((build) => {
110
- const link = labelType?.linkTemplate ? resolveLabelLink(labelType.linkTemplate, project, build, value) : null;
111
- return /* @__PURE__ */ jsxs("tr", { children: [
112
- /* @__PURE__ */ jsxs("td", { children: [/* @__PURE__ */ jsx("div", {
113
- style: "font-weight:600;",
114
- children: build.gitBranch
115
- }), /* @__PURE__ */ jsxs("div", {
116
- class: "field__hint",
117
- style: "font-family: ui-monospace, monospace;",
118
- children: [
119
- build.gitSha.slice(0, 7),
120
- " ",
121
- build.message ? `· ${build.message.slice(0, 60)}` : ""
122
- ]
123
- })] }),
124
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Badge, {
125
- tone: statusTone(build.status),
126
- children: build.status
127
- }) }),
128
- /* @__PURE__ */ jsxs("td", { children: [/* @__PURE__ */ jsx("div", { children: build.authorName ?? "—" }), /* @__PURE__ */ jsx("div", {
129
- class: "field__hint",
130
- children: build.authorEmail ?? ""
131
- })] }),
132
- /* @__PURE__ */ jsx("td", {
133
- class: "field__hint",
134
- children: new Date(build.createdAt).toLocaleString()
135
- }),
136
- /* @__PURE__ */ jsxs("td", {
137
- style: "white-space:nowrap;",
138
- children: [/* @__PURE__ */ jsx("a", {
139
- class: "btn btn--secondary",
140
- href: `/projects/${project.slug}/builds/${build.id}`,
141
- children: "View"
142
- }), link ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", { style: "margin-left:.35rem;" }), /* @__PURE__ */ jsx("a", {
143
- class: "btn btn--ghost",
144
- href: link,
145
- target: "_blank",
146
- rel: "noreferrer",
147
- children: "Open link"
148
- })] }) : null]
149
- })
150
- ] }, build.id);
151
- }) })] })
152
- })]
153
- });
154
- }
155
- /** Label types overview page (architecture.md `GET /projects/:slug/labels`). */
156
- async function renderLabelsPage(slug) {
157
- const project = (await new ProjectModel(getStore().db).list()).find((item) => item.slug === slug);
158
- if (!project) return null;
159
- const labelTypes = await new LabelModel(getStore().db).listTypes(project.id);
160
- return /* @__PURE__ */ jsxs(DocumentLayout, {
161
- title: `Labels · ${project.name}`,
162
- nav: {
163
- active: "labels",
164
- projectSlug: project.slug,
165
- projectName: project.name
166
- },
167
- children: [/* @__PURE__ */ jsxs("div", {
168
- class: "page-header",
169
- children: [/* @__PURE__ */ jsx("nav", {
170
- class: "breadcrumbs",
171
- "aria-label": "Breadcrumb",
172
- children: /* @__PURE__ */ jsxs("ol", { children: [
173
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
174
- href: "/projects",
175
- children: "Projects"
176
- }) }),
177
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
178
- href: `/projects/${project.slug}/builds`,
179
- children: project.name
180
- }) }),
181
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", {
182
- "aria-current": "page",
183
- children: "Labels"
184
- }) })
185
- ] })
186
- }), /* @__PURE__ */ jsx("div", {
187
- class: "page-header__row",
188
- children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", {
189
- class: "page-header__title",
190
- children: "Labels"
191
- }), /* @__PURE__ */ jsx("p", {
192
- class: "page-header__desc",
193
- children: "Typed labels attach values to builds and link out to external systems."
194
- })] })
195
- })]
196
- }), labelTypes.length === 0 ? /* @__PURE__ */ jsxs("div", {
197
- class: "empty",
198
- children: [/* @__PURE__ */ jsx("h2", {
199
- class: "empty__title",
200
- children: "No label types"
201
- }), /* @__PURE__ */ jsx("p", {
202
- class: "empty__desc",
203
- children: "No label types are configured for this project."
204
- })]
205
- }) : /* @__PURE__ */ jsx("div", {
206
- class: "table-wrap",
207
- children: /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
208
- /* @__PURE__ */ jsx("th", { children: "Key" }),
209
- /* @__PURE__ */ jsx("th", { children: "Name" }),
210
- /* @__PURE__ */ jsx("th", { children: "Template" })
211
- ] }) }), /* @__PURE__ */ jsx("tbody", { children: labelTypes.map((labelType) => /* @__PURE__ */ jsxs("tr", { children: [
212
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Badge, {
213
- tone: "neutral",
214
- children: labelType.key
215
- }) }),
216
- /* @__PURE__ */ jsx("td", { children: labelType.name }),
217
- /* @__PURE__ */ jsx("td", {
218
- style: "max-width:32ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;",
219
- children: labelType.linkTemplate ?? "—"
220
- })
221
- ] }, labelType.id)) })] })
222
- })]
223
- });
224
- }
225
- //#endregion
226
- export { renderLabelDetailPage, renderLabelsPage, resolveLabelLink };
227
-
228
- //# sourceMappingURL=label-detail.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"label-detail.mjs","names":[],"sources":["../../src/pages/label-detail.tsx"],"sourcesContent":["import type { HtmlEscapedString } from \"hono/utils/html\";\nimport { BuildModel } from \"../models/build.ts\";\nimport { LabelModel } from \"../models/label.ts\";\nimport { ProjectModel } from \"../models/project.ts\";\nimport { getStore } from \"../store.ts\";\nimport { Badge, statusTone } from \"../ui/components.tsx\";\nimport { DocumentLayout, type RenderedContent } from \"../ui/document.tsx\";\n\n/** Resolve a label type's `link_template` against a build, or return null. */\nexport function resolveLabelLink(\n template: string | null,\n project: { gitRepository: string | null },\n build: { gitBranch: string },\n value: string,\n): string | null {\n if (!template) {\n return null;\n }\n const repo = project.gitRepository ?? \"\";\n return template\n .replaceAll(\"{value}\", value)\n .replaceAll(\"{repo}\", repo)\n .replaceAll(\"{branch}\", build.gitBranch);\n}\n\n/** Label page: every build bearing `key=value`, latest first (ADR 0013). */\nexport async function renderLabelDetailPage(\n slug: string,\n key: string,\n value: string,\n): Promise<RenderedContent | null> {\n const projects = await new ProjectModel(getStore().db).list();\n const project = projects.find((item) => item.slug === slug);\n if (!project) {\n return null;\n }\n const [builds, labelType] = await Promise.all([\n new BuildModel(getStore().db).list(project.id, { labelKey: key, labelValue: value }),\n new LabelModel(getStore().db).getType(project.id, key),\n ]);\n\n return (\n <DocumentLayout\n title={`${key}: ${value}`}\n nav={{ active: \"labels\", projectSlug: project.slug, projectName: project.name }}\n >\n <div class=\"page-header\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"/projects\">Projects</a>\n </li>\n <li>\n <a href={`/projects/${project.slug}/builds`}>{project.name}</a>\n </li>\n <li>\n <span aria-current=\"page\">\n {labelType ? labelType.name : key}: {value}\n </span>\n </li>\n </ol>\n </nav>\n <div class=\"page-header__row\">\n <div>\n <h1 class=\"page-header__title\">\n {labelType ? labelType.name : key}: {value}\n </h1>\n <p class=\"page-header__desc\">\n <Badge tone=\"neutral\">{key}</Badge> Builds bearing this{\" \"}\n {labelType ? labelType.name.toLowerCase() : \"label\"}, latest first.\n </p>\n </div>\n <div class=\"page-header__actions\">\n <a class=\"btn btn--ghost\" href={`/projects/${project.slug}/labels`}>\n All labels\n </a>\n </div>\n </div>\n </div>\n\n {builds.length === 0 ? (\n <div class=\"empty\">\n <h2 class=\"empty__title\">No builds</h2>\n <p class=\"empty__desc\">\n No build currently bears the label {key}: {value}.\n </p>\n </div>\n ) : (\n <div class=\"table-wrap\">\n <table>\n <thead>\n <tr>\n <th>Build</th>\n <th>Status</th>\n <th>Author</th>\n <th>Created</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {builds.map((build): HtmlEscapedString | Promise<HtmlEscapedString> => {\n const link = labelType?.linkTemplate\n ? resolveLabelLink(labelType.linkTemplate, project, build, value)\n : null;\n return (\n <tr key={build.id}>\n <td>\n <div style=\"font-weight:600;\">{build.gitBranch}</div>\n <div class=\"field__hint\" style=\"font-family: ui-monospace, monospace;\">\n {build.gitSha.slice(0, 7)}{\" \"}\n {build.message ? `· ${build.message.slice(0, 60)}` : \"\"}\n </div>\n </td>\n <td>\n <Badge tone={statusTone(build.status)}>{build.status}</Badge>\n </td>\n <td>\n <div>{build.authorName ?? \"—\"}</div>\n <div class=\"field__hint\">{build.authorEmail ?? \"\"}</div>\n </td>\n <td class=\"field__hint\">{new Date(build.createdAt).toLocaleString()}</td>\n <td style=\"white-space:nowrap;\">\n <a\n class=\"btn btn--secondary\"\n href={`/projects/${project.slug}/builds/${build.id}`}\n >\n View\n </a>\n {link ? (\n <>\n <span style=\"margin-left:.35rem;\" />\n <a class=\"btn btn--ghost\" href={link} target=\"_blank\" rel=\"noreferrer\">\n Open link\n </a>\n </>\n ) : null}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n )}\n </DocumentLayout>\n );\n}\n\n/** Label types overview page (architecture.md `GET /projects/:slug/labels`). */\nexport async function renderLabelsPage(slug: string): Promise<RenderedContent | null> {\n const projects = await new ProjectModel(getStore().db).list();\n const project = projects.find((item) => item.slug === slug);\n if (!project) {\n return null;\n }\n const labelTypes = await new LabelModel(getStore().db).listTypes(project.id);\n\n return (\n <DocumentLayout\n title={`Labels · ${project.name}`}\n nav={{ active: \"labels\", projectSlug: project.slug, projectName: project.name }}\n >\n <div class=\"page-header\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"/projects\">Projects</a>\n </li>\n <li>\n <a href={`/projects/${project.slug}/builds`}>{project.name}</a>\n </li>\n <li>\n <span aria-current=\"page\">Labels</span>\n </li>\n </ol>\n </nav>\n <div class=\"page-header__row\">\n <div>\n <h1 class=\"page-header__title\">Labels</h1>\n <p class=\"page-header__desc\">\n Typed labels attach values to builds and link out to external systems.\n </p>\n </div>\n </div>\n </div>\n\n {labelTypes.length === 0 ? (\n <div class=\"empty\">\n <h2 class=\"empty__title\">No label types</h2>\n <p class=\"empty__desc\">No label types are configured for this project.</p>\n </div>\n ) : (\n <div class=\"table-wrap\">\n <table>\n <thead>\n <tr>\n <th>Key</th>\n <th>Name</th>\n <th>Template</th>\n </tr>\n </thead>\n <tbody>\n {labelTypes.map((labelType): HtmlEscapedString | Promise<HtmlEscapedString> => (\n <tr key={labelType.id}>\n <td>\n <Badge tone=\"neutral\">{labelType.key}</Badge>\n </td>\n <td>{labelType.name}</td>\n <td style=\"max-width:32ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;\">\n {labelType.linkTemplate ?? \"—\"}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </DocumentLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,78 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { DocumentLayout } from "../ui/document.mjs";
5
- import { jsx, jsxs } from "hono/jsx/jsx-runtime";
6
- //#region src/pages/login.tsx
7
- /** Sign-in page with password form and optional SSO button. */
8
- function renderLoginPage(state = {}) {
9
- return /* @__PURE__ */ jsx(DocumentLayout, {
10
- title: "Sign in",
11
- children: /* @__PURE__ */ jsx("div", {
12
- class: "login",
13
- style: "max-width: 360px; margin: 3rem auto;",
14
- children: /* @__PURE__ */ jsxs("div", {
15
- class: "card card--padded",
16
- children: [
17
- /* @__PURE__ */ jsx("h1", {
18
- style: "margin-top:0;",
19
- children: "Sign in"
20
- }),
21
- state.error ? /* @__PURE__ */ jsxs("div", {
22
- class: "alert alert--danger",
23
- role: "alert",
24
- children: [/* @__PURE__ */ jsx("strong", {
25
- class: "alert__title",
26
- children: "Could not sign in"
27
- }), /* @__PURE__ */ jsx("div", {
28
- class: "alert__body",
29
- children: state.error
30
- })]
31
- }) : null,
32
- /* @__PURE__ */ jsxs("form", {
33
- method: "post",
34
- action: "/auth/login",
35
- novalidate: true,
36
- children: [/* @__PURE__ */ jsxs("div", {
37
- class: "field",
38
- children: [/* @__PURE__ */ jsx("label", {
39
- class: "field__label",
40
- for: "password",
41
- children: "Password"
42
- }), /* @__PURE__ */ jsx("input", {
43
- class: "field__input",
44
- id: "password",
45
- name: "password",
46
- type: "password",
47
- required: true,
48
- autofocus: true,
49
- autocomplete: "current-password"
50
- })]
51
- }), /* @__PURE__ */ jsx("button", {
52
- class: "btn btn--primary",
53
- type: "submit",
54
- style: "width:100%; margin-top:1rem;",
55
- children: "Sign in"
56
- })]
57
- }),
58
- state.ssoUrl ? /* @__PURE__ */ jsxs("div", {
59
- style: "margin-top:1rem; text-align:center;",
60
- children: [/* @__PURE__ */ jsx("span", {
61
- style: "color: var(--color-text-secondary); font-size:.875rem;",
62
- children: "or"
63
- }), /* @__PURE__ */ jsx("a", {
64
- class: "btn btn--secondary",
65
- href: state.ssoUrl,
66
- style: "display:block; margin-top:.5rem;",
67
- children: "Sign in with SSO"
68
- })]
69
- }) : null
70
- ]
71
- })
72
- })
73
- });
74
- }
75
- //#endregion
76
- export { renderLoginPage };
77
-
78
- //# sourceMappingURL=login.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login.mjs","names":[],"sources":["../../src/pages/login.tsx"],"sourcesContent":["import { DocumentLayout, type RenderedContent } from \"../ui/document.tsx\";\n\n/** Form state for the sign-in page (SSO link and error message). */\nexport interface LoginPageState {\n ssoUrl?: string;\n error?: string;\n}\n\n/** Sign-in page with password form and optional SSO button. */\nexport function renderLoginPage(state: LoginPageState = {}): RenderedContent {\n return (\n <DocumentLayout title=\"Sign in\">\n <div class=\"login\" style=\"max-width: 360px; margin: 3rem auto;\">\n <div class=\"card card--padded\">\n <h1 style=\"margin-top:0;\">Sign in</h1>\n\n {state.error ? (\n <div class=\"alert alert--danger\" role=\"alert\">\n <strong class=\"alert__title\">Could not sign in</strong>\n <div class=\"alert__body\">{state.error}</div>\n </div>\n ) : null}\n\n <form method=\"post\" action=\"/auth/login\" novalidate>\n <div class=\"field\">\n <label class=\"field__label\" for=\"password\">\n Password\n </label>\n <input\n class=\"field__input\"\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autofocus\n autocomplete=\"current-password\"\n />\n </div>\n <button class=\"btn btn--primary\" type=\"submit\" style=\"width:100%; margin-top:1rem;\">\n Sign in\n </button>\n </form>\n\n {state.ssoUrl ? (\n <div style=\"margin-top:1rem; text-align:center;\">\n <span style=\"color: var(--color-text-secondary); font-size:.875rem;\">or</span>\n <a\n class=\"btn btn--secondary\"\n href={state.ssoUrl}\n style=\"display:block; margin-top:.5rem;\"\n >\n Sign in with SSO\n </a>\n </div>\n ) : null}\n </div>\n </div>\n </DocumentLayout>\n );\n}\n"],"mappings":";;;;;;;AASA,SAAgB,gBAAgB,QAAwB,CAAC,GAAoB;CAC3E,OACE,oBAAC,gBAAD;EAAgB,OAAM;EACpB,UAAA,oBAAC,OAAD;GAAK,OAAM;GAAQ,OAAM;GACvB,UAAA,qBAAC,OAAD;IAAK,OAAM;IAAX,UAAA;KACE,oBAAC,MAAD;MAAI,OAAM;MAAgB,UAAA;KAAW,CAAA;KAEpC,MAAM,QACL,qBAAC,OAAD;MAAK,OAAM;MAAsB,MAAK;MAAtC,UAAA,CACE,oBAAC,UAAD;OAAQ,OAAM;OAAe,UAAA;MAAyB,CAAA,GACtD,oBAAC,OAAD;OAAK,OAAM;OAAe,UAAA,MAAM;MAAW,CAAA,CACxC;KACH,CAAA,IAAA;KAEJ,qBAAC,QAAD;MAAM,QAAO;MAAO,QAAO;MAAc,YAAA;MAAzC,UAAA,CACE,qBAAC,OAAD;OAAK,OAAM;OAAX,UAAA,CACE,oBAAC,SAAD;QAAO,OAAM;QAAe,KAAI;QAAW,UAAA;OAEpC,CAAA,GACP,oBAAC,SAAD;QACE,OAAM;QACN,IAAG;QACH,MAAK;QACL,MAAK;QACL,UAAA;QACA,WAAA;QACA,cAAa;OACd,CAAA,CACE;MACL,CAAA,GAAA,oBAAC,UAAD;OAAQ,OAAM;OAAmB,MAAK;OAAS,OAAM;OAA+B,UAAA;MAE5E,CAAA,CACJ;;KAEL,MAAM,SACL,qBAAC,OAAD;MAAK,OAAM;MAAX,UAAA,CACE,oBAAC,QAAD;OAAM,OAAM;OAAyD,UAAA;MAAQ,CAAA,GAC7E,oBAAC,KAAD;OACE,OAAM;OACN,MAAM,MAAM;OACZ,OAAM;OACP,UAAA;MAEE,CAAA,CACA;KACH,CAAA,IAAA;IACD;;EACF,CAAA;CACS,CAAA;AAEpB"}
@@ -1,231 +0,0 @@
1
- import "node:path";
2
- import "node:url";
3
- import.meta.url;
4
- import { BuildModel } from "../models/build.mjs";
5
- import { ProjectModel } from "../models/project.mjs";
6
- import { getStore } from "../store.mjs";
7
- import { DocumentLayout } from "../ui/document.mjs";
8
- import { Badge, statusTone } from "../ui/feedback.mjs";
9
- import { jsx, jsxs } from "hono/jsx/jsx-runtime";
10
- //#region src/pages/project-builds.tsx
11
- /** Project builds page: filterable build history for one project. */
12
- async function renderProjectBuildsPage(slug, query = {}) {
13
- const project = (await new ProjectModel(getStore().db).list()).find((item) => item.slug === slug);
14
- if (!project) return null;
15
- const builds = await new BuildModel(getStore().db).list(project.id, {
16
- status: query.status,
17
- branch: query.branch
18
- });
19
- return /* @__PURE__ */ jsxs(DocumentLayout, {
20
- title: project.name,
21
- nav: {
22
- active: "builds",
23
- projectSlug: project.slug,
24
- projectName: project.name
25
- },
26
- children: [
27
- /* @__PURE__ */ jsxs("div", {
28
- class: "page-header",
29
- children: [/* @__PURE__ */ jsx("nav", {
30
- class: "breadcrumbs",
31
- "aria-label": "Breadcrumb",
32
- children: /* @__PURE__ */ jsxs("ol", { children: [/* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
33
- href: "/projects",
34
- children: "Projects"
35
- }) }), /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", {
36
- "aria-current": "page",
37
- children: project.name
38
- }) })] })
39
- }), /* @__PURE__ */ jsxs("div", {
40
- class: "page-header__row",
41
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", {
42
- class: "page-header__title",
43
- children: project.name
44
- }), /* @__PURE__ */ jsxs("p", {
45
- class: "page-header__desc",
46
- children: [
47
- /* @__PURE__ */ jsx("code", { children: project.slug }),
48
- " ",
49
- project.gitRepository ? `· ${project.gitRepository}` : "",
50
- " ·",
51
- " ",
52
- /* @__PURE__ */ jsx(Badge, {
53
- tone: "neutral",
54
- children: project.gitDefaultBranch
55
- })
56
- ]
57
- })] }), /* @__PURE__ */ jsxs("div", {
58
- class: "page-header__actions",
59
- children: [/* @__PURE__ */ jsx("a", {
60
- class: "btn btn--secondary",
61
- href: `/projects/${project.slug}/settings`,
62
- children: "Settings"
63
- }), /* @__PURE__ */ jsx("a", {
64
- class: "btn btn--ghost",
65
- href: `/projects/${project.slug}/builds`,
66
- children: "Refresh"
67
- })]
68
- })]
69
- })]
70
- }),
71
- /* @__PURE__ */ jsx("div", {
72
- class: "card card--padded",
73
- style: "margin-bottom:1rem;",
74
- children: /* @__PURE__ */ jsxs("form", {
75
- method: "get",
76
- action: `/projects/${project.slug}/builds`,
77
- style: "display:flex; gap:.5rem; flex-wrap:wrap; align-items:end;",
78
- children: [
79
- /* @__PURE__ */ jsxs("div", {
80
- class: "field",
81
- style: "margin:0; min-width:160px;",
82
- children: [/* @__PURE__ */ jsx("label", {
83
- class: "field__label",
84
- for: "status",
85
- children: "Status"
86
- }), /* @__PURE__ */ jsxs("select", {
87
- class: "field__input",
88
- id: "status",
89
- name: "status",
90
- children: [
91
- /* @__PURE__ */ jsx("option", {
92
- value: "",
93
- selected: !query.status,
94
- children: "All"
95
- }),
96
- /* @__PURE__ */ jsx("option", {
97
- value: "pending",
98
- selected: query.status === "pending",
99
- children: "pending"
100
- }),
101
- /* @__PURE__ */ jsx("option", {
102
- value: "reviewing",
103
- selected: query.status === "reviewing",
104
- children: "reviewing"
105
- }),
106
- /* @__PURE__ */ jsx("option", {
107
- value: "approved",
108
- selected: query.status === "approved",
109
- children: "approved"
110
- }),
111
- /* @__PURE__ */ jsx("option", {
112
- value: "rejected",
113
- selected: query.status === "rejected",
114
- children: "rejected"
115
- }),
116
- /* @__PURE__ */ jsx("option", {
117
- value: "failed",
118
- selected: query.status === "failed",
119
- children: "failed"
120
- })
121
- ]
122
- })]
123
- }),
124
- /* @__PURE__ */ jsxs("div", {
125
- class: "field",
126
- style: "margin:0; min-width:180px;",
127
- children: [/* @__PURE__ */ jsx("label", {
128
- class: "field__label",
129
- for: "branch",
130
- children: "Branch"
131
- }), /* @__PURE__ */ jsx("input", {
132
- class: "field__input",
133
- id: "branch",
134
- name: "branch",
135
- value: query.branch ?? "",
136
- placeholder: "main"
137
- })]
138
- }),
139
- /* @__PURE__ */ jsx("button", {
140
- class: "btn btn--secondary",
141
- type: "submit",
142
- children: "Filter"
143
- }),
144
- query.status || query.branch ? /* @__PURE__ */ jsx("a", {
145
- class: "btn btn--ghost",
146
- href: `/projects/${project.slug}/builds`,
147
- children: "Clear"
148
- }) : null
149
- ]
150
- })
151
- }),
152
- builds.length === 0 ? /* @__PURE__ */ jsxs("div", {
153
- class: "empty",
154
- children: [/* @__PURE__ */ jsx("h2", {
155
- class: "empty__title",
156
- children: "No builds"
157
- }), /* @__PURE__ */ jsx("p", {
158
- class: "empty__desc",
159
- children: query.status || query.branch ? "No builds match the current filter." : "Upload your first build with the CLI. Builds appear here once uploaded."
160
- })]
161
- }) : /* @__PURE__ */ jsx("div", {
162
- class: "table-wrap",
163
- children: /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
164
- /* @__PURE__ */ jsx("th", { children: "Branch / SHA" }),
165
- /* @__PURE__ */ jsx("th", { children: "Status" }),
166
- /* @__PURE__ */ jsx("th", { children: "Snapshots" }),
167
- /* @__PURE__ */ jsx("th", { children: "Author" }),
168
- /* @__PURE__ */ jsx("th", { children: "Created" }),
169
- /* @__PURE__ */ jsx("th", {})
170
- ] }) }), /* @__PURE__ */ jsx("tbody", { children: builds.map((build) => /* @__PURE__ */ jsxs("tr", { children: [
171
- /* @__PURE__ */ jsxs("td", { children: [/* @__PURE__ */ jsx("div", {
172
- style: "font-weight:600;",
173
- children: build.gitBranch
174
- }), /* @__PURE__ */ jsxs("div", {
175
- class: "field__hint",
176
- style: "font-family: ui-monospace, monospace;",
177
- children: [
178
- build.gitSha.slice(0, 7),
179
- " ",
180
- build.message ? `· ${build.message.slice(0, 60)}` : ""
181
- ]
182
- })] }),
183
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Badge, {
184
- tone: statusTone(build.status),
185
- children: build.status
186
- }) }),
187
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsxs("span", {
188
- class: "field__hint",
189
- children: [
190
- build.changedCount,
191
- " changed · ",
192
- build.approvedCount,
193
- " approved ·",
194
- " ",
195
- build.snapshotCount,
196
- " total"
197
- ]
198
- }) }),
199
- /* @__PURE__ */ jsxs("td", { children: [/* @__PURE__ */ jsx("div", { children: build.authorName ?? "—" }), /* @__PURE__ */ jsx("div", {
200
- class: "field__hint",
201
- children: build.authorEmail ?? ""
202
- })] }),
203
- /* @__PURE__ */ jsx("td", {
204
- class: "field__hint",
205
- children: new Date(build.createdAt).toLocaleString()
206
- }),
207
- /* @__PURE__ */ jsxs("td", {
208
- style: "white-space:nowrap;",
209
- children: [
210
- /* @__PURE__ */ jsx("a", {
211
- class: "btn btn--secondary",
212
- href: `/projects/${project.slug}/builds/${build.id}`,
213
- children: "View"
214
- }),
215
- /* @__PURE__ */ jsx("span", { style: "margin-left:.35rem;" }),
216
- /* @__PURE__ */ jsx("a", {
217
- class: "btn btn--ghost",
218
- href: `/projects/${project.slug}/builds/${build.id}/diff`,
219
- children: "Review"
220
- })
221
- ]
222
- })
223
- ] }, build.id)) })] })
224
- })
225
- ]
226
- });
227
- }
228
- //#endregion
229
- export { renderProjectBuildsPage };
230
-
231
- //# sourceMappingURL=project-builds.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project-builds.mjs","names":[],"sources":["../../src/pages/project-builds.tsx"],"sourcesContent":["import type { HtmlEscapedString } from \"hono/utils/html\";\nimport { BuildModel } from \"../models/build.ts\";\nimport { ProjectModel } from \"../models/project.ts\";\nimport { getStore } from \"../store.ts\";\nimport { Badge, statusTone } from \"../ui/components.tsx\";\nimport { DocumentLayout, type RenderedContent } from \"../ui/document.tsx\";\n\n/** Project builds page: filterable build history for one project. */\nexport async function renderProjectBuildsPage(\n slug: string,\n query: { status?: string; branch?: string } = {},\n): Promise<RenderedContent | null> {\n const projects = await new ProjectModel(getStore().db).list();\n const project = projects.find((item) => item.slug === slug);\n if (!project) {\n return null;\n }\n const builds = await new BuildModel(getStore().db).list(project.id, {\n status: query.status as never,\n branch: query.branch,\n });\n\n return (\n <DocumentLayout\n title={project.name}\n nav={{ active: \"builds\", projectSlug: project.slug, projectName: project.name }}\n >\n <div class=\"page-header\">\n <nav class=\"breadcrumbs\" aria-label=\"Breadcrumb\">\n <ol>\n <li>\n <a href=\"/projects\">Projects</a>\n </li>\n <li>\n <span aria-current=\"page\">{project.name}</span>\n </li>\n </ol>\n </nav>\n <div class=\"page-header__row\">\n <div>\n <h1 class=\"page-header__title\">{project.name}</h1>\n <p class=\"page-header__desc\">\n <code>{project.slug}</code>{\" \"}\n {project.gitRepository ? `· ${project.gitRepository}` : \"\"} ·{\" \"}\n <Badge tone=\"neutral\">{project.gitDefaultBranch}</Badge>\n </p>\n </div>\n <div class=\"page-header__actions\">\n <a class=\"btn btn--secondary\" href={`/projects/${project.slug}/settings`}>\n Settings\n </a>\n <a class=\"btn btn--ghost\" href={`/projects/${project.slug}/builds`}>\n Refresh\n </a>\n </div>\n </div>\n </div>\n\n <div class=\"card card--padded\" style=\"margin-bottom:1rem;\">\n <form\n method=\"get\"\n action={`/projects/${project.slug}/builds`}\n style=\"display:flex; gap:.5rem; flex-wrap:wrap; align-items:end;\"\n >\n <div class=\"field\" style=\"margin:0; min-width:160px;\">\n <label class=\"field__label\" for=\"status\">\n Status\n </label>\n <select class=\"field__input\" id=\"status\" name=\"status\">\n <option value=\"\" selected={!query.status}>\n All\n </option>\n <option value=\"pending\" selected={query.status === \"pending\"}>\n pending\n </option>\n <option value=\"reviewing\" selected={query.status === \"reviewing\"}>\n reviewing\n </option>\n <option value=\"approved\" selected={query.status === \"approved\"}>\n approved\n </option>\n <option value=\"rejected\" selected={query.status === \"rejected\"}>\n rejected\n </option>\n <option value=\"failed\" selected={query.status === \"failed\"}>\n failed\n </option>\n </select>\n </div>\n <div class=\"field\" style=\"margin:0; min-width:180px;\">\n <label class=\"field__label\" for=\"branch\">\n Branch\n </label>\n <input\n class=\"field__input\"\n id=\"branch\"\n name=\"branch\"\n value={query.branch ?? \"\"}\n placeholder=\"main\"\n />\n </div>\n <button class=\"btn btn--secondary\" type=\"submit\">\n Filter\n </button>\n {query.status || query.branch ? (\n <a class=\"btn btn--ghost\" href={`/projects/${project.slug}/builds`}>\n Clear\n </a>\n ) : null}\n </form>\n </div>\n\n {builds.length === 0 ? (\n <div class=\"empty\">\n <h2 class=\"empty__title\">No builds</h2>\n <p class=\"empty__desc\">\n {query.status || query.branch\n ? \"No builds match the current filter.\"\n : \"Upload your first build with the CLI. Builds appear here once uploaded.\"}\n </p>\n </div>\n ) : (\n <div class=\"table-wrap\">\n <table>\n <thead>\n <tr>\n <th>Branch / SHA</th>\n <th>Status</th>\n <th>Snapshots</th>\n <th>Author</th>\n <th>Created</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {builds.map((build): HtmlEscapedString | Promise<HtmlEscapedString> => (\n <tr key={build.id}>\n <td>\n <div style=\"font-weight:600;\">{build.gitBranch}</div>\n <div class=\"field__hint\" style=\"font-family: ui-monospace, monospace;\">\n {build.gitSha.slice(0, 7)}{\" \"}\n {build.message ? `· ${build.message.slice(0, 60)}` : \"\"}\n </div>\n </td>\n <td>\n <Badge tone={statusTone(build.status)}>{build.status}</Badge>\n </td>\n <td>\n <span class=\"field__hint\">\n {build.changedCount} changed · {build.approvedCount} approved ·{\" \"}\n {build.snapshotCount} total\n </span>\n </td>\n <td>\n <div>{build.authorName ?? \"—\"}</div>\n <div class=\"field__hint\">{build.authorEmail ?? \"\"}</div>\n </td>\n <td class=\"field__hint\">{new Date(build.createdAt).toLocaleString()}</td>\n <td style=\"white-space:nowrap;\">\n <a\n class=\"btn btn--secondary\"\n href={`/projects/${project.slug}/builds/${build.id}`}\n >\n View\n </a>\n <span style=\"margin-left:.35rem;\" />\n <a\n class=\"btn btn--ghost\"\n href={`/projects/${project.slug}/builds/${build.id}/diff`}\n >\n Review\n </a>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </DocumentLayout>\n );\n}\n"],"mappings":"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"}