@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
@@ -0,0 +1,147 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { injectTraceContext, withSpan } from "../tracing.mjs";
5
+ //#region src/utils/http.ts
6
+ /**
7
+ * Fetch JSON with timeout, retries, and structured errors.
8
+ *
9
+ * Retries network failures, 429, and 502/503/504 (honoring `Retry-After`);
10
+ * every other status throws {@link HttpError} immediately.
11
+ *
12
+ * @param url - Absolute request URL.
13
+ * @param options - Method, headers, JSON body, timeout, retries, logger.
14
+ * @returns The parsed JSON response body.
15
+ */
16
+ async function httpJson(url, options = {}) {
17
+ return await requestWithRetry(url, options, options.retries ?? DEFAULT_RETRIES, options.timeoutMs ?? DEFAULT_TIMEOUT_MS, doFetchJson);
18
+ }
19
+ /**
20
+ * POST/PUT plain payloads (e.g. Slack/Teams webhook cards) with the same
21
+ * timeout, retry, and `Retry-After` semantics as {@link httpJson}.
22
+ *
23
+ * @param url - Absolute request URL.
24
+ * @param options - Method, headers, text body, timeout, retries, logger.
25
+ * @returns The raw response body text.
26
+ */
27
+ async function httpText(url, options = {}) {
28
+ return await requestWithRetry(url, options, options.retries ?? DEFAULT_RETRIES, options.timeoutMs ?? DEFAULT_TIMEOUT_MS, doFetchText);
29
+ }
30
+ /** Failed HTTP response: status code plus a snippet of the response body. */
31
+ var HttpError = class extends Error {
32
+ status;
33
+ body;
34
+ headers;
35
+ constructor(status, body, headers) {
36
+ super(`HTTP ${status}: ${body}`);
37
+ this.name = "HttpError";
38
+ this.status = status;
39
+ this.body = body;
40
+ this.headers = headers ?? new Headers();
41
+ }
42
+ };
43
+ const DEFAULT_TIMEOUT_MS = 3e4;
44
+ const DEFAULT_RETRIES = 3;
45
+ const MAX_RETRY_AFTER_MS = 3e4;
46
+ const BACKOFF_BASE_MS = 1e3;
47
+ const MAX_BODY_SNIPPET = 500;
48
+ /** Whether a failure is worth retrying: network errors, 429, and 502/503/504. */
49
+ function shouldRetry(error, attempt, maxAttempts) {
50
+ if (attempt >= maxAttempts) return false;
51
+ if (!(error instanceof HttpError)) return true;
52
+ return error.status === 429 || error.status >= 502 && error.status <= 504;
53
+ }
54
+ /** Parse a Retry-After value (seconds or HTTP-date) into milliseconds. */
55
+ function parseRetryAfter(value) {
56
+ if (!value) return null;
57
+ const seconds = Number(value);
58
+ if (Number.isFinite(seconds) && seconds >= 0) return Math.min(seconds * 1e3, MAX_RETRY_AFTER_MS);
59
+ const date = Date.parse(value);
60
+ if (!Number.isNaN(date)) return Math.min(Math.max(date - Date.now(), 0), MAX_RETRY_AFTER_MS);
61
+ return null;
62
+ }
63
+ /** Delay before the next attempt: Retry-After when present, else 1s/2s/4s. */
64
+ function retryDelayMs(error, attempt) {
65
+ if (error instanceof HttpError) {
66
+ const retryAfter = parseRetryAfter(error.headers.get("retry-after"));
67
+ if (retryAfter !== null) return retryAfter;
68
+ }
69
+ return Math.min(BACKOFF_BASE_MS * 2 ** (attempt - 1), MAX_RETRY_AFTER_MS);
70
+ }
71
+ /** Sleep helper for retry backoff. */
72
+ async function sleep(ms) {
73
+ await new Promise((resolve) => {
74
+ setTimeout(resolve, ms);
75
+ });
76
+ }
77
+ async function requestWithRetry(url, options, maxAttempts, timeoutMs, perform) {
78
+ return await withSpan("http.client", async (span) => {
79
+ for (let attempt = 1;; attempt += 1) try {
80
+ return await perform(url, options, timeoutMs);
81
+ } catch (error) {
82
+ span.recordException(error instanceof Error ? error : String(error));
83
+ if (!shouldRetry(error, attempt, maxAttempts)) throw error;
84
+ span.setAttribute("http.retry.count", attempt);
85
+ await backoff(error, attempt, url, options.logger);
86
+ }
87
+ }, {
88
+ "http.request.method": options.method ?? "GET",
89
+ "url.full": redactUrl(url)
90
+ });
91
+ }
92
+ /** Strip the query string (tokens, signatures) from a URL for span attributes. */
93
+ function redactUrl(url) {
94
+ const query = url.indexOf("?");
95
+ return query === -1 ? url : url.slice(0, query);
96
+ }
97
+ async function backoff(error, attempt, url, logger) {
98
+ const delay = retryDelayMs(error, attempt);
99
+ logger?.warn({
100
+ url,
101
+ attempt,
102
+ delayMs: delay
103
+ }, "http request failed, retrying");
104
+ await sleep(delay);
105
+ }
106
+ function buildRequest(options) {
107
+ const headers = { ...options.headers };
108
+ let body;
109
+ if (options.json !== void 0) {
110
+ headers["content-type"] = "application/json";
111
+ body = JSON.stringify(options.json);
112
+ }
113
+ return {
114
+ headers,
115
+ body,
116
+ method: options.method ?? "GET"
117
+ };
118
+ }
119
+ async function doFetchJson(url, options, timeoutMs) {
120
+ return await (await doFetchResponse(url, options, timeoutMs)).json();
121
+ }
122
+ async function doFetchText(url, options, timeoutMs) {
123
+ return await (await doFetchResponse(url, options, timeoutMs)).text();
124
+ }
125
+ async function doFetchResponse(url, options, timeoutMs) {
126
+ const request = buildRequest(options);
127
+ injectTraceContext(request.headers);
128
+ options.logger?.debug({
129
+ url,
130
+ method: request.method
131
+ }, "http request");
132
+ const response = await fetch(url, {
133
+ method: request.method,
134
+ headers: request.headers,
135
+ body: request.body,
136
+ signal: AbortSignal.timeout(timeoutMs)
137
+ });
138
+ if (!response.ok) {
139
+ const text = await response.text();
140
+ throw new HttpError(response.status, text.slice(0, MAX_BODY_SNIPPET), response.headers);
141
+ }
142
+ return response;
143
+ }
144
+ //#endregion
145
+ export { HttpError, httpJson, httpText };
146
+
147
+ //# sourceMappingURL=http.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.mjs","names":[],"sources":["../../src/utils/http.ts"],"sourcesContent":["import type { Logger } from \"../logger.ts\";\nimport { injectTraceContext, withSpan } from \"../tracing.ts\";\n\n/**\n * Fetch JSON with timeout, retries, and structured errors.\n *\n * Retries network failures, 429, and 502/503/504 (honoring `Retry-After`);\n * every other status throws {@link HttpError} immediately.\n *\n * @param url - Absolute request URL.\n * @param options - Method, headers, JSON body, timeout, retries, logger.\n * @returns The parsed JSON response body.\n */\nexport async function httpJson<T>(url: string, options: HttpRequestOptions = {}): Promise<T> {\n return await requestWithRetry<T>(\n url,\n options,\n options.retries ?? DEFAULT_RETRIES,\n options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n doFetchJson,\n );\n}\n\n/**\n * POST/PUT plain payloads (e.g. Slack/Teams webhook cards) with the same\n * timeout, retry, and `Retry-After` semantics as {@link httpJson}.\n *\n * @param url - Absolute request URL.\n * @param options - Method, headers, text body, timeout, retries, logger.\n * @returns The raw response body text.\n */\nexport async function httpText(url: string, options: HttpTextOptions = {}): Promise<string> {\n return await requestWithRetry<string>(\n url,\n options,\n options.retries ?? DEFAULT_RETRIES,\n options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n doFetchText,\n );\n}\n\n/** Failed HTTP response: status code plus a snippet of the response body. */\nexport class HttpError extends Error {\n readonly status: number;\n readonly body: string;\n readonly headers: Headers;\n\n constructor(status: number, body: string, headers?: Headers) {\n super(`HTTP ${status}: ${body}`);\n this.name = \"HttpError\";\n this.status = status;\n this.body = body;\n this.headers = headers ?? new Headers();\n }\n}\n\n/** Options for {@link httpJson}. */\nexport interface HttpRequestOptions {\n method?: string;\n headers?: Record<string, string>;\n /** Body serialized as JSON with a `content-type` header. */\n json?: unknown;\n /** Per-attempt timeout in milliseconds (default 30s). */\n timeoutMs?: number;\n /** Total attempts including the first (default 3). */\n retries?: number;\n logger?: Logger;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Options for {@link httpText}. */\nexport interface HttpTextOptions {\n method?: string;\n headers?: Record<string, string>;\n /** Body serialized as JSON with a `content-type` header. */\n json?: unknown;\n /** Per-attempt timeout in milliseconds (default 30s). */\n timeoutMs?: number;\n /** Total attempts including the first (default 3). */\n retries?: number;\n logger?: Logger;\n}\nconst DEFAULT_RETRIES = 3;\nconst MAX_RETRY_AFTER_MS = 30_000;\nconst BACKOFF_BASE_MS = 1000;\nconst MAX_BODY_SNIPPET = 500;\n\n/** Whether a failure is worth retrying: network errors, 429, and 502/503/504. */\nfunction shouldRetry(error: unknown, attempt: number, maxAttempts: number): boolean {\n if (attempt >= maxAttempts) {\n return false;\n }\n if (!(error instanceof HttpError)) {\n return true;\n }\n return error.status === 429 || (error.status >= 502 && error.status <= 504);\n}\n\n/** Parse a Retry-After value (seconds or HTTP-date) into milliseconds. */\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) {\n return null;\n }\n const seconds = Number(value);\n if (Number.isFinite(seconds) && seconds >= 0) {\n return Math.min(seconds * 1000, MAX_RETRY_AFTER_MS);\n }\n const date = Date.parse(value);\n if (!Number.isNaN(date)) {\n return Math.min(Math.max(date - Date.now(), 0), MAX_RETRY_AFTER_MS);\n }\n return null;\n}\n\n/** Delay before the next attempt: Retry-After when present, else 1s/2s/4s. */\nfunction retryDelayMs(error: unknown, attempt: number): number {\n if (error instanceof HttpError) {\n const retryAfter = parseRetryAfter(error.headers.get(\"retry-after\"));\n if (retryAfter !== null) {\n return retryAfter;\n }\n }\n return Math.min(BACKOFF_BASE_MS * 2 ** (attempt - 1), MAX_RETRY_AFTER_MS);\n}\n\n/** Sleep helper for retry backoff. */\nasync function sleep(ms: number): Promise<void> {\n await new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/* oxlint-disable eslint/no-await-in-loop -- retry attempts run sequentially by design */\nasync function requestWithRetry<T>(\n url: string,\n options: HttpRequestOptions,\n maxAttempts: number,\n timeoutMs: number,\n perform: (url: string, options: HttpRequestOptions, timeoutMs: number) => Promise<T>,\n): Promise<T> {\n return await withSpan(\n \"http.client\",\n async (span) => {\n for (let attempt = 1; ; attempt += 1) {\n try {\n return await perform(url, options, timeoutMs);\n } catch (error) {\n span.recordException(error instanceof Error ? error : String(error));\n if (!shouldRetry(error, attempt, maxAttempts)) {\n throw error;\n }\n span.setAttribute(\"http.retry.count\", attempt);\n await backoff(error, attempt, url, options.logger);\n }\n }\n },\n { \"http.request.method\": options.method ?? \"GET\", \"url.full\": redactUrl(url) },\n );\n}\n/* oxlint-enable eslint/no-await-in-loop */\n\n/** Strip the query string (tokens, signatures) from a URL for span attributes. */\nfunction redactUrl(url: string): string {\n const query = url.indexOf(\"?\");\n return query === -1 ? url : url.slice(0, query);\n}\n\nasync function backoff(\n error: unknown,\n attempt: number,\n url: string,\n logger?: Logger,\n): Promise<void> {\n const delay = retryDelayMs(error, attempt);\n logger?.warn({ url, attempt, delayMs: delay }, \"http request failed, retrying\");\n await sleep(delay);\n}\n\nfunction buildRequest(options: HttpRequestOptions): {\n headers: Record<string, string>;\n body: string | undefined;\n method: string;\n} {\n const headers: Record<string, string> = { ...options.headers };\n let body: string | undefined;\n if (options.json !== undefined) {\n headers[\"content-type\"] = \"application/json\";\n body = JSON.stringify(options.json);\n }\n return { headers, body, method: options.method ?? \"GET\" };\n}\n\nasync function doFetchJson<T>(\n url: string,\n options: HttpRequestOptions,\n timeoutMs: number,\n): Promise<T> {\n const response = await doFetchResponse(url, options, timeoutMs);\n return (await response.json()) as T;\n}\n\nasync function doFetchText(\n url: string,\n options: HttpRequestOptions,\n timeoutMs: number,\n): Promise<string> {\n const response = await doFetchResponse(url, options, timeoutMs);\n return await response.text();\n}\n\nasync function doFetchResponse(\n url: string,\n options: HttpRequestOptions,\n timeoutMs: number,\n): Promise<Response> {\n const request = buildRequest(options);\n injectTraceContext(request.headers);\n options.logger?.debug({ url, method: request.method }, \"http request\");\n const response = await fetch(url, {\n method: request.method,\n headers: request.headers,\n body: request.body,\n signal: AbortSignal.timeout(timeoutMs),\n });\n if (!response.ok) {\n const text = await response.text();\n throw new HttpError(response.status, text.slice(0, MAX_BODY_SNIPPET), response.headers);\n }\n return response;\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ //#region src/utils/mime.d.ts
4
+ /** Shared MIME types for storybook static serving. */
5
+ declare const MIME_TYPES: Record<string, string>;
6
+ declare function mimeFor(filePath: string): string;
7
+ //#endregion
8
+ export { MIME_TYPES, mimeFor };
9
+ //# sourceMappingURL=mime.d.mts.map
@@ -0,0 +1,33 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ //#region src/utils/mime.ts
5
+ /** Shared MIME types for storybook static serving. */
6
+ const MIME_TYPES = {
7
+ ".css": "text/css; charset=utf-8",
8
+ ".html": "text/html; charset=utf-8",
9
+ ".htm": "text/html; charset=utf-8",
10
+ ".ico": "image/x-icon",
11
+ ".jpeg": "image/jpeg",
12
+ ".jpg": "image/jpeg",
13
+ ".js": "application/javascript",
14
+ ".json": "application/json; charset=utf-8",
15
+ ".map": "application/json; charset=utf-8",
16
+ ".mjs": "application/javascript",
17
+ ".png": "image/png",
18
+ ".svg": "image/svg+xml",
19
+ ".webp": "image/webp",
20
+ ".woff": "font/woff",
21
+ ".woff2": "font/woff2",
22
+ ".ttf": "font/ttf",
23
+ ".wasm": "application/wasm",
24
+ ".gif": "image/gif"
25
+ };
26
+ function mimeFor(filePath) {
27
+ const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
28
+ return MIME_TYPES[ext] ?? "application/octet-stream";
29
+ }
30
+ //#endregion
31
+ export { MIME_TYPES, mimeFor };
32
+
33
+ //# sourceMappingURL=mime.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.mjs","names":[],"sources":["../../src/utils/mime.ts"],"sourcesContent":["/** Shared MIME types for storybook static serving. */\nexport const MIME_TYPES: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".htm\": \"text/html; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".jpeg\": \"image/jpeg\",\n \".jpg\": \"image/jpeg\",\n \".js\": \"application/javascript\",\n \".json\": \"application/json; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n \".mjs\": \"application/javascript\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n \".webp\": \"image/webp\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".wasm\": \"application/wasm\",\n \".gif\": \"image/gif\",\n};\n\nexport function mimeFor(filePath: string): string {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n return MIME_TYPES[ext] ?? \"application/octet-stream\";\n}\n"],"mappings":";;;;;AACA,MAAa,aAAqC;CAChD,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,OAAO;CACP,SAAS;CACT,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,SAAS;CACT,UAAU;CACV,QAAQ;CACR,SAAS;CACT,QAAQ;AACV;AAEA,SAAgB,QAAQ,UAA0B;CAChD,MAAM,MAAM,SAAS,MAAM,SAAS,YAAY,GAAG,CAAC,CAAC,CAAC,YAAY;CAClE,OAAO,WAAW,QAAQ;AAC5B"}
@@ -0,0 +1,12 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ //#region src/utils/path-security.d.ts
4
+ /** Whether a path segment is safe (no traversal). */
5
+ declare function isSafeSegment(segment: string): boolean;
6
+ /** Whether joining root with candidate stays inside root (no traversal). */
7
+ declare function isPathSafe(root: string, candidate: string): boolean;
8
+ /** Check if a path built from root + entry would escape root (for zip extraction). */
9
+ declare function isBlockedTarget(root: string, entryPath: string): boolean;
10
+ //#endregion
11
+ export { isBlockedTarget, isPathSafe, isSafeSegment };
12
+ //# sourceMappingURL=path-security.d.mts.map
@@ -0,0 +1,24 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { join, normalize, sep } from "node:path";
5
+ //#region src/utils/path-security.ts
6
+ /** Whether a path segment is safe (no traversal). */
7
+ function isSafeSegment(segment) {
8
+ return segment !== ".." && !segment.startsWith("/") && !segment.includes("\\") && !segment.includes("..");
9
+ }
10
+ /** Whether joining root with candidate stays inside root (no traversal). */
11
+ function isPathSafe(root, candidate) {
12
+ const normalizedRoot = normalize(root);
13
+ const normalizedCandidate = normalize(candidate);
14
+ return normalizedCandidate === normalizedRoot || normalizedCandidate.startsWith(normalizedRoot + sep) || normalizedCandidate.startsWith(`${normalizedRoot}/`);
15
+ }
16
+ /** Check if a path built from root + entry would escape root (for zip extraction). */
17
+ function isBlockedTarget(root, entryPath) {
18
+ const target = normalize(join(root, entryPath));
19
+ return target !== root && !target.startsWith(normalize(root) + sep);
20
+ }
21
+ //#endregion
22
+ export { isBlockedTarget, isPathSafe, isSafeSegment };
23
+
24
+ //# sourceMappingURL=path-security.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-security.mjs","names":[],"sources":["../../src/utils/path-security.ts"],"sourcesContent":["import { join, normalize, sep } from \"node:path\";\n\n/** Whether a path segment is safe (no traversal). */\nexport function isSafeSegment(segment: string): boolean {\n return (\n segment !== \"..\" &&\n !segment.startsWith(\"/\") &&\n !segment.includes(\"\\\\\") &&\n !segment.includes(\"..\")\n );\n}\n\n/** Whether joining root with candidate stays inside root (no traversal). */\nexport function isPathSafe(root: string, candidate: string): boolean {\n const normalizedRoot = normalize(root);\n const normalizedCandidate = normalize(candidate);\n return (\n normalizedCandidate === normalizedRoot ||\n normalizedCandidate.startsWith(normalizedRoot + sep) ||\n normalizedCandidate.startsWith(`${normalizedRoot}/`)\n );\n}\n\n/** Check if a path built from root + entry would escape root (for zip extraction). */\nexport function isBlockedTarget(root: string, entryPath: string): boolean {\n const target = normalize(join(root, entryPath));\n return target !== root && !target.startsWith(normalize(root) + sep);\n}\n"],"mappings":";;;;;;AAGA,SAAgB,cAAc,SAA0B;CACtD,OACE,YAAY,QACZ,CAAC,QAAQ,WAAW,GAAG,KACvB,CAAC,QAAQ,SAAS,IAAI,KACtB,CAAC,QAAQ,SAAS,IAAI;AAE1B;;AAGA,SAAgB,WAAW,MAAc,WAA4B;CACnE,MAAM,iBAAiB,UAAU,IAAI;CACrC,MAAM,sBAAsB,UAAU,SAAS;CAC/C,OACE,wBAAwB,kBACxB,oBAAoB,WAAW,iBAAiB,GAAG,KACnD,oBAAoB,WAAW,GAAG,eAAe,EAAE;AAEvD;;AAGA,SAAgB,gBAAgB,MAAc,WAA4B;CACxE,MAAM,SAAS,UAAU,KAAK,MAAM,SAAS,CAAC;CAC9C,OAAO,WAAW,QAAQ,CAAC,OAAO,WAAW,UAAU,IAAI,IAAI,GAAG;AACpE"}
@@ -0,0 +1,17 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ //#region src/utils/redact.d.ts
4
+ /**
5
+ * Secret redaction for adapter errors, health details, and logs.
6
+ *
7
+ * Adapter-thrown messages routinely embed connection strings and tokens.
8
+ * Every surface that exposes adapter text (503 gate, health report, error
9
+ * logs) must pass through here before truncation or transport.
10
+ */
11
+ /** Replace embedded secrets with `[redacted]`. Never throws on weird input. */
12
+ declare function redactSecrets(text: string): string;
13
+ /** Redact secrets, then truncate to `maxLength`. */
14
+ declare function sanitizeErrorText(text: string, maxLength: number): string;
15
+ //#endregion
16
+ export { redactSecrets, sanitizeErrorText };
17
+ //# sourceMappingURL=redact.d.mts.map
@@ -0,0 +1,42 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ //#region src/utils/redact.ts
5
+ /**
6
+ * Secret redaction for adapter errors, health details, and logs.
7
+ *
8
+ * Adapter-thrown messages routinely embed connection strings and tokens.
9
+ * Every surface that exposes adapter text (503 gate, health report, error
10
+ * logs) must pass through here before truncation or transport.
11
+ */
12
+ const SECRET_PATTERNS = [
13
+ /(:\/\/)[^/\s:]+:[^/\s@]+(?=@)/u,
14
+ /([?&#](?:token|secret|password|api[_-]?key|auth[_-]?token|access[_-]?key)=)[^&#\s]*/giu,
15
+ /((?:password|passwd|secret|token|api[_-]?key|auth[_-]?token|client[_-]?secret|access[_-]?key|private[_-]?key)\s*[:=]\s*['"]?)[^\s'";,[\]&]+/giu,
16
+ /AKIA[0-9A-Z]{16}/gu,
17
+ /gh[pous]_[A-Za-z0-9_]+/gu,
18
+ /github_pat_[A-Za-z0-9_]+/gu,
19
+ /xox[bpasr]-[A-Za-z0-9-]+/gu,
20
+ /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu
21
+ ];
22
+ /** Replace embedded secrets with `[redacted]`. Never throws on weird input. */
23
+ function redactSecrets(text) {
24
+ let redacted = text;
25
+ for (const pattern of SECRET_PATTERNS) {
26
+ pattern.lastIndex = 0;
27
+ redacted = redacted.replace(pattern, (...args) => {
28
+ const group = args[1];
29
+ return typeof group === "string" ? `${group}[redacted]` : "[redacted]";
30
+ });
31
+ }
32
+ return redacted;
33
+ }
34
+ /** Redact secrets, then truncate to `maxLength`. */
35
+ function sanitizeErrorText(text, maxLength) {
36
+ const redacted = redactSecrets(text);
37
+ return redacted.length > maxLength ? redacted.slice(0, maxLength) : redacted;
38
+ }
39
+ //#endregion
40
+ export { redactSecrets, sanitizeErrorText };
41
+
42
+ //# sourceMappingURL=redact.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.mjs","names":[],"sources":["../../src/utils/redact.ts"],"sourcesContent":["/**\n * Secret redaction for adapter errors, health details, and logs.\n *\n * Adapter-thrown messages routinely embed connection strings and tokens.\n * Every surface that exposes adapter text (503 gate, health report, error\n * logs) must pass through here before truncation or transport.\n */\n\nconst SECRET_PATTERNS: RegExp[] = [\n /(:\\/\\/)[^/\\s:]+:[^/\\s@]+(?=@)/u,\n /([?&#](?:token|secret|password|api[_-]?key|auth[_-]?token|access[_-]?key)=)[^&#\\s]*/giu,\n /((?:password|passwd|secret|token|api[_-]?key|auth[_-]?token|client[_-]?secret|access[_-]?key|private[_-]?key)\\s*[:=]\\s*['\"]?)[^\\s'\";,[\\]&]+/giu,\n /AKIA[0-9A-Z]{16}/gu,\n /gh[pous]_[A-Za-z0-9_]+/gu,\n /github_pat_[A-Za-z0-9_]+/gu,\n /xox[bpasr]-[A-Za-z0-9-]+/gu,\n /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*?-----END [A-Z ]*PRIVATE KEY-----/gu,\n];\n\n/** Replace embedded secrets with `[redacted]`. Never throws on weird input. */\nexport function redactSecrets(text: string): string {\n let redacted = text;\n for (const pattern of SECRET_PATTERNS) {\n pattern.lastIndex = 0;\n redacted = redacted.replace(pattern, (...args: unknown[]) => {\n const group = args[1];\n return typeof group === \"string\" ? `${group}[redacted]` : \"[redacted]\";\n });\n }\n return redacted;\n}\n\n/** Redact secrets, then truncate to `maxLength`. */\nexport function sanitizeErrorText(text: string, maxLength: number): string {\n const redacted = redactSecrets(text);\n return redacted.length > maxLength ? redacted.slice(0, maxLength) : redacted;\n}\n"],"mappings":";;;;;;;;;;;AAQA,MAAM,kBAA4B;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,SAAgB,cAAc,MAAsB;CAClD,IAAI,WAAW;CACf,KAAK,MAAM,WAAW,iBAAiB;EACrC,QAAQ,YAAY;EACpB,WAAW,SAAS,QAAQ,UAAU,GAAG,SAAoB;GAC3D,MAAM,QAAQ,KAAK;GACnB,OAAO,OAAO,UAAU,WAAW,GAAG,MAAM,cAAc;EAC5D,CAAC;CACH;CACA,OAAO;AACT;;AAGA,SAAgB,kBAAkB,MAAc,WAA2B;CACzE,MAAM,WAAW,cAAc,IAAI;CACnC,OAAO,SAAS,SAAS,YAAY,SAAS,MAAM,GAAG,SAAS,IAAI;AACtE"}
@@ -0,0 +1,19 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ //#region src/utils/timing.d.ts
4
+ /** Aggregated durations for one scope (family/phase name → total ms). */
5
+ type TimingMap = Record<string, number>;
6
+ /** Run `fn` with a fresh timing scope, returning its result and aggregates. */
7
+ declare function runWithTimings<T>(fn: () => T | Promise<T>): Promise<{
8
+ result: T;
9
+ timings: TimingMap;
10
+ }>;
11
+ /** Add `durationMs` to `name` in the active scope (no-op when scopeless). */
12
+ declare function addTiming(name: string, durationMs: number): void;
13
+ /** Run `fn`, recording its wall duration under `name` in the active scope. */
14
+ declare function timed<T>(name: string, fn: () => T | Promise<T>): Promise<T>;
15
+ /** Copy of aggregates with whole-millisecond values for logs and headers. */
16
+ declare function roundedTimings(timings: TimingMap): TimingMap;
17
+ //#endregion
18
+ export { TimingMap, addTiming, roundedTimings, runWithTimings, timed };
19
+ //# sourceMappingURL=timing.d.mts.map
@@ -0,0 +1,46 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { AsyncLocalStorage } from "node:async_hooks";
5
+ //#region src/utils/timing.ts
6
+ /**
7
+ * Per-scope timing recorder: aggregate millisecond sums under shared names.
8
+ *
9
+ * Framework- and telemetry-free (ALS + numbers only) so any host — the Hono
10
+ * app, the remote worker, or a third-party server — can open a scope. The
11
+ * app folds request scopes into `Server-Timing`; background scopes surface
12
+ * as log lines and attempt history. Without an open scope every call is a
13
+ * cheap no-op, keeping unit tests and sleeping workers silent.
14
+ */
15
+ const scopes = new AsyncLocalStorage();
16
+ /** Run `fn` with a fresh timing scope, returning its result and aggregates. */
17
+ async function runWithTimings(fn) {
18
+ const timings = {};
19
+ return {
20
+ result: await scopes.run(timings, fn),
21
+ timings
22
+ };
23
+ }
24
+ /** Add `durationMs` to `name` in the active scope (no-op when scopeless). */
25
+ function addTiming(name, durationMs) {
26
+ const timings = scopes.getStore();
27
+ if (!timings) return;
28
+ timings[name] = (timings[name] ?? 0) + durationMs;
29
+ }
30
+ /** Run `fn`, recording its wall duration under `name` in the active scope. */
31
+ async function timed(name, fn) {
32
+ const started = performance.now();
33
+ try {
34
+ return await fn();
35
+ } finally {
36
+ addTiming(name, performance.now() - started);
37
+ }
38
+ }
39
+ /** Copy of aggregates with whole-millisecond values for logs and headers. */
40
+ function roundedTimings(timings) {
41
+ return Object.fromEntries(Object.entries(timings).map(([name, ms]) => [name, Math.round(ms)]));
42
+ }
43
+ //#endregion
44
+ export { addTiming, roundedTimings, runWithTimings, timed };
45
+
46
+ //# sourceMappingURL=timing.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timing.mjs","names":[],"sources":["../../src/utils/timing.ts"],"sourcesContent":["/**\n * Per-scope timing recorder: aggregate millisecond sums under shared names.\n *\n * Framework- and telemetry-free (ALS + numbers only) so any host — the Hono\n * app, the remote worker, or a third-party server — can open a scope. The\n * app folds request scopes into `Server-Timing`; background scopes surface\n * as log lines and attempt history. Without an open scope every call is a\n * cheap no-op, keeping unit tests and sleeping workers silent.\n */\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n/** Aggregated durations for one scope (family/phase name → total ms). */\nexport type TimingMap = Record<string, number>;\n\nconst scopes = new AsyncLocalStorage<TimingMap>();\n\n/** Run `fn` with a fresh timing scope, returning its result and aggregates. */\nexport async function runWithTimings<T>(\n fn: () => T | Promise<T>,\n): Promise<{ result: T; timings: TimingMap }> {\n const timings: TimingMap = {};\n const result = await scopes.run(timings, fn);\n return { result, timings };\n}\n\n/** Add `durationMs` to `name` in the active scope (no-op when scopeless). */\nexport function addTiming(name: string, durationMs: number): void {\n const timings = scopes.getStore();\n if (!timings) {\n return;\n }\n timings[name] = (timings[name] ?? 0) + durationMs;\n}\n\n/** Run `fn`, recording its wall duration under `name` in the active scope. */\nexport async function timed<T>(name: string, fn: () => T | Promise<T>): Promise<T> {\n const started = performance.now();\n try {\n return await fn();\n } finally {\n addTiming(name, performance.now() - started);\n }\n}\n\n/** Copy of aggregates with whole-millisecond values for logs and headers. */\nexport function roundedTimings(timings: TimingMap): TimingMap {\n return Object.fromEntries(Object.entries(timings).map(([name, ms]) => [name, Math.round(ms)]));\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,MAAM,SAAS,IAAI,kBAA6B;;AAGhD,eAAsB,eACpB,IAC4C;CAC5C,MAAM,UAAqB,CAAC;CAE5B,OAAO;EAAE,QAAA,MADY,OAAO,IAAI,SAAS,EAAE;EAC1B;CAAQ;AAC3B;;AAGA,SAAgB,UAAU,MAAc,YAA0B;CAChE,MAAM,UAAU,OAAO,SAAS;CAChC,IAAI,CAAC,SACH;CAEF,QAAQ,SAAS,QAAQ,SAAS,KAAK;AACzC;;AAGA,eAAsB,MAAS,MAAc,IAAsC;CACjF,MAAM,UAAU,YAAY,IAAI;CAChC,IAAI;EACF,OAAO,MAAM,GAAG;CAClB,UAAU;EACR,UAAU,MAAM,YAAY,IAAI,IAAI,OAAO;CAC7C;AACF;;AAGA,SAAgB,eAAe,SAA+B;CAC5D,OAAO,OAAO,YAAY,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC;AAC/F"}
@@ -0,0 +1,10 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ //#region src/utils/ulid.d.ts
4
+ /** Generate a sortable, collision-resistant ULID. */
5
+ declare function ulid(): string;
6
+ /** Convert a name to a URL-safe slug of at most 63 characters. */
7
+ declare function slugify(value: string): string;
8
+ //#endregion
9
+ export { slugify, ulid };
10
+ //# sourceMappingURL=ulid.d.mts.map
@@ -3,6 +3,14 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { randomBytes } from "node:crypto";
5
5
  //#region src/utils/ulid.ts
6
+ /** Generate a sortable, collision-resistant ULID. */
7
+ function ulid() {
8
+ return encodeTime(Date.now()) + encodeRandom(randomBytes(10));
9
+ }
10
+ /** Convert a name to a URL-safe slug of at most 63 characters. */
11
+ function slugify(value) {
12
+ return value.toLowerCase().replaceAll(/[^a-z0-9]+/gu, "-").replaceAll(/^-+|-+$/gu, "").slice(0, 63);
13
+ }
6
14
  const CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
7
15
  function encodeTime(time) {
8
16
  let out = "";
@@ -29,14 +37,6 @@ function encodeRandom(bytes) {
29
37
  if (bits > 0) out += CROCKFORD.charAt(buffer << 5 - bits & 31);
30
38
  return out;
31
39
  }
32
- /** Generate a sortable, collision-resistant ULID. */
33
- function ulid() {
34
- return encodeTime(Date.now()) + encodeRandom(randomBytes(10));
35
- }
36
- /** Convert a name to a URL-safe slug of at most 63 characters. */
37
- function slugify(value) {
38
- return value.toLowerCase().replaceAll(/[^a-z0-9]+/gu, "-").replaceAll(/^-+|-+$/gu, "").slice(0, 63);
39
- }
40
40
  //#endregion
41
41
  export { slugify, ulid };
42
42
 
@@ -1 +1 @@
1
- {"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/utils/ulid.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\nconst CROCKFORD = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction encodeTime(time: number): string {\n let out = \"\";\n let remaining = time;\n for (let i = 9; i >= 0; i -= 1) {\n const mod = remaining % 32;\n out = CROCKFORD.charAt(mod) + out;\n remaining = (remaining - mod) / 32;\n }\n return out;\n}\n\n/* eslint-disable no-bitwise, no-non-null-assertion -- ULID encoding is inherently bitwise. */\nfunction encodeRandom(bytes: Buffer): string {\n let out = \"\";\n let buffer = 0;\n let bits = 0;\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD.charAt((buffer >>> (bits - 5)) & 31);\n bits -= 5;\n }\n }\n if (bits > 0) {\n out += CROCKFORD.charAt((buffer << (5 - bits)) & 31);\n }\n return out;\n}\n/* eslint-enable no-bitwise, no-non-null-assertion */\n\n/** Generate a sortable, collision-resistant ULID. */\nexport function ulid(): string {\n return encodeTime(Date.now()) + encodeRandom(randomBytes(10));\n}\n\n/** Convert a name to a URL-safe slug of at most 63 characters. */\nexport function slugify(value: string): string {\n return value\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gu, \"-\")\n .replaceAll(/^-+|-+$/gu, \"\")\n .slice(0, 63);\n}\n"],"mappings":";;;;;AAEA,MAAM,YAAY;AAElB,SAAS,WAAW,MAAsB;CACxC,IAAI,MAAM;CACV,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG;EAC9B,MAAM,MAAM,YAAY;EACxB,MAAM,UAAU,OAAO,GAAG,IAAI;EAC9B,aAAa,YAAY,OAAO;CAClC;CACA,OAAO;AACT;AAGA,SAAS,aAAa,OAAuB;CAC3C,IAAI,MAAM;CACV,IAAI,SAAS;CACb,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAU,UAAU,IAAK;EACzB,QAAQ;EACR,OAAO,QAAQ,GAAG;GAChB,OAAO,UAAU,OAAQ,WAAY,OAAO,IAAM,EAAE;GACpD,QAAQ;EACV;CACF;CACA,IAAI,OAAO,GACT,OAAO,UAAU,OAAQ,UAAW,IAAI,OAAS,EAAE;CAErD,OAAO;AACT;;AAIA,SAAgB,OAAe;CAC7B,OAAO,WAAW,KAAK,IAAI,CAAC,IAAI,aAAa,YAAY,EAAE,CAAC;AAC9D;;AAGA,SAAgB,QAAQ,OAAuB;CAC7C,OAAO,MACJ,YAAY,CAAC,CACb,WAAW,gBAAgB,GAAG,CAAC,CAC/B,WAAW,aAAa,EAAE,CAAC,CAC3B,MAAM,GAAG,EAAE;AAChB"}
1
+ {"version":3,"file":"ulid.mjs","names":[],"sources":["../../src/utils/ulid.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\n\n/** Generate a sortable, collision-resistant ULID. */\nexport function ulid(): string {\n return encodeTime(Date.now()) + encodeRandom(randomBytes(10));\n}\n\n/** Convert a name to a URL-safe slug of at most 63 characters. */\nexport function slugify(value: string): string {\n return value\n .toLowerCase()\n .replaceAll(/[^a-z0-9]+/gu, \"-\")\n .replaceAll(/^-+|-+$/gu, \"\")\n .slice(0, 63);\n}\n\nconst CROCKFORD = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nfunction encodeTime(time: number): string {\n let out = \"\";\n let remaining = time;\n for (let i = 9; i >= 0; i -= 1) {\n const mod = remaining % 32;\n out = CROCKFORD.charAt(mod) + out;\n remaining = (remaining - mod) / 32;\n }\n return out;\n}\n\n/* eslint-disable no-bitwise, no-non-null-assertion -- ULID encoding is inherently bitwise. */\nfunction encodeRandom(bytes: Buffer): string {\n let out = \"\";\n let buffer = 0;\n let bits = 0;\n for (const byte of bytes) {\n buffer = (buffer << 8) | byte;\n bits += 8;\n while (bits >= 5) {\n out += CROCKFORD.charAt((buffer >>> (bits - 5)) & 31);\n bits -= 5;\n }\n }\n if (bits > 0) {\n out += CROCKFORD.charAt((buffer << (5 - bits)) & 31);\n }\n return out;\n}\n/* eslint-enable no-bitwise, no-non-null-assertion */\n"],"mappings":";;;;;;AAGA,SAAgB,OAAe;CAC7B,OAAO,WAAW,KAAK,IAAI,CAAC,IAAI,aAAa,YAAY,EAAE,CAAC;AAC9D;;AAGA,SAAgB,QAAQ,OAAuB;CAC7C,OAAO,MACJ,YAAY,CAAC,CACb,WAAW,gBAAgB,GAAG,CAAC,CAC/B,WAAW,aAAa,EAAE,CAAC,CAC3B,MAAM,GAAG,EAAE;AAChB;AAEA,MAAM,YAAY;AAElB,SAAS,WAAW,MAAsB;CACxC,IAAI,MAAM;CACV,IAAI,YAAY;CAChB,KAAK,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG;EAC9B,MAAM,MAAM,YAAY;EACxB,MAAM,UAAU,OAAO,GAAG,IAAI;EAC9B,aAAa,YAAY,OAAO;CAClC;CACA,OAAO;AACT;AAGA,SAAS,aAAa,OAAuB;CAC3C,IAAI,MAAM;CACV,IAAI,SAAS;CACb,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,OAAO;EACxB,SAAU,UAAU,IAAK;EACzB,QAAQ;EACR,OAAO,QAAQ,GAAG;GAChB,OAAO,UAAU,OAAQ,WAAY,OAAO,IAAM,EAAE;GACpD,QAAQ;EACV;CACF;CACA,IAAI,OAAO,GACT,OAAO,UAAU,OAAQ,UAAW,IAAI,OAAS,EAAE;CAErD,OAAO;AACT"}
@@ -0,0 +1,12 @@
1
+ import __tsdown_shims_path from 'node:path';
2
+ import __tsdown_shims_url from 'node:url';
3
+ import { KeyUsed, SecretInput, SecretKeys, UndecryptableCredentialError, decrypt, decryptCredential, decryptWithKey, encrypt } from "./utils/encrypt.mjs";
4
+ import { hmacSha256, randomToken, sha256, timingSafeEqualString } from "./utils/hash.mjs";
5
+ import { HttpError, HttpRequestOptions, HttpTextOptions, httpJson, httpText } from "./utils/http.mjs";
6
+ import { baselinePath, diffPath, screenshotPath, storybookDir, storybookZipPath } from "./paths.mjs";
7
+ import { MIME_TYPES, mimeFor } from "./utils/mime.mjs";
8
+ import { isBlockedTarget, isPathSafe, isSafeSegment } from "./utils/path-security.mjs";
9
+ import { redactSecrets, sanitizeErrorText } from "./utils/redact.mjs";
10
+ import { TimingMap, addTiming, roundedTimings, runWithTimings, timed } from "./utils/timing.mjs";
11
+ import { slugify, ulid } from "./utils/ulid.mjs";
12
+ export { HttpError, type HttpRequestOptions, type HttpTextOptions, type KeyUsed, MIME_TYPES, type SecretInput, type SecretKeys, type TimingMap, UndecryptableCredentialError, addTiming, baselinePath, decrypt, decryptCredential, decryptWithKey, diffPath, encrypt, hmacSha256, httpJson, httpText, isBlockedTarget, isPathSafe, isSafeSegment, mimeFor, randomToken, redactSecrets, roundedTimings, runWithTimings, sanitizeErrorText, screenshotPath, sha256, slugify, storybookDir, storybookZipPath, timed, timingSafeEqualString, ulid };
package/dist/utils.mjs ADDED
@@ -0,0 +1,13 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ import { redactSecrets, sanitizeErrorText } from "./utils/redact.mjs";
5
+ import { UndecryptableCredentialError, decrypt, decryptCredential, decryptWithKey, encrypt } from "./utils/encrypt.mjs";
6
+ import { slugify, ulid } from "./utils/ulid.mjs";
7
+ import { hmacSha256, randomToken, sha256, timingSafeEqualString } from "./utils/hash.mjs";
8
+ import { addTiming, roundedTimings, runWithTimings, timed } from "./utils/timing.mjs";
9
+ import { isBlockedTarget, isPathSafe, isSafeSegment } from "./utils/path-security.mjs";
10
+ import { baselinePath, diffPath, screenshotPath, storybookDir, storybookZipPath } from "./paths.mjs";
11
+ import { HttpError, httpJson, httpText } from "./utils/http.mjs";
12
+ import { MIME_TYPES, mimeFor } from "./utils/mime.mjs";
13
+ export { HttpError, MIME_TYPES, UndecryptableCredentialError, addTiming, baselinePath, decrypt, decryptCredential, decryptWithKey, diffPath, encrypt, hmacSha256, httpJson, httpText, isBlockedTarget, isPathSafe, isSafeSegment, mimeFor, randomToken, redactSecrets, roundedTimings, runWithTimings, sanitizeErrorText, screenshotPath, sha256, slugify, storybookDir, storybookZipPath, timed, timingSafeEqualString, ulid };