@shipfox/client-workflows 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/.storybook/main.ts +1 -0
  2. package/.storybook/preview.css +10 -0
  3. package/.storybook/preview.tsx +97 -0
  4. package/.swcrc +42 -0
  5. package/.turbo/turbo-build.log +2 -0
  6. package/.turbo/turbo-type$colon$emit.log +1 -0
  7. package/.turbo/turbo-type.log +1 -0
  8. package/CHANGELOG.md +162 -0
  9. package/LICENSE +21 -0
  10. package/dist/components/identifier/identifier.d.ts +6 -0
  11. package/dist/components/identifier/identifier.d.ts.map +1 -0
  12. package/dist/components/identifier/identifier.js +144 -0
  13. package/dist/components/identifier/identifier.js.map +1 -0
  14. package/dist/components/identifier/index.d.ts +2 -0
  15. package/dist/components/identifier/index.d.ts.map +1 -0
  16. package/dist/components/identifier/index.js +3 -0
  17. package/dist/components/identifier/index.js.map +1 -0
  18. package/dist/components/job-graph/graph-model.d.ts +27 -0
  19. package/dist/components/job-graph/graph-model.d.ts.map +1 -0
  20. package/dist/components/job-graph/graph-model.js +107 -0
  21. package/dist/components/job-graph/graph-model.js.map +1 -0
  22. package/dist/components/job-graph/index.d.ts +3 -0
  23. package/dist/components/job-graph/index.d.ts.map +1 -0
  24. package/dist/components/job-graph/index.js +3 -0
  25. package/dist/components/job-graph/index.js.map +1 -0
  26. package/dist/components/job-graph/job-duration-format.d.ts +4 -0
  27. package/dist/components/job-graph/job-duration-format.d.ts.map +1 -0
  28. package/dist/components/job-graph/job-duration-format.js +41 -0
  29. package/dist/components/job-graph/job-duration-format.js.map +1 -0
  30. package/dist/components/job-graph/job-duration-label.d.ts +5 -0
  31. package/dist/components/job-graph/job-duration-label.d.ts.map +1 -0
  32. package/dist/components/job-graph/job-duration-label.js +33 -0
  33. package/dist/components/job-graph/job-duration-label.js.map +1 -0
  34. package/dist/components/job-graph/job-graph-content.d.ts +9 -0
  35. package/dist/components/job-graph/job-graph-content.d.ts.map +1 -0
  36. package/dist/components/job-graph/job-graph-content.js +181 -0
  37. package/dist/components/job-graph/job-graph-content.js.map +1 -0
  38. package/dist/components/job-graph/job-graph-view.d.ts +11 -0
  39. package/dist/components/job-graph/job-graph-view.d.ts.map +1 -0
  40. package/dist/components/job-graph/job-graph-view.js +24 -0
  41. package/dist/components/job-graph/job-graph-view.js.map +1 -0
  42. package/dist/components/job-graph/job-graph.d.ts +3 -0
  43. package/dist/components/job-graph/job-graph.d.ts.map +1 -0
  44. package/dist/components/job-graph/job-graph.js +21 -0
  45. package/dist/components/job-graph/job-graph.js.map +1 -0
  46. package/dist/components/job-graph/job-node.d.ts +16 -0
  47. package/dist/components/job-graph/job-node.d.ts.map +1 -0
  48. package/dist/components/job-graph/job-node.js +196 -0
  49. package/dist/components/job-graph/job-node.js.map +1 -0
  50. package/dist/components/job-graph/types.d.ts +9 -0
  51. package/dist/components/job-graph/types.d.ts.map +1 -0
  52. package/dist/components/job-graph/types.js +3 -0
  53. package/dist/components/job-graph/types.js.map +1 -0
  54. package/dist/components/step-list/index.d.ts +3 -0
  55. package/dist/components/step-list/index.d.ts.map +1 -0
  56. package/dist/components/step-list/index.js +3 -0
  57. package/dist/components/step-list/index.js.map +1 -0
  58. package/dist/components/step-list/step-list-model.d.ts +36 -0
  59. package/dist/components/step-list/step-list-model.d.ts.map +1 -0
  60. package/dist/components/step-list/step-list-model.js +135 -0
  61. package/dist/components/step-list/step-list-model.js.map +1 -0
  62. package/dist/components/step-list/step-list.d.ts +32 -0
  63. package/dist/components/step-list/step-list.d.ts.map +1 -0
  64. package/dist/components/step-list/step-list.js +409 -0
  65. package/dist/components/step-list/step-list.js.map +1 -0
  66. package/dist/components/workflow-run-duration-label.d.ts +8 -0
  67. package/dist/components/workflow-run-duration-label.d.ts.map +1 -0
  68. package/dist/components/workflow-run-duration-label.js +84 -0
  69. package/dist/components/workflow-run-duration-label.js.map +1 -0
  70. package/dist/components/workflow-run-list/index.d.ts +2 -0
  71. package/dist/components/workflow-run-list/index.d.ts.map +1 -0
  72. package/dist/components/workflow-run-list/index.js +3 -0
  73. package/dist/components/workflow-run-list/index.js.map +1 -0
  74. package/dist/components/workflow-run-list/run-display.d.ts +5 -0
  75. package/dist/components/workflow-run-list/run-display.d.ts.map +1 -0
  76. package/dist/components/workflow-run-list/run-display.js +19 -0
  77. package/dist/components/workflow-run-list/run-display.js.map +1 -0
  78. package/dist/components/workflow-run-list/types.d.ts +21 -0
  79. package/dist/components/workflow-run-list/types.d.ts.map +1 -0
  80. package/dist/components/workflow-run-list/types.js +3 -0
  81. package/dist/components/workflow-run-list/types.js.map +1 -0
  82. package/dist/components/workflow-run-list/workflow-run-list-content.d.ts +14 -0
  83. package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -0
  84. package/dist/components/workflow-run-list/workflow-run-list-content.js +37 -0
  85. package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -0
  86. package/dist/components/workflow-run-list/workflow-run-list-header.d.ts +10 -0
  87. package/dist/components/workflow-run-list/workflow-run-list-header.d.ts.map +1 -0
  88. package/dist/components/workflow-run-list/workflow-run-list-header.js +55 -0
  89. package/dist/components/workflow-run-list/workflow-run-list-header.js.map +1 -0
  90. package/dist/components/workflow-run-list/workflow-run-list-states.d.ts +15 -0
  91. package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -0
  92. package/dist/components/workflow-run-list/workflow-run-list-states.js +103 -0
  93. package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -0
  94. package/dist/components/workflow-run-list/workflow-run-list-view.d.ts +3 -0
  95. package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -0
  96. package/dist/components/workflow-run-list/workflow-run-list-view.js +46 -0
  97. package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -0
  98. package/dist/components/workflow-run-list/workflow-run-list.d.ts +3 -0
  99. package/dist/components/workflow-run-list/workflow-run-list.d.ts.map +1 -0
  100. package/dist/components/workflow-run-list/workflow-run-list.js +20 -0
  101. package/dist/components/workflow-run-list/workflow-run-list.js.map +1 -0
  102. package/dist/components/workflow-run-list/workflow-run-row.d.ts +14 -0
  103. package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -0
  104. package/dist/components/workflow-run-list/workflow-run-row.js +172 -0
  105. package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -0
  106. package/dist/components/workflow-run-summary/index.d.ts +2 -0
  107. package/dist/components/workflow-run-summary/index.d.ts.map +1 -0
  108. package/dist/components/workflow-run-summary/index.js +3 -0
  109. package/dist/components/workflow-run-summary/index.js.map +1 -0
  110. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts +9 -0
  111. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts.map +1 -0
  112. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +138 -0
  113. package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -0
  114. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +20 -0
  115. package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -0
  116. package/dist/components/workflow-run-summary/workflow-run-summary.js +252 -0
  117. package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -0
  118. package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts +7 -0
  119. package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +1 -0
  120. package/dist/components/workflow-run-view/agent-config-failure-callout.js +84 -0
  121. package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +1 -0
  122. package/dist/components/workflow-run-view/index.d.ts +3 -0
  123. package/dist/components/workflow-run-view/index.d.ts.map +1 -0
  124. package/dist/components/workflow-run-view/index.js +4 -0
  125. package/dist/components/workflow-run-view/index.js.map +1 -0
  126. package/dist/components/workflow-run-view/job-card.d.ts +17 -0
  127. package/dist/components/workflow-run-view/job-card.d.ts.map +1 -0
  128. package/dist/components/workflow-run-view/job-card.js +476 -0
  129. package/dist/components/workflow-run-view/job-card.js.map +1 -0
  130. package/dist/components/workflow-run-view/job-execution-switcher.d.ts +10 -0
  131. package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +1 -0
  132. package/dist/components/workflow-run-view/job-execution-switcher.js +171 -0
  133. package/dist/components/workflow-run-view/job-execution-switcher.js.map +1 -0
  134. package/dist/components/workflow-run-view/job-execution-time-text.d.ts +6 -0
  135. package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +1 -0
  136. package/dist/components/workflow-run-view/job-execution-time-text.js +24 -0
  137. package/dist/components/workflow-run-view/job-execution-time-text.js.map +1 -0
  138. package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +9 -0
  139. package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +1 -0
  140. package/dist/components/workflow-run-view/step-attempt-log-panel.js +152 -0
  141. package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +1 -0
  142. package/dist/components/workflow-run-view/workflow-run-selection.d.ts +14 -0
  143. package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -0
  144. package/dist/components/workflow-run-view/workflow-run-selection.js +56 -0
  145. package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -0
  146. package/dist/components/workflow-run-view/workflow-run-states.d.ts +12 -0
  147. package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -0
  148. package/dist/components/workflow-run-view/workflow-run-states.js +91 -0
  149. package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -0
  150. package/dist/components/workflow-run-view/workflow-run-view.d.ts +15 -0
  151. package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -0
  152. package/dist/components/workflow-run-view/workflow-run-view.js +285 -0
  153. package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -0
  154. package/dist/components/workflow-source-panel/index.d.ts +2 -0
  155. package/dist/components/workflow-source-panel/index.d.ts.map +1 -0
  156. package/dist/components/workflow-source-panel/index.js +3 -0
  157. package/dist/components/workflow-source-panel/index.js.map +1 -0
  158. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts +13 -0
  159. package/dist/components/workflow-source-panel/workflow-source-panel.d.ts.map +1 -0
  160. package/dist/components/workflow-source-panel/workflow-source-panel.js +91 -0
  161. package/dist/components/workflow-source-panel/workflow-source-panel.js.map +1 -0
  162. package/dist/components/workflow-status/status-visuals.d.ts +12 -0
  163. package/dist/components/workflow-status/status-visuals.d.ts.map +1 -0
  164. package/dist/components/workflow-status/status-visuals.js +54 -0
  165. package/dist/components/workflow-status/status-visuals.js.map +1 -0
  166. package/dist/components/workflow-status/workflow-status-icon.d.ts +22 -0
  167. package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -0
  168. package/dist/components/workflow-status/workflow-status-icon.js +100 -0
  169. package/dist/components/workflow-status/workflow-status-icon.js.map +1 -0
  170. package/dist/core/entities/job-execution.d.ts +69 -0
  171. package/dist/core/entities/job-execution.d.ts.map +1 -0
  172. package/dist/core/entities/job-execution.js +83 -0
  173. package/dist/core/entities/job-execution.js.map +1 -0
  174. package/dist/core/entities/job.d.ts +56 -0
  175. package/dist/core/entities/job.d.ts.map +1 -0
  176. package/dist/core/entities/job.js +71 -0
  177. package/dist/core/entities/job.js.map +1 -0
  178. package/dist/core/entities/step-attempt.d.ts +49 -0
  179. package/dist/core/entities/step-attempt.d.ts.map +1 -0
  180. package/dist/core/entities/step-attempt.js +48 -0
  181. package/dist/core/entities/step-attempt.js.map +1 -0
  182. package/dist/core/entities/step.d.ts +41 -0
  183. package/dist/core/entities/step.d.ts.map +1 -0
  184. package/dist/core/entities/step.js +51 -0
  185. package/dist/core/entities/step.js.map +1 -0
  186. package/dist/core/entities/workflow-run-attempt.d.ts +44 -0
  187. package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -0
  188. package/dist/core/entities/workflow-run-attempt.js +51 -0
  189. package/dist/core/entities/workflow-run-attempt.js.map +1 -0
  190. package/dist/core/entities/workflow-run.d.ts +61 -0
  191. package/dist/core/entities/workflow-run.d.ts.map +1 -0
  192. package/dist/core/entities/workflow-run.js +104 -0
  193. package/dist/core/entities/workflow-run.js.map +1 -0
  194. package/dist/core/workflow-run-url-state.d.ts +13 -0
  195. package/dist/core/workflow-run-url-state.d.ts.map +1 -0
  196. package/dist/core/workflow-run-url-state.js +43 -0
  197. package/dist/core/workflow-run-url-state.js.map +1 -0
  198. package/dist/core/workflow-run.d.ts +13 -0
  199. package/dist/core/workflow-run.d.ts.map +1 -0
  200. package/dist/core/workflow-run.js +8 -0
  201. package/dist/core/workflow-run.js.map +1 -0
  202. package/dist/env.d.js +2 -0
  203. package/dist/env.d.js.map +1 -0
  204. package/dist/feature.d.ts +20 -0
  205. package/dist/feature.d.ts.map +1 -0
  206. package/dist/feature.js +27 -0
  207. package/dist/feature.js.map +1 -0
  208. package/dist/hooks/api/workflow-runs.d.ts +109 -0
  209. package/dist/hooks/api/workflow-runs.d.ts.map +1 -0
  210. package/dist/hooks/api/workflow-runs.js +394 -0
  211. package/dist/hooks/api/workflow-runs.js.map +1 -0
  212. package/dist/index.d.ts +5 -0
  213. package/dist/index.d.ts.map +1 -0
  214. package/dist/index.js +5 -0
  215. package/dist/index.js.map +1 -0
  216. package/dist/pages/workflow-run-first-time-use.d.ts +6 -0
  217. package/dist/pages/workflow-run-first-time-use.d.ts.map +1 -0
  218. package/dist/pages/workflow-run-first-time-use.js +17 -0
  219. package/dist/pages/workflow-run-first-time-use.js.map +1 -0
  220. package/dist/pages/workflow-run-page.d.ts +8 -0
  221. package/dist/pages/workflow-run-page.d.ts.map +1 -0
  222. package/dist/pages/workflow-run-page.js +83 -0
  223. package/dist/pages/workflow-run-page.js.map +1 -0
  224. package/dist/routes/run-detail.d.ts +8 -0
  225. package/dist/routes/run-detail.d.ts.map +1 -0
  226. package/dist/routes/run-detail.js +21 -0
  227. package/dist/routes/run-detail.js.map +1 -0
  228. package/dist/routes/runs.d.ts +8 -0
  229. package/dist/routes/runs.d.ts.map +1 -0
  230. package/dist/routes/runs.js +20 -0
  231. package/dist/routes/runs.js.map +1 -0
  232. package/dist/tsconfig.test.tsbuildinfo +1 -0
  233. package/package.json +114 -0
  234. package/src/components/identifier/identifier.tsx +178 -0
  235. package/src/components/identifier/index.ts +1 -0
  236. package/src/components/job-graph/graph-model.test.ts +189 -0
  237. package/src/components/job-graph/graph-model.ts +178 -0
  238. package/src/components/job-graph/index.ts +2 -0
  239. package/src/components/job-graph/job-duration-format.ts +54 -0
  240. package/src/components/job-graph/job-duration-label.tsx +29 -0
  241. package/src/components/job-graph/job-graph-content.tsx +225 -0
  242. package/src/components/job-graph/job-graph-view.test.tsx +298 -0
  243. package/src/components/job-graph/job-graph-view.tsx +45 -0
  244. package/src/components/job-graph/job-graph.stories.tsx +182 -0
  245. package/src/components/job-graph/job-graph.tsx +24 -0
  246. package/src/components/job-graph/job-node.stories.tsx +364 -0
  247. package/src/components/job-graph/job-node.test.tsx +347 -0
  248. package/src/components/job-graph/job-node.tsx +202 -0
  249. package/src/components/job-graph/types.ts +9 -0
  250. package/src/components/step-list/index.ts +6 -0
  251. package/src/components/step-list/step-list-model.test.ts +369 -0
  252. package/src/components/step-list/step-list-model.ts +205 -0
  253. package/src/components/step-list/step-list.stories.tsx +419 -0
  254. package/src/components/step-list/step-list.test.tsx +566 -0
  255. package/src/components/step-list/step-list.tsx +494 -0
  256. package/src/components/workflow-run-duration-label.tsx +118 -0
  257. package/src/components/workflow-run-list/index.ts +1 -0
  258. package/src/components/workflow-run-list/run-display.test.ts +53 -0
  259. package/src/components/workflow-run-list/run-display.ts +22 -0
  260. package/src/components/workflow-run-list/types.ts +22 -0
  261. package/src/components/workflow-run-list/workflow-run-list-content.tsx +58 -0
  262. package/src/components/workflow-run-list/workflow-run-list-header.tsx +53 -0
  263. package/src/components/workflow-run-list/workflow-run-list-states.tsx +86 -0
  264. package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +178 -0
  265. package/src/components/workflow-run-list/workflow-run-list-view.tsx +57 -0
  266. package/src/components/workflow-run-list/workflow-run-list.stories.tsx +111 -0
  267. package/src/components/workflow-run-list/workflow-run-list.tsx +29 -0
  268. package/src/components/workflow-run-list/workflow-run-row.tsx +176 -0
  269. package/src/components/workflow-run-summary/index.ts +1 -0
  270. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx +230 -0
  271. package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +146 -0
  272. package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +414 -0
  273. package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +354 -0
  274. package/src/components/workflow-run-summary/workflow-run-summary.tsx +295 -0
  275. package/src/components/workflow-run-view/agent-config-failure-callout.stories.tsx +140 -0
  276. package/src/components/workflow-run-view/agent-config-failure-callout.tsx +93 -0
  277. package/src/components/workflow-run-view/index.ts +2 -0
  278. package/src/components/workflow-run-view/job-card.stories.tsx +788 -0
  279. package/src/components/workflow-run-view/job-card.tsx +566 -0
  280. package/src/components/workflow-run-view/job-execution-switcher.tsx +170 -0
  281. package/src/components/workflow-run-view/job-execution-time-text.tsx +34 -0
  282. package/src/components/workflow-run-view/step-attempt-log-panel.test.tsx +290 -0
  283. package/src/components/workflow-run-view/step-attempt-log-panel.tsx +152 -0
  284. package/src/components/workflow-run-view/workflow-run-selection.test.ts +280 -0
  285. package/src/components/workflow-run-view/workflow-run-selection.ts +89 -0
  286. package/src/components/workflow-run-view/workflow-run-states.tsx +70 -0
  287. package/src/components/workflow-run-view/workflow-run-view.test.tsx +1214 -0
  288. package/src/components/workflow-run-view/workflow-run-view.tsx +341 -0
  289. package/src/components/workflow-source-panel/index.ts +1 -0
  290. package/src/components/workflow-source-panel/workflow-source-panel.stories.tsx +110 -0
  291. package/src/components/workflow-source-panel/workflow-source-panel.test.tsx +96 -0
  292. package/src/components/workflow-source-panel/workflow-source-panel.tsx +136 -0
  293. package/src/components/workflow-status/status-visuals.test.ts +38 -0
  294. package/src/components/workflow-status/status-visuals.ts +36 -0
  295. package/src/components/workflow-status/workflow-status-icon.stories.tsx +90 -0
  296. package/src/components/workflow-status/workflow-status-icon.tsx +135 -0
  297. package/src/core/entities/job-execution.ts +139 -0
  298. package/src/core/entities/job.ts +149 -0
  299. package/src/core/entities/step-attempt.ts +89 -0
  300. package/src/core/entities/step.ts +105 -0
  301. package/src/core/entities/workflow-run-attempt.ts +87 -0
  302. package/src/core/entities/workflow-run.ts +183 -0
  303. package/src/core/workflow-run-url-state.ts +61 -0
  304. package/src/core/workflow-run.test.ts +640 -0
  305. package/src/core/workflow-run.ts +66 -0
  306. package/src/env.d.ts +8 -0
  307. package/src/feature.ts +26 -0
  308. package/src/hooks/api/workflow-runs.test.tsx +410 -0
  309. package/src/hooks/api/workflow-runs.ts +485 -0
  310. package/src/index.ts +45 -0
  311. package/src/page-harness-budget.test.ts +33 -0
  312. package/src/pages/workflow-run-first-time-use.tsx +17 -0
  313. package/src/pages/workflow-run-page.test.tsx +517 -0
  314. package/src/pages/workflow-run-page.tsx +89 -0
  315. package/src/routes/run-detail.tsx +15 -0
  316. package/src/routes/runs.tsx +11 -0
  317. package/test/fixtures/logs.ts +13 -0
  318. package/test/fixtures/workflow-run.ts +311 -0
  319. package/test/pages.tsx +79 -0
  320. package/test/render.tsx +40 -0
  321. package/test/setup.ts +3 -0
  322. package/tsconfig.build.json +9 -0
  323. package/tsconfig.build.tsbuildinfo +1 -0
  324. package/tsconfig.json +3 -0
  325. package/tsconfig.test.json +8 -0
  326. package/vercel.json +8 -0
  327. package/vitest.config.ts +70 -0
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Dot } from '@shipfox/react-ui/dot';
3
+ import { Icon } from '@shipfox/react-ui/icon';
4
+ import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
5
+ import { cn } from '@shipfox/react-ui/utils';
6
+ import { getWorkflowStatusVisual } from './status-visuals.js';
7
+ // Status glyphs use the same saturated accent tokens as IconBadge/StatusBadge.
8
+ const toneByVariant = {
9
+ neutral: 'text-tag-neutral-icon',
10
+ info: 'text-tag-blue-icon',
11
+ feature: 'text-tag-purple-icon',
12
+ success: 'text-tag-success-icon',
13
+ warning: 'text-tag-warning-icon',
14
+ error: 'text-tag-error-icon'
15
+ };
16
+ // Terminal states are self-contained solid discs; the shape names the state. Running and
17
+ // pending render their own shapes (the live Dot and a bold ring), so they aren't here.
18
+ const glyphByKind = {
19
+ succeeded: 'checkCircleSolid',
20
+ failed: 'xCircleSolid',
21
+ cancelled: 'forbid2Fill',
22
+ skipped: 'forbid2Fill'
23
+ };
24
+ // The solid discs fill ~90-95% of their viewBox and forbid2Fill ~83%, so one numeric size
25
+ // renders different diameters. These multipliers land every disc at the running Dot's diameter.
26
+ const glyphScale = {
27
+ checkCircleSolid: 1.12,
28
+ xCircleSolid: 1.06,
29
+ forbid2Fill: 1.22
30
+ };
31
+ // Only the two sizes the app uses are mapped; both are literal strings so Tailwind emits them.
32
+ const dotSizeClass = {
33
+ 12: 'size-12',
34
+ 14: 'size-14',
35
+ 20: 'size-20'
36
+ };
37
+ // Pending is a neutral ring: a filled disc with a transparent center punched out by a radial
38
+ // mask. Reads as "not started" and stays visually consistent with the solid discs - much
39
+ // bolder than a dotted outline. Tune the mask stops to make the band thicker or thinner.
40
+ const PENDING_RING_MASK = 'radial-gradient(circle closest-side, transparent 0 52%, #000 56%)';
41
+ /**
42
+ * The job/run/step state indicator: an icon-in-circle glyph whose shape (not just color)
43
+ * names the state. Carries the status as its accessible name (`role="img"`) and, by default,
44
+ * a hover tooltip, so the state is reachable by pointer and assistive tech everywhere.
45
+ */ export function WorkflowStatusIcon({ status, jobMode = 'one_shot', size = 14, ripple = true, tooltip = true, className }) {
46
+ const visual = getWorkflowStatusVisual(status);
47
+ const box = dotSizeClass[size] ?? 'size-14';
48
+ let glyph;
49
+ if (visual.kind === 'running') {
50
+ glyph = jobMode === 'listening' ? /*#__PURE__*/ _jsx("span", {
51
+ className: cn('inline-flex shrink-0 items-center justify-center rounded-full bg-current', box, toneByVariant.info),
52
+ children: /*#__PURE__*/ _jsx(Icon, {
53
+ name: "pulseLine",
54
+ size: Math.max(8, Math.round(size * 0.7)),
55
+ className: "text-white"
56
+ })
57
+ }) : /*#__PURE__*/ _jsx(Dot, {
58
+ variant: "info",
59
+ ripple: ripple,
60
+ className: box
61
+ });
62
+ } else if (visual.kind === 'pending') {
63
+ glyph = /*#__PURE__*/ _jsx("span", {
64
+ className: cn('rounded-full bg-current', box, toneByVariant.neutral),
65
+ style: {
66
+ maskImage: PENDING_RING_MASK,
67
+ WebkitMaskImage: PENDING_RING_MASK
68
+ }
69
+ });
70
+ } else {
71
+ const name = glyphByKind[visual.kind] ?? 'forbid2Fill';
72
+ glyph = /*#__PURE__*/ _jsx("span", {
73
+ className: cn('inline-flex shrink-0 items-center justify-center', box, toneByVariant[visual.dot], (visual.kind === 'cancelled' || visual.kind === 'skipped') && 'opacity-70'),
74
+ children: /*#__PURE__*/ _jsx(Icon, {
75
+ name: name,
76
+ size: Math.round(size * (glyphScale[name] ?? 1))
77
+ })
78
+ });
79
+ }
80
+ const indicator = /*#__PURE__*/ _jsx("span", {
81
+ role: "img",
82
+ "aria-label": visual.label,
83
+ className: cn('inline-flex shrink-0', className),
84
+ children: glyph
85
+ });
86
+ if (!tooltip) return indicator;
87
+ return /*#__PURE__*/ _jsxs(Tooltip, {
88
+ children: [
89
+ /*#__PURE__*/ _jsx(TooltipTrigger, {
90
+ asChild: true,
91
+ children: indicator
92
+ }),
93
+ /*#__PURE__*/ _jsx(TooltipContent, {
94
+ children: visual.label
95
+ })
96
+ ]
97
+ });
98
+ }
99
+
100
+ //# sourceMappingURL=workflow-status-icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/workflow-status/workflow-status-icon.tsx"],"sourcesContent":["import {Dot, type DotVariant} from '@shipfox/react-ui/dot';\nimport {Icon, type IconName} from '@shipfox/react-ui/icon';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {cn} from '@shipfox/react-ui/utils';\nimport type {ReactNode} from 'react';\nimport {getWorkflowStatusVisual, type WorkflowStatus} from './status-visuals.js';\n\n// Status glyphs use the same saturated accent tokens as IconBadge/StatusBadge.\nconst toneByVariant: Record<DotVariant, string> = {\n neutral: 'text-tag-neutral-icon',\n info: 'text-tag-blue-icon',\n feature: 'text-tag-purple-icon',\n success: 'text-tag-success-icon',\n warning: 'text-tag-warning-icon',\n error: 'text-tag-error-icon',\n};\n\n// Terminal states are self-contained solid discs; the shape names the state. Running and\n// pending render their own shapes (the live Dot and a bold ring), so they aren't here.\nconst glyphByKind: Partial<Record<WorkflowStatus, IconName>> = {\n succeeded: 'checkCircleSolid',\n failed: 'xCircleSolid',\n cancelled: 'forbid2Fill',\n skipped: 'forbid2Fill',\n};\n\n// The solid discs fill ~90-95% of their viewBox and forbid2Fill ~83%, so one numeric size\n// renders different diameters. These multipliers land every disc at the running Dot's diameter.\nconst glyphScale: Partial<Record<IconName, number>> = {\n checkCircleSolid: 1.12,\n xCircleSolid: 1.06,\n forbid2Fill: 1.22,\n};\n\n// Only the two sizes the app uses are mapped; both are literal strings so Tailwind emits them.\nconst dotSizeClass: Record<number, string> = {\n 12: 'size-12',\n 14: 'size-14',\n 20: 'size-20',\n};\n\n// Pending is a neutral ring: a filled disc with a transparent center punched out by a radial\n// mask. Reads as \"not started\" and stays visually consistent with the solid discs - much\n// bolder than a dotted outline. Tune the mask stops to make the band thicker or thinner.\nconst PENDING_RING_MASK = 'radial-gradient(circle closest-side, transparent 0 52%, #000 56%)';\n\nexport interface WorkflowStatusIconProps {\n status: WorkflowStatus;\n jobMode?: 'one_shot' | 'listening';\n /** Optical diameter in px: 14 in the DAG node and run row. */\n size?: number;\n /** Pulsing halo for the running state. */\n ripple?: boolean;\n /**\n * Wrap the indicator in a hover tooltip naming the status. Defaults on. Pass false where\n * the status text is already visible next to it (the DAG node) to avoid a redundant tooltip.\n */\n tooltip?: boolean;\n className?: string;\n}\n\n/**\n * The job/run/step state indicator: an icon-in-circle glyph whose shape (not just color)\n * names the state. Carries the status as its accessible name (`role=\"img\"`) and, by default,\n * a hover tooltip, so the state is reachable by pointer and assistive tech everywhere.\n */\nexport function WorkflowStatusIcon({\n status,\n jobMode = 'one_shot',\n size = 14,\n ripple = true,\n tooltip = true,\n className,\n}: WorkflowStatusIconProps) {\n const visual = getWorkflowStatusVisual(status);\n const box = dotSizeClass[size] ?? 'size-14';\n\n let glyph: ReactNode;\n if (visual.kind === 'running') {\n glyph =\n jobMode === 'listening' ? (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center justify-center rounded-full bg-current',\n box,\n toneByVariant.info,\n )}\n >\n <Icon\n name=\"pulseLine\"\n size={Math.max(8, Math.round(size * 0.7))}\n className=\"text-white\"\n />\n </span>\n ) : (\n <Dot variant=\"info\" ripple={ripple} className={box} />\n );\n } else if (visual.kind === 'pending') {\n glyph = (\n <span\n className={cn('rounded-full bg-current', box, toneByVariant.neutral)}\n style={{maskImage: PENDING_RING_MASK, WebkitMaskImage: PENDING_RING_MASK}}\n />\n );\n } else {\n const name = glyphByKind[visual.kind] ?? 'forbid2Fill';\n glyph = (\n <span\n className={cn(\n 'inline-flex shrink-0 items-center justify-center',\n box,\n toneByVariant[visual.dot],\n (visual.kind === 'cancelled' || visual.kind === 'skipped') && 'opacity-70',\n )}\n >\n <Icon name={name} size={Math.round(size * (glyphScale[name] ?? 1))} />\n </span>\n );\n }\n\n const indicator = (\n <span role=\"img\" aria-label={visual.label} className={cn('inline-flex shrink-0', className)}>\n {glyph}\n </span>\n );\n\n if (!tooltip) return indicator;\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>{indicator}</TooltipTrigger>\n <TooltipContent>{visual.label}</TooltipContent>\n </Tooltip>\n );\n}\n"],"names":["Dot","Icon","Tooltip","TooltipContent","TooltipTrigger","cn","getWorkflowStatusVisual","toneByVariant","neutral","info","feature","success","warning","error","glyphByKind","succeeded","failed","cancelled","skipped","glyphScale","checkCircleSolid","xCircleSolid","forbid2Fill","dotSizeClass","PENDING_RING_MASK","WorkflowStatusIcon","status","jobMode","size","ripple","tooltip","className","visual","box","glyph","kind","span","name","Math","max","round","variant","style","maskImage","WebkitMaskImage","dot","indicator","role","aria-label","label","asChild"],"mappings":";AAAA,SAAQA,GAAG,QAAwB,wBAAwB;AAC3D,SAAQC,IAAI,QAAsB,yBAAyB;AAC3D,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,EAAE,QAAO,0BAA0B;AAE3C,SAAQC,uBAAuB,QAA4B,sBAAsB;AAEjF,+EAA+E;AAC/E,MAAMC,gBAA4C;IAChDC,SAAS;IACTC,MAAM;IACNC,SAAS;IACTC,SAAS;IACTC,SAAS;IACTC,OAAO;AACT;AAEA,yFAAyF;AACzF,uFAAuF;AACvF,MAAMC,cAAyD;IAC7DC,WAAW;IACXC,QAAQ;IACRC,WAAW;IACXC,SAAS;AACX;AAEA,0FAA0F;AAC1F,gGAAgG;AAChG,MAAMC,aAAgD;IACpDC,kBAAkB;IAClBC,cAAc;IACdC,aAAa;AACf;AAEA,+FAA+F;AAC/F,MAAMC,eAAuC;IAC3C,IAAI;IACJ,IAAI;IACJ,IAAI;AACN;AAEA,6FAA6F;AAC7F,yFAAyF;AACzF,yFAAyF;AACzF,MAAMC,oBAAoB;AAiB1B;;;;CAIC,GACD,OAAO,SAASC,mBAAmB,EACjCC,MAAM,EACNC,UAAU,UAAU,EACpBC,OAAO,EAAE,EACTC,SAAS,IAAI,EACbC,UAAU,IAAI,EACdC,SAAS,EACe;IACxB,MAAMC,SAAS1B,wBAAwBoB;IACvC,MAAMO,MAAMV,YAAY,CAACK,KAAK,IAAI;IAElC,IAAIM;IACJ,IAAIF,OAAOG,IAAI,KAAK,WAAW;QAC7BD,QACEP,YAAY,4BACV,KAACS;YACCL,WAAW1B,GACT,4EACA4B,KACA1B,cAAcE,IAAI;sBAGpB,cAAA,KAACR;gBACCoC,MAAK;gBACLT,MAAMU,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAACZ,OAAO;gBACpCG,WAAU;;2BAId,KAAC/B;YAAIyC,SAAQ;YAAOZ,QAAQA;YAAQE,WAAWE;;IAErD,OAAO,IAAID,OAAOG,IAAI,KAAK,WAAW;QACpCD,sBACE,KAACE;YACCL,WAAW1B,GAAG,2BAA2B4B,KAAK1B,cAAcC,OAAO;YACnEkC,OAAO;gBAACC,WAAWnB;gBAAmBoB,iBAAiBpB;YAAiB;;IAG9E,OAAO;QACL,MAAMa,OAAOvB,WAAW,CAACkB,OAAOG,IAAI,CAAC,IAAI;QACzCD,sBACE,KAACE;YACCL,WAAW1B,GACT,oDACA4B,KACA1B,aAAa,CAACyB,OAAOa,GAAG,CAAC,EACzB,AAACb,CAAAA,OAAOG,IAAI,KAAK,eAAeH,OAAOG,IAAI,KAAK,SAAQ,KAAM;sBAGhE,cAAA,KAAClC;gBAAKoC,MAAMA;gBAAMT,MAAMU,KAAKE,KAAK,CAACZ,OAAQT,CAAAA,UAAU,CAACkB,KAAK,IAAI,CAAA;;;IAGrE;IAEA,MAAMS,0BACJ,KAACV;QAAKW,MAAK;QAAMC,cAAYhB,OAAOiB,KAAK;QAAElB,WAAW1B,GAAG,wBAAwB0B;kBAC9EG;;IAIL,IAAI,CAACJ,SAAS,OAAOgB;IAErB,qBACE,MAAC5C;;0BACC,KAACE;gBAAe8C,OAAO;0BAAEJ;;0BACzB,KAAC3C;0BAAgB6B,OAAOiB,KAAK;;;;AAGnC"}
@@ -0,0 +1,69 @@
1
+ import type { WorkflowExecutionEventDto, WorkflowRunJobExecutionDetailDto } from '@shipfox/api-workflows-dto';
2
+ import { type Duration } from 'date-fns';
3
+ import { type Step } from './step.js';
4
+ export type JobExecutionStatus = WorkflowRunJobExecutionDetailDto['status'];
5
+ export type JobExecutionTime = {
6
+ state: 'fixed';
7
+ elapsed: Duration;
8
+ } | {
9
+ state: 'live';
10
+ fromIso: string;
11
+ };
12
+ export type JobExecutionDisplayDuration = ({
13
+ kind: 'queue';
14
+ } & JobExecutionTime) | ({
15
+ kind: 'run';
16
+ } & JobExecutionTime);
17
+ interface JobExecutionFields {
18
+ id: string;
19
+ jobId: string;
20
+ sequence: number;
21
+ name: string;
22
+ status: JobExecutionStatus;
23
+ statusReason: string | null;
24
+ triggerEvents: WorkflowExecutionEventDto[];
25
+ queuedAt: string | null;
26
+ startedAt: string | null;
27
+ finishedAt: string | null;
28
+ timedOutAt: string | null;
29
+ createdAt: string;
30
+ updatedAt: string;
31
+ steps: Step[];
32
+ }
33
+ export declare class JobExecution {
34
+ id: string;
35
+ jobId: string;
36
+ sequence: number;
37
+ name: string;
38
+ status: JobExecutionStatus;
39
+ statusReason: string | null;
40
+ triggerEvents: WorkflowExecutionEventDto[];
41
+ queuedAt: string | null;
42
+ startedAt: string | null;
43
+ finishedAt: string | null;
44
+ timedOutAt: string | null;
45
+ createdAt: string;
46
+ updatedAt: string;
47
+ steps: Step[];
48
+ constructor(fields: JobExecutionFields);
49
+ get queueTime(): JobExecutionTime | null;
50
+ get runTime(): JobExecutionTime | null;
51
+ get displayDuration(): JobExecutionDisplayDuration | null;
52
+ }
53
+ export declare function toJobExecution(dto: WorkflowRunJobExecutionDetailDto): JobExecution;
54
+ export declare function jobExecutionQueueTimeFromTimestamps({ queuedAt, startedAt, finishedAt, }: {
55
+ queuedAt: string | null;
56
+ startedAt: string | null;
57
+ finishedAt: string | null;
58
+ }): JobExecutionTime | null;
59
+ export declare function jobExecutionRunTimeFromTimestamps({ startedAt, finishedAt, }: {
60
+ startedAt: string | null;
61
+ finishedAt: string | null;
62
+ }): JobExecutionTime | null;
63
+ export declare function jobExecutionDisplayDurationFromTimestamps(timestamps: {
64
+ queuedAt: string | null;
65
+ startedAt: string | null;
66
+ finishedAt: string | null;
67
+ }): JobExecutionDisplayDuration | null;
68
+ export {};
69
+ //# sourceMappingURL=job-execution.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-execution.d.ts","sourceRoot":"","sources":["../../../src/core/entities/job-execution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,gCAAgC,EACjC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,KAAK,QAAQ,EAAqB,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAC,KAAK,IAAI,EAAS,MAAM,WAAW,CAAC;AAE5C,MAAM,MAAM,kBAAkB,GAAG,gCAAgC,CAAC,QAAQ,CAAC,CAAC;AAC5E,MAAM,MAAM,gBAAgB,GACxB;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAC,GACnC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AACrC,MAAM,MAAM,2BAA2B,GACnC,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAC,GAAG,gBAAgB,CAAC,GACpC,CAAC;IAAC,IAAI,EAAE,KAAK,CAAA;CAAC,GAAG,gBAAgB,CAAC,CAAC;AAEvC,UAAU,kBAAkB;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,yBAAyB,EAAE,CAAC;IAC3C,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AAED,qBAAa,YAAY;IACvB,EAAE,EAAG,MAAM,CAAC;IACZ,KAAK,EAAG,MAAM,CAAC;IACf,QAAQ,EAAG,MAAM,CAAC;IAClB,IAAI,EAAG,MAAM,CAAC;IACd,MAAM,EAAG,kBAAkB,CAAC;IAC5B,YAAY,EAAG,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,yBAAyB,EAAE,CAAC;IAC5C,QAAQ,EAAG,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAG,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAG,MAAM,CAAC;IACnB,SAAS,EAAG,MAAM,CAAC;IACnB,KAAK,EAAG,IAAI,EAAE,CAAC;gBAEH,MAAM,EAAE,kBAAkB;IAItC,IAAI,SAAS,IAAI,gBAAgB,GAAG,IAAI,CAEvC;IAED,IAAI,OAAO,IAAI,gBAAgB,GAAG,IAAI,CAErC;IAED,IAAI,eAAe,IAAI,2BAA2B,GAAG,IAAI,CAExD;CACF;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,gCAAgC,GAAG,YAAY,CAiBlF;AAED,wBAAgB,mCAAmC,CAAC,EAClD,QAAQ,EACR,SAAS,EACT,UAAU,GACX,EAAE;IACD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,gBAAgB,GAAG,IAAI,CAO1B;AAED,wBAAgB,iCAAiC,CAAC,EAChD,SAAS,EACT,UAAU,GACX,EAAE;IACD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,gBAAgB,GAAG,IAAI,CAM1B;AAED,wBAAgB,yCAAyC,CAAC,UAAU,EAAE;IACpE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,2BAA2B,GAAG,IAAI,CAQrC"}
@@ -0,0 +1,83 @@
1
+ import { intervalToDuration } from 'date-fns';
2
+ import { toStep } from './step.js';
3
+ export class JobExecution {
4
+ constructor(fields){
5
+ Object.assign(this, fields);
6
+ }
7
+ get queueTime() {
8
+ return jobExecutionQueueTimeFromTimestamps(this);
9
+ }
10
+ get runTime() {
11
+ return jobExecutionRunTimeFromTimestamps(this);
12
+ }
13
+ get displayDuration() {
14
+ return jobExecutionDisplayDurationFromTimestamps(this);
15
+ }
16
+ }
17
+ export function toJobExecution(dto) {
18
+ return new JobExecution({
19
+ id: dto.id,
20
+ jobId: dto.job_id,
21
+ sequence: dto.sequence,
22
+ name: dto.name,
23
+ status: dto.status,
24
+ statusReason: dto.status_reason,
25
+ triggerEvents: dto.trigger_events ?? [],
26
+ queuedAt: dto.queued_at ?? null,
27
+ startedAt: dto.started_at ?? null,
28
+ finishedAt: dto.finished_at ?? null,
29
+ timedOutAt: dto.timed_out_at ?? null,
30
+ createdAt: dto.created_at,
31
+ updatedAt: dto.updated_at,
32
+ steps: dto.steps.map(toStep)
33
+ });
34
+ }
35
+ export function jobExecutionQueueTimeFromTimestamps({ queuedAt, startedAt, finishedAt }) {
36
+ if (queuedAt === null) return null;
37
+ if (finishedAt !== null && startedAt === null) return null;
38
+ if (startedAt === null) return {
39
+ state: 'live',
40
+ fromIso: queuedAt
41
+ };
42
+ const elapsed = durationBetween(queuedAt, startedAt);
43
+ return elapsed === null ? null : {
44
+ state: 'fixed',
45
+ elapsed
46
+ };
47
+ }
48
+ export function jobExecutionRunTimeFromTimestamps({ startedAt, finishedAt }) {
49
+ if (startedAt === null) return null;
50
+ if (finishedAt === null) return {
51
+ state: 'live',
52
+ fromIso: startedAt
53
+ };
54
+ const elapsed = durationBetween(startedAt, finishedAt);
55
+ return elapsed === null ? null : {
56
+ state: 'fixed',
57
+ elapsed
58
+ };
59
+ }
60
+ export function jobExecutionDisplayDurationFromTimestamps(timestamps) {
61
+ const runTime = jobExecutionRunTimeFromTimestamps(timestamps);
62
+ if (runTime !== null) return {
63
+ kind: 'run',
64
+ ...runTime
65
+ };
66
+ const queueTime = jobExecutionQueueTimeFromTimestamps(timestamps);
67
+ if (queueTime !== null) return {
68
+ kind: 'queue',
69
+ ...queueTime
70
+ };
71
+ return null;
72
+ }
73
+ function durationBetween(from, to) {
74
+ const start = new Date(from);
75
+ const end = new Date(to);
76
+ if (!Number.isFinite(start.getTime()) || !Number.isFinite(end.getTime())) return null;
77
+ return intervalToDuration({
78
+ start,
79
+ end: end < start ? start : end
80
+ });
81
+ }
82
+
83
+ //# sourceMappingURL=job-execution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/job-execution.ts"],"sourcesContent":["import type {\n WorkflowExecutionEventDto,\n WorkflowRunJobExecutionDetailDto,\n} from '@shipfox/api-workflows-dto';\nimport {type Duration, intervalToDuration} from 'date-fns';\nimport {type Step, toStep} from './step.js';\n\nexport type JobExecutionStatus = WorkflowRunJobExecutionDetailDto['status'];\nexport type JobExecutionTime =\n | {state: 'fixed'; elapsed: Duration}\n | {state: 'live'; fromIso: string};\nexport type JobExecutionDisplayDuration =\n | ({kind: 'queue'} & JobExecutionTime)\n | ({kind: 'run'} & JobExecutionTime);\n\ninterface JobExecutionFields {\n id: string;\n jobId: string;\n sequence: number;\n name: string;\n status: JobExecutionStatus;\n statusReason: string | null;\n triggerEvents: WorkflowExecutionEventDto[];\n queuedAt: string | null;\n startedAt: string | null;\n finishedAt: string | null;\n timedOutAt: string | null;\n createdAt: string;\n updatedAt: string;\n steps: Step[];\n}\n\nexport class JobExecution {\n id!: string;\n jobId!: string;\n sequence!: number;\n name!: string;\n status!: JobExecutionStatus;\n statusReason!: string | null;\n triggerEvents!: WorkflowExecutionEventDto[];\n queuedAt!: string | null;\n startedAt!: string | null;\n finishedAt!: string | null;\n timedOutAt!: string | null;\n createdAt!: string;\n updatedAt!: string;\n steps!: Step[];\n\n constructor(fields: JobExecutionFields) {\n Object.assign(this, fields);\n }\n\n get queueTime(): JobExecutionTime | null {\n return jobExecutionQueueTimeFromTimestamps(this);\n }\n\n get runTime(): JobExecutionTime | null {\n return jobExecutionRunTimeFromTimestamps(this);\n }\n\n get displayDuration(): JobExecutionDisplayDuration | null {\n return jobExecutionDisplayDurationFromTimestamps(this);\n }\n}\n\nexport function toJobExecution(dto: WorkflowRunJobExecutionDetailDto): JobExecution {\n return new JobExecution({\n id: dto.id,\n jobId: dto.job_id,\n sequence: dto.sequence,\n name: dto.name,\n status: dto.status,\n statusReason: dto.status_reason,\n triggerEvents: dto.trigger_events ?? [],\n queuedAt: dto.queued_at ?? null,\n startedAt: dto.started_at ?? null,\n finishedAt: dto.finished_at ?? null,\n timedOutAt: dto.timed_out_at ?? null,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n steps: dto.steps.map(toStep),\n });\n}\n\nexport function jobExecutionQueueTimeFromTimestamps({\n queuedAt,\n startedAt,\n finishedAt,\n}: {\n queuedAt: string | null;\n startedAt: string | null;\n finishedAt: string | null;\n}): JobExecutionTime | null {\n if (queuedAt === null) return null;\n if (finishedAt !== null && startedAt === null) return null;\n if (startedAt === null) return {state: 'live', fromIso: queuedAt};\n\n const elapsed = durationBetween(queuedAt, startedAt);\n return elapsed === null ? null : {state: 'fixed', elapsed};\n}\n\nexport function jobExecutionRunTimeFromTimestamps({\n startedAt,\n finishedAt,\n}: {\n startedAt: string | null;\n finishedAt: string | null;\n}): JobExecutionTime | null {\n if (startedAt === null) return null;\n if (finishedAt === null) return {state: 'live', fromIso: startedAt};\n\n const elapsed = durationBetween(startedAt, finishedAt);\n return elapsed === null ? null : {state: 'fixed', elapsed};\n}\n\nexport function jobExecutionDisplayDurationFromTimestamps(timestamps: {\n queuedAt: string | null;\n startedAt: string | null;\n finishedAt: string | null;\n}): JobExecutionDisplayDuration | null {\n const runTime = jobExecutionRunTimeFromTimestamps(timestamps);\n if (runTime !== null) return {kind: 'run', ...runTime};\n\n const queueTime = jobExecutionQueueTimeFromTimestamps(timestamps);\n if (queueTime !== null) return {kind: 'queue', ...queueTime};\n\n return null;\n}\n\nfunction durationBetween(from: string, to: string): Duration | null {\n const start = new Date(from);\n const end = new Date(to);\n if (!Number.isFinite(start.getTime()) || !Number.isFinite(end.getTime())) return null;\n\n return intervalToDuration({\n start,\n end: end < start ? start : end,\n });\n}\n"],"names":["intervalToDuration","toStep","JobExecution","fields","Object","assign","queueTime","jobExecutionQueueTimeFromTimestamps","runTime","jobExecutionRunTimeFromTimestamps","displayDuration","jobExecutionDisplayDurationFromTimestamps","toJobExecution","dto","id","jobId","job_id","sequence","name","status","statusReason","status_reason","triggerEvents","trigger_events","queuedAt","queued_at","startedAt","started_at","finishedAt","finished_at","timedOutAt","timed_out_at","createdAt","created_at","updatedAt","updated_at","steps","map","state","fromIso","elapsed","durationBetween","timestamps","kind","from","to","start","Date","end","Number","isFinite","getTime"],"mappings":"AAIA,SAAuBA,kBAAkB,QAAO,WAAW;AAC3D,SAAmBC,MAAM,QAAO,YAAY;AA2B5C,OAAO,MAAMC;IAgBX,YAAYC,MAA0B,CAAE;QACtCC,OAAOC,MAAM,CAAC,IAAI,EAAEF;IACtB;IAEA,IAAIG,YAAqC;QACvC,OAAOC,oCAAoC,IAAI;IACjD;IAEA,IAAIC,UAAmC;QACrC,OAAOC,kCAAkC,IAAI;IAC/C;IAEA,IAAIC,kBAAsD;QACxD,OAAOC,0CAA0C,IAAI;IACvD;AACF;AAEA,OAAO,SAASC,eAAeC,GAAqC;IAClE,OAAO,IAAIX,aAAa;QACtBY,IAAID,IAAIC,EAAE;QACVC,OAAOF,IAAIG,MAAM;QACjBC,UAAUJ,IAAII,QAAQ;QACtBC,MAAML,IAAIK,IAAI;QACdC,QAAQN,IAAIM,MAAM;QAClBC,cAAcP,IAAIQ,aAAa;QAC/BC,eAAeT,IAAIU,cAAc,IAAI,EAAE;QACvCC,UAAUX,IAAIY,SAAS,IAAI;QAC3BC,WAAWb,IAAIc,UAAU,IAAI;QAC7BC,YAAYf,IAAIgB,WAAW,IAAI;QAC/BC,YAAYjB,IAAIkB,YAAY,IAAI;QAChCC,WAAWnB,IAAIoB,UAAU;QACzBC,WAAWrB,IAAIsB,UAAU;QACzBC,OAAOvB,IAAIuB,KAAK,CAACC,GAAG,CAACpC;IACvB;AACF;AAEA,OAAO,SAASM,oCAAoC,EAClDiB,QAAQ,EACRE,SAAS,EACTE,UAAU,EAKX;IACC,IAAIJ,aAAa,MAAM,OAAO;IAC9B,IAAII,eAAe,QAAQF,cAAc,MAAM,OAAO;IACtD,IAAIA,cAAc,MAAM,OAAO;QAACY,OAAO;QAAQC,SAASf;IAAQ;IAEhE,MAAMgB,UAAUC,gBAAgBjB,UAAUE;IAC1C,OAAOc,YAAY,OAAO,OAAO;QAACF,OAAO;QAASE;IAAO;AAC3D;AAEA,OAAO,SAAS/B,kCAAkC,EAChDiB,SAAS,EACTE,UAAU,EAIX;IACC,IAAIF,cAAc,MAAM,OAAO;IAC/B,IAAIE,eAAe,MAAM,OAAO;QAACU,OAAO;QAAQC,SAASb;IAAS;IAElE,MAAMc,UAAUC,gBAAgBf,WAAWE;IAC3C,OAAOY,YAAY,OAAO,OAAO;QAACF,OAAO;QAASE;IAAO;AAC3D;AAEA,OAAO,SAAS7B,0CAA0C+B,UAIzD;IACC,MAAMlC,UAAUC,kCAAkCiC;IAClD,IAAIlC,YAAY,MAAM,OAAO;QAACmC,MAAM;QAAO,GAAGnC,OAAO;IAAA;IAErD,MAAMF,YAAYC,oCAAoCmC;IACtD,IAAIpC,cAAc,MAAM,OAAO;QAACqC,MAAM;QAAS,GAAGrC,SAAS;IAAA;IAE3D,OAAO;AACT;AAEA,SAASmC,gBAAgBG,IAAY,EAAEC,EAAU;IAC/C,MAAMC,QAAQ,IAAIC,KAAKH;IACvB,MAAMI,MAAM,IAAID,KAAKF;IACrB,IAAI,CAACI,OAAOC,QAAQ,CAACJ,MAAMK,OAAO,OAAO,CAACF,OAAOC,QAAQ,CAACF,IAAIG,OAAO,KAAK,OAAO;IAEjF,OAAOnD,mBAAmB;QACxB8C;QACAE,KAAKA,MAAMF,QAAQA,QAAQE;IAC7B;AACF"}
@@ -0,0 +1,56 @@
1
+ import type { JobListeningDto, JobModeDto, JobStatusDto, JobStatusReasonDto, ListenerStatusDto, ResolutionReasonDto, WorkflowRunJobDetailDto } from '@shipfox/api-workflows-dto';
2
+ import { type JobExecution, type JobExecutionDisplayDuration } from './job-execution.js';
3
+ export type JobStatus = JobStatusDto;
4
+ export type JobMode = JobModeDto;
5
+ export type ListenerStatus = ListenerStatusDto;
6
+ export type ResolutionReason = ResolutionReasonDto;
7
+ export type JobStatusReason = JobStatusReasonDto;
8
+ export type JobDisplayDuration = JobExecutionDisplayDuration;
9
+ export declare const WORKFLOW_JOB_STATUSES: readonly ["pending", "running", "succeeded", "failed", "cancelled", "skipped"];
10
+ export declare const TERMINAL_WORKFLOW_JOB_STATUSES: readonly ["succeeded", "failed", "cancelled", "skipped"];
11
+ interface JobFields {
12
+ id: string;
13
+ runAttemptId: string;
14
+ key: string;
15
+ name: string | null;
16
+ mode: JobMode;
17
+ status: JobStatus;
18
+ statusReason: JobStatusReason | null;
19
+ carriedOver: boolean;
20
+ listening: JobListeningDto | null;
21
+ listenerStatus: ListenerStatus;
22
+ resolutionReason: ResolutionReason | null;
23
+ dependencies: string[];
24
+ position: number;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ jobExecutions: JobExecution[];
28
+ }
29
+ export declare class Job {
30
+ id: string;
31
+ runAttemptId: string;
32
+ key: string;
33
+ name: string | null;
34
+ mode: JobMode;
35
+ status: JobStatus;
36
+ statusReason: JobStatusReason | null;
37
+ carriedOver: boolean;
38
+ listening: JobListeningDto | null;
39
+ listenerStatus: ListenerStatus;
40
+ resolutionReason: ResolutionReason | null;
41
+ dependencies: string[];
42
+ position: number;
43
+ createdAt: string;
44
+ updatedAt: string;
45
+ jobExecutions: JobExecution[];
46
+ constructor(fields: JobFields);
47
+ get displayName(): string;
48
+ get displayDuration(): JobDisplayDuration | null;
49
+ get executionCountVisible(): boolean;
50
+ }
51
+ export declare function isTerminalJobStatus(status: JobStatus): boolean;
52
+ export declare function resolveJobExecution(job: Job, jobExecutionId: string | undefined): JobExecution | undefined;
53
+ export declare function defaultJobExecution(job: Job): JobExecution | undefined;
54
+ export declare function toJob(dto: WorkflowRunJobDetailDto): Job;
55
+ export {};
56
+ //# sourceMappingURL=job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../../../src/core/entities/job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,2BAA2B,EAEjC,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC;AACrC,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC;AACjC,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAC/C,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAEjD,MAAM,MAAM,kBAAkB,GAAG,2BAA2B,CAAC;AAE7D,eAAO,MAAM,qBAAqB,gFAOO,CAAC;AAE1C,eAAO,MAAM,8BAA8B,0DAKF,CAAC;AAI1C,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,qBAAa,GAAG;IACd,EAAE,EAAG,MAAM,CAAC;IACZ,YAAY,EAAG,MAAM,CAAC;IACtB,GAAG,EAAG,MAAM,CAAC;IACb,IAAI,EAAG,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAG,OAAO,CAAC;IACf,MAAM,EAAG,SAAS,CAAC;IACnB,YAAY,EAAG,eAAe,GAAG,IAAI,CAAC;IACtC,WAAW,EAAG,OAAO,CAAC;IACtB,SAAS,EAAG,eAAe,GAAG,IAAI,CAAC;IACnC,cAAc,EAAG,cAAc,CAAC;IAChC,gBAAgB,EAAG,gBAAgB,GAAG,IAAI,CAAC;IAC3C,YAAY,EAAG,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAG,MAAM,CAAC;IAClB,SAAS,EAAG,MAAM,CAAC;IACnB,SAAS,EAAG,MAAM,CAAC;IACnB,aAAa,EAAG,YAAY,EAAE,CAAC;gBAEnB,MAAM,EAAE,SAAS;IAI7B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,eAAe,IAAI,kBAAkB,GAAG,IAAI,CAI/C;IAED,IAAI,qBAAqB,IAAI,OAAO,CAInC;CACF;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAE9D;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,GAAG,EACR,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,YAAY,GAAG,SAAS,CAO1B;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,YAAY,GAAG,SAAS,CAUtE;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,uBAAuB,GAAG,GAAG,CAqBvD"}
@@ -0,0 +1,71 @@
1
+ import { toJobExecution } from './job-execution.js';
2
+ export const WORKFLOW_JOB_STATUSES = [
3
+ 'pending',
4
+ 'running',
5
+ 'succeeded',
6
+ 'failed',
7
+ 'cancelled',
8
+ 'skipped'
9
+ ];
10
+ export const TERMINAL_WORKFLOW_JOB_STATUSES = [
11
+ 'succeeded',
12
+ 'failed',
13
+ 'cancelled',
14
+ 'skipped'
15
+ ];
16
+ const TERMINAL_JOB_STATUS_SET = new Set(TERMINAL_WORKFLOW_JOB_STATUSES);
17
+ export class Job {
18
+ constructor(fields){
19
+ Object.assign(this, fields);
20
+ }
21
+ get displayName() {
22
+ return this.name || this.key;
23
+ }
24
+ get displayDuration() {
25
+ if (this.mode === 'listening') return null;
26
+ if (this.jobExecutions.length !== 1) return null;
27
+ return this.jobExecutions[0]?.displayDuration ?? null;
28
+ }
29
+ get executionCountVisible() {
30
+ return this.jobExecutions.length > 0 && (this.mode === 'listening' || this.jobExecutions.length > 1);
31
+ }
32
+ }
33
+ export function isTerminalJobStatus(status) {
34
+ return TERMINAL_JOB_STATUS_SET.has(status);
35
+ }
36
+ export function resolveJobExecution(job, jobExecutionId) {
37
+ const selectedExecution = jobExecutionId ? job.jobExecutions.find((jobExecution)=>jobExecution.id === jobExecutionId) : undefined;
38
+ if (selectedExecution) return selectedExecution;
39
+ return defaultJobExecution(job);
40
+ }
41
+ export function defaultJobExecution(job) {
42
+ const runningExecution = job.jobExecutions.find((jobExecution)=>jobExecution.status === 'running');
43
+ if (runningExecution) return runningExecution;
44
+ return job.jobExecutions.reduce((latest, jobExecution)=>{
45
+ if (!latest) return jobExecution;
46
+ return jobExecution.sequence > latest.sequence ? jobExecution : latest;
47
+ }, undefined);
48
+ }
49
+ export function toJob(dto) {
50
+ const jobExecutions = dto.job_executions.map(toJobExecution);
51
+ return new Job({
52
+ id: dto.id,
53
+ runAttemptId: dto.run_attempt_id,
54
+ key: dto.key,
55
+ name: dto.name,
56
+ mode: dto.mode,
57
+ status: dto.status,
58
+ statusReason: dto.status_reason,
59
+ carriedOver: dto.carried_over,
60
+ listening: dto.listening,
61
+ listenerStatus: dto.listener_status,
62
+ resolutionReason: dto.resolution_reason,
63
+ dependencies: dto.dependencies,
64
+ position: dto.position,
65
+ createdAt: dto.created_at,
66
+ updatedAt: dto.updated_at,
67
+ jobExecutions
68
+ });
69
+ }
70
+
71
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/job.ts"],"sourcesContent":["import type {\n JobListeningDto,\n JobModeDto,\n JobStatusDto,\n JobStatusReasonDto,\n ListenerStatusDto,\n ResolutionReasonDto,\n WorkflowRunJobDetailDto,\n} from '@shipfox/api-workflows-dto';\nimport {\n type JobExecution,\n type JobExecutionDisplayDuration,\n toJobExecution,\n} from './job-execution.js';\n\nexport type JobStatus = JobStatusDto;\nexport type JobMode = JobModeDto;\nexport type ListenerStatus = ListenerStatusDto;\nexport type ResolutionReason = ResolutionReasonDto;\nexport type JobStatusReason = JobStatusReasonDto;\n\nexport type JobDisplayDuration = JobExecutionDisplayDuration;\n\nexport const WORKFLOW_JOB_STATUSES = [\n 'pending',\n 'running',\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nexport const TERMINAL_WORKFLOW_JOB_STATUSES = [\n 'succeeded',\n 'failed',\n 'cancelled',\n 'skipped',\n] as const satisfies readonly JobStatus[];\n\nconst TERMINAL_JOB_STATUS_SET = new Set<JobStatus>(TERMINAL_WORKFLOW_JOB_STATUSES);\n\ninterface JobFields {\n id: string;\n runAttemptId: string;\n key: string;\n name: string | null;\n mode: JobMode;\n status: JobStatus;\n statusReason: JobStatusReason | null;\n carriedOver: boolean;\n listening: JobListeningDto | null;\n listenerStatus: ListenerStatus;\n resolutionReason: ResolutionReason | null;\n dependencies: string[];\n position: number;\n createdAt: string;\n updatedAt: string;\n jobExecutions: JobExecution[];\n}\n\nexport class Job {\n id!: string;\n runAttemptId!: string;\n key!: string;\n name!: string | null;\n mode!: JobMode;\n status!: JobStatus;\n statusReason!: JobStatusReason | null;\n carriedOver!: boolean;\n listening!: JobListeningDto | null;\n listenerStatus!: ListenerStatus;\n resolutionReason!: ResolutionReason | null;\n dependencies!: string[];\n position!: number;\n createdAt!: string;\n updatedAt!: string;\n jobExecutions!: JobExecution[];\n\n constructor(fields: JobFields) {\n Object.assign(this, fields);\n }\n\n get displayName(): string {\n return this.name || this.key;\n }\n\n get displayDuration(): JobDisplayDuration | null {\n if (this.mode === 'listening') return null;\n if (this.jobExecutions.length !== 1) return null;\n return this.jobExecutions[0]?.displayDuration ?? null;\n }\n\n get executionCountVisible(): boolean {\n return (\n this.jobExecutions.length > 0 && (this.mode === 'listening' || this.jobExecutions.length > 1)\n );\n }\n}\n\nexport function isTerminalJobStatus(status: JobStatus): boolean {\n return TERMINAL_JOB_STATUS_SET.has(status);\n}\n\nexport function resolveJobExecution(\n job: Job,\n jobExecutionId: string | undefined,\n): JobExecution | undefined {\n const selectedExecution = jobExecutionId\n ? job.jobExecutions.find((jobExecution) => jobExecution.id === jobExecutionId)\n : undefined;\n if (selectedExecution) return selectedExecution;\n\n return defaultJobExecution(job);\n}\n\nexport function defaultJobExecution(job: Job): JobExecution | undefined {\n const runningExecution = job.jobExecutions.find(\n (jobExecution) => jobExecution.status === 'running',\n );\n if (runningExecution) return runningExecution;\n\n return job.jobExecutions.reduce<JobExecution | undefined>((latest, jobExecution) => {\n if (!latest) return jobExecution;\n return jobExecution.sequence > latest.sequence ? jobExecution : latest;\n }, undefined);\n}\n\nexport function toJob(dto: WorkflowRunJobDetailDto): Job {\n const jobExecutions = dto.job_executions.map(toJobExecution);\n\n return new Job({\n id: dto.id,\n runAttemptId: dto.run_attempt_id,\n key: dto.key,\n name: dto.name,\n mode: dto.mode,\n status: dto.status,\n statusReason: dto.status_reason,\n carriedOver: dto.carried_over,\n listening: dto.listening,\n listenerStatus: dto.listener_status,\n resolutionReason: dto.resolution_reason,\n dependencies: dto.dependencies,\n position: dto.position,\n createdAt: dto.created_at,\n updatedAt: dto.updated_at,\n jobExecutions,\n });\n}\n"],"names":["toJobExecution","WORKFLOW_JOB_STATUSES","TERMINAL_WORKFLOW_JOB_STATUSES","TERMINAL_JOB_STATUS_SET","Set","Job","fields","Object","assign","displayName","name","key","displayDuration","mode","jobExecutions","length","executionCountVisible","isTerminalJobStatus","status","has","resolveJobExecution","job","jobExecutionId","selectedExecution","find","jobExecution","id","undefined","defaultJobExecution","runningExecution","reduce","latest","sequence","toJob","dto","job_executions","map","runAttemptId","run_attempt_id","statusReason","status_reason","carriedOver","carried_over","listening","listenerStatus","listener_status","resolutionReason","resolution_reason","dependencies","position","createdAt","created_at","updatedAt","updated_at"],"mappings":"AASA,SAGEA,cAAc,QACT,qBAAqB;AAU5B,OAAO,MAAMC,wBAAwB;IACnC;IACA;IACA;IACA;IACA;IACA;CACD,CAAyC;AAE1C,OAAO,MAAMC,iCAAiC;IAC5C;IACA;IACA;IACA;CACD,CAAyC;AAE1C,MAAMC,0BAA0B,IAAIC,IAAeF;AAqBnD,OAAO,MAAMG;IAkBX,YAAYC,MAAiB,CAAE;QAC7BC,OAAOC,MAAM,CAAC,IAAI,EAAEF;IACtB;IAEA,IAAIG,cAAsB;QACxB,OAAO,IAAI,CAACC,IAAI,IAAI,IAAI,CAACC,GAAG;IAC9B;IAEA,IAAIC,kBAA6C;QAC/C,IAAI,IAAI,CAACC,IAAI,KAAK,aAAa,OAAO;QACtC,IAAI,IAAI,CAACC,aAAa,CAACC,MAAM,KAAK,GAAG,OAAO;QAC5C,OAAO,IAAI,CAACD,aAAa,CAAC,EAAE,EAAEF,mBAAmB;IACnD;IAEA,IAAII,wBAAiC;QACnC,OACE,IAAI,CAACF,aAAa,CAACC,MAAM,GAAG,KAAM,CAAA,IAAI,CAACF,IAAI,KAAK,eAAe,IAAI,CAACC,aAAa,CAACC,MAAM,GAAG,CAAA;IAE/F;AACF;AAEA,OAAO,SAASE,oBAAoBC,MAAiB;IACnD,OAAOf,wBAAwBgB,GAAG,CAACD;AACrC;AAEA,OAAO,SAASE,oBACdC,GAAQ,EACRC,cAAkC;IAElC,MAAMC,oBAAoBD,iBACtBD,IAAIP,aAAa,CAACU,IAAI,CAAC,CAACC,eAAiBA,aAAaC,EAAE,KAAKJ,kBAC7DK;IACJ,IAAIJ,mBAAmB,OAAOA;IAE9B,OAAOK,oBAAoBP;AAC7B;AAEA,OAAO,SAASO,oBAAoBP,GAAQ;IAC1C,MAAMQ,mBAAmBR,IAAIP,aAAa,CAACU,IAAI,CAC7C,CAACC,eAAiBA,aAAaP,MAAM,KAAK;IAE5C,IAAIW,kBAAkB,OAAOA;IAE7B,OAAOR,IAAIP,aAAa,CAACgB,MAAM,CAA2B,CAACC,QAAQN;QACjE,IAAI,CAACM,QAAQ,OAAON;QACpB,OAAOA,aAAaO,QAAQ,GAAGD,OAAOC,QAAQ,GAAGP,eAAeM;IAClE,GAAGJ;AACL;AAEA,OAAO,SAASM,MAAMC,GAA4B;IAChD,MAAMpB,gBAAgBoB,IAAIC,cAAc,CAACC,GAAG,CAACpC;IAE7C,OAAO,IAAIK,IAAI;QACbqB,IAAIQ,IAAIR,EAAE;QACVW,cAAcH,IAAII,cAAc;QAChC3B,KAAKuB,IAAIvB,GAAG;QACZD,MAAMwB,IAAIxB,IAAI;QACdG,MAAMqB,IAAIrB,IAAI;QACdK,QAAQgB,IAAIhB,MAAM;QAClBqB,cAAcL,IAAIM,aAAa;QAC/BC,aAAaP,IAAIQ,YAAY;QAC7BC,WAAWT,IAAIS,SAAS;QACxBC,gBAAgBV,IAAIW,eAAe;QACnCC,kBAAkBZ,IAAIa,iBAAiB;QACvCC,cAAcd,IAAIc,YAAY;QAC9BC,UAAUf,IAAIe,QAAQ;QACtBC,WAAWhB,IAAIiB,UAAU;QACzBC,WAAWlB,IAAImB,UAAU;QACzBvC;IACF;AACF"}
@@ -0,0 +1,49 @@
1
+ import type { StepAttemptDto, StepGateResultDto } from '@shipfox/api-workflows-dto';
2
+ import { type Duration } from 'date-fns';
3
+ export type StepGateResult = StepGateResultDto;
4
+ export type StepAttemptDisplayDuration = {
5
+ state: 'fixed';
6
+ elapsed: Duration;
7
+ } | {
8
+ state: 'live';
9
+ fromIso: string;
10
+ };
11
+ interface StepAttemptFields {
12
+ id: string;
13
+ stepId: string;
14
+ jobExecutionId: string;
15
+ attempt: number;
16
+ executionOrder: number;
17
+ status: string;
18
+ exitCode: number | null;
19
+ output: Record<string, unknown> | null;
20
+ error: Record<string, unknown> | null;
21
+ gateResult: StepGateResult;
22
+ restartFeedback: string | null;
23
+ startedAt: string;
24
+ finishedAt: string | null;
25
+ }
26
+ export declare class StepAttempt {
27
+ id: string;
28
+ stepId: string;
29
+ jobExecutionId: string;
30
+ attempt: number;
31
+ executionOrder: number;
32
+ status: string;
33
+ exitCode: number | null;
34
+ output: Record<string, unknown> | null;
35
+ error: Record<string, unknown> | null;
36
+ gateResult: StepGateResult;
37
+ restartFeedback: string | null;
38
+ startedAt: string;
39
+ finishedAt: string | null;
40
+ constructor(fields: StepAttemptFields);
41
+ get displayDuration(): StepAttemptDisplayDuration | null;
42
+ }
43
+ export declare function toStepAttempt(dto: StepAttemptDto, jobExecutionId: string): StepAttempt;
44
+ export declare function stepAttemptDisplayDurationFromTimestamps({ startedAt, finishedAt, }: {
45
+ startedAt: string;
46
+ finishedAt: string | null;
47
+ }): StepAttemptDisplayDuration | null;
48
+ export {};
49
+ //# sourceMappingURL=step-attempt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-attempt.d.ts","sourceRoot":"","sources":["../../../src/core/entities/step-attempt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,cAAc,EAAE,iBAAiB,EAAC,MAAM,4BAA4B,CAAC;AAClF,OAAO,EAAC,KAAK,QAAQ,EAAqB,MAAM,UAAU,CAAC;AAE3D,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAC/C,MAAM,MAAM,0BAA0B,GAClC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAC,GACnC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,CAAC;AAErC,UAAU,iBAAiB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,cAAc,CAAC;IAC3B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,qBAAa,WAAW;IACtB,EAAE,EAAG,MAAM,CAAC;IACZ,MAAM,EAAG,MAAM,CAAC;IAChB,cAAc,EAAG,MAAM,CAAC;IACxB,OAAO,EAAG,MAAM,CAAC;IACjB,cAAc,EAAG,MAAM,CAAC;IACxB,MAAM,EAAG,MAAM,CAAC;IAChB,QAAQ,EAAG,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,KAAK,EAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvC,UAAU,EAAG,cAAc,CAAC;IAC5B,eAAe,EAAG,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAG,MAAM,CAAC;IACnB,UAAU,EAAG,MAAM,GAAG,IAAI,CAAC;gBAEf,MAAM,EAAE,iBAAiB;IAIrC,IAAI,eAAe,IAAI,0BAA0B,GAAG,IAAI,CAEvD;CACF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,GAAG,WAAW,CAgBtF;AAED,wBAAgB,wCAAwC,CAAC,EACvD,SAAS,EACT,UAAU,GACX,EAAE;IACD,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,GAAG,0BAA0B,GAAG,IAAI,CAKpC"}
@@ -0,0 +1,48 @@
1
+ import { intervalToDuration } from 'date-fns';
2
+ export class StepAttempt {
3
+ constructor(fields){
4
+ Object.assign(this, fields);
5
+ }
6
+ get displayDuration() {
7
+ return stepAttemptDisplayDurationFromTimestamps(this);
8
+ }
9
+ }
10
+ export function toStepAttempt(dto, jobExecutionId) {
11
+ return new StepAttempt({
12
+ id: dto.id,
13
+ stepId: dto.step_id,
14
+ jobExecutionId,
15
+ attempt: dto.attempt,
16
+ executionOrder: dto.execution_order,
17
+ status: dto.status,
18
+ exitCode: dto.exit_code ?? null,
19
+ output: dto.output ?? null,
20
+ error: dto.error ?? null,
21
+ gateResult: dto.gate_result ?? null,
22
+ restartFeedback: dto.restart_feedback ?? null,
23
+ startedAt: dto.started_at,
24
+ finishedAt: dto.finished_at ?? null
25
+ });
26
+ }
27
+ export function stepAttemptDisplayDurationFromTimestamps({ startedAt, finishedAt }) {
28
+ if (finishedAt === null) return {
29
+ state: 'live',
30
+ fromIso: startedAt
31
+ };
32
+ const elapsed = durationBetween(startedAt, finishedAt);
33
+ return elapsed === null ? null : {
34
+ state: 'fixed',
35
+ elapsed
36
+ };
37
+ }
38
+ function durationBetween(from, to) {
39
+ const start = new Date(from);
40
+ const end = new Date(to);
41
+ if (!Number.isFinite(start.getTime()) || !Number.isFinite(end.getTime())) return null;
42
+ return intervalToDuration({
43
+ start,
44
+ end: end < start ? start : end
45
+ });
46
+ }
47
+
48
+ //# sourceMappingURL=step-attempt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/entities/step-attempt.ts"],"sourcesContent":["import type {StepAttemptDto, StepGateResultDto} from '@shipfox/api-workflows-dto';\nimport {type Duration, intervalToDuration} from 'date-fns';\n\nexport type StepGateResult = StepGateResultDto;\nexport type StepAttemptDisplayDuration =\n | {state: 'fixed'; elapsed: Duration}\n | {state: 'live'; fromIso: string};\n\ninterface StepAttemptFields {\n id: string;\n stepId: string;\n jobExecutionId: string;\n attempt: number;\n executionOrder: number;\n status: string;\n exitCode: number | null;\n output: Record<string, unknown> | null;\n error: Record<string, unknown> | null;\n gateResult: StepGateResult;\n restartFeedback: string | null;\n startedAt: string;\n finishedAt: string | null;\n}\n\nexport class StepAttempt {\n id!: string;\n stepId!: string;\n jobExecutionId!: string;\n attempt!: number;\n executionOrder!: number;\n status!: string;\n exitCode!: number | null;\n output!: Record<string, unknown> | null;\n error!: Record<string, unknown> | null;\n gateResult!: StepGateResult;\n restartFeedback!: string | null;\n startedAt!: string;\n finishedAt!: string | null;\n\n constructor(fields: StepAttemptFields) {\n Object.assign(this, fields);\n }\n\n get displayDuration(): StepAttemptDisplayDuration | null {\n return stepAttemptDisplayDurationFromTimestamps(this);\n }\n}\n\nexport function toStepAttempt(dto: StepAttemptDto, jobExecutionId: string): StepAttempt {\n return new StepAttempt({\n id: dto.id,\n stepId: dto.step_id,\n jobExecutionId,\n attempt: dto.attempt,\n executionOrder: dto.execution_order,\n status: dto.status,\n exitCode: dto.exit_code ?? null,\n output: dto.output ?? null,\n error: dto.error ?? null,\n gateResult: dto.gate_result ?? null,\n restartFeedback: dto.restart_feedback ?? null,\n startedAt: dto.started_at,\n finishedAt: dto.finished_at ?? null,\n });\n}\n\nexport function stepAttemptDisplayDurationFromTimestamps({\n startedAt,\n finishedAt,\n}: {\n startedAt: string;\n finishedAt: string | null;\n}): StepAttemptDisplayDuration | null {\n if (finishedAt === null) return {state: 'live', fromIso: startedAt};\n\n const elapsed = durationBetween(startedAt, finishedAt);\n return elapsed === null ? null : {state: 'fixed', elapsed};\n}\n\nfunction durationBetween(from: string, to: string): Duration | null {\n const start = new Date(from);\n const end = new Date(to);\n if (!Number.isFinite(start.getTime()) || !Number.isFinite(end.getTime())) return null;\n\n return intervalToDuration({\n start,\n end: end < start ? start : end,\n });\n}\n"],"names":["intervalToDuration","StepAttempt","fields","Object","assign","displayDuration","stepAttemptDisplayDurationFromTimestamps","toStepAttempt","dto","jobExecutionId","id","stepId","step_id","attempt","executionOrder","execution_order","status","exitCode","exit_code","output","error","gateResult","gate_result","restartFeedback","restart_feedback","startedAt","started_at","finishedAt","finished_at","state","fromIso","elapsed","durationBetween","from","to","start","Date","end","Number","isFinite","getTime"],"mappings":"AACA,SAAuBA,kBAAkB,QAAO,WAAW;AAuB3D,OAAO,MAAMC;IAeX,YAAYC,MAAyB,CAAE;QACrCC,OAAOC,MAAM,CAAC,IAAI,EAAEF;IACtB;IAEA,IAAIG,kBAAqD;QACvD,OAAOC,yCAAyC,IAAI;IACtD;AACF;AAEA,OAAO,SAASC,cAAcC,GAAmB,EAAEC,cAAsB;IACvE,OAAO,IAAIR,YAAY;QACrBS,IAAIF,IAAIE,EAAE;QACVC,QAAQH,IAAII,OAAO;QACnBH;QACAI,SAASL,IAAIK,OAAO;QACpBC,gBAAgBN,IAAIO,eAAe;QACnCC,QAAQR,IAAIQ,MAAM;QAClBC,UAAUT,IAAIU,SAAS,IAAI;QAC3BC,QAAQX,IAAIW,MAAM,IAAI;QACtBC,OAAOZ,IAAIY,KAAK,IAAI;QACpBC,YAAYb,IAAIc,WAAW,IAAI;QAC/BC,iBAAiBf,IAAIgB,gBAAgB,IAAI;QACzCC,WAAWjB,IAAIkB,UAAU;QACzBC,YAAYnB,IAAIoB,WAAW,IAAI;IACjC;AACF;AAEA,OAAO,SAAStB,yCAAyC,EACvDmB,SAAS,EACTE,UAAU,EAIX;IACC,IAAIA,eAAe,MAAM,OAAO;QAACE,OAAO;QAAQC,SAASL;IAAS;IAElE,MAAMM,UAAUC,gBAAgBP,WAAWE;IAC3C,OAAOI,YAAY,OAAO,OAAO;QAACF,OAAO;QAASE;IAAO;AAC3D;AAEA,SAASC,gBAAgBC,IAAY,EAAEC,EAAU;IAC/C,MAAMC,QAAQ,IAAIC,KAAKH;IACvB,MAAMI,MAAM,IAAID,KAAKF;IACrB,IAAI,CAACI,OAAOC,QAAQ,CAACJ,MAAMK,OAAO,OAAO,CAACF,OAAOC,QAAQ,CAACF,IAAIG,OAAO,KAAK,OAAO;IAEjF,OAAOxC,mBAAmB;QACxBmC;QACAE,KAAKA,MAAMF,QAAQA,QAAQE;IAC7B;AACF"}
@@ -0,0 +1,41 @@
1
+ import type { AgentConfigIssueDto, StepErrorCategoryDto, StepErrorReasonDto, WorkflowRunStepDetailDto } from '@shipfox/api-workflows-dto';
2
+ import { type StepAttempt } from './step-attempt.js';
3
+ export type StepErrorReason = StepErrorReasonDto;
4
+ export type AgentConfigIssue = AgentConfigIssueDto;
5
+ export type StepErrorCategory = StepErrorCategoryDto;
6
+ export interface StepSourceLocation {
7
+ startLine: number;
8
+ endLine: number;
9
+ }
10
+ export interface StepError {
11
+ message: string;
12
+ exitCode: number | null;
13
+ signal: string | undefined;
14
+ reason: StepErrorReason | undefined;
15
+ agentConfigIssue: AgentConfigIssue | undefined;
16
+ category: StepErrorCategory | undefined;
17
+ }
18
+ export interface AgentStepConfig {
19
+ provider: string | null;
20
+ model: string | null;
21
+ thinking: string | null;
22
+ }
23
+ export interface Step {
24
+ id: string;
25
+ jobExecutionId: string;
26
+ key: string | null;
27
+ name: string;
28
+ sourceLocation: StepSourceLocation | null;
29
+ status: string;
30
+ type: string;
31
+ config: Record<string, unknown>;
32
+ agentConfig: AgentStepConfig | null;
33
+ error: StepError | null;
34
+ position: number;
35
+ currentAttempt: number;
36
+ createdAt: string;
37
+ updatedAt: string;
38
+ attempts: StepAttempt[];
39
+ }
40
+ export declare function toStep(dto: WorkflowRunStepDetailDto): Step;
41
+ //# sourceMappingURL=step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../../src/core/entities/step.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAElB,wBAAwB,EACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAC,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,eAAe,GAAG,kBAAkB,CAAC;AACjD,MAAM,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACnD,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,EAAE,eAAe,GAAG,SAAS,CAAC;IACpC,gBAAgB,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC/C,QAAQ,EAAE,iBAAiB,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;IACpC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,wBAAwB,GAAG,IAAI,CAkB1D"}