@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.
- package/.storybook/main.ts +1 -0
- package/.storybook/preview.css +10 -0
- package/.storybook/preview.tsx +97 -0
- package/.swcrc +42 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +162 -0
- package/LICENSE +21 -0
- package/dist/components/identifier/identifier.d.ts +6 -0
- package/dist/components/identifier/identifier.d.ts.map +1 -0
- package/dist/components/identifier/identifier.js +144 -0
- package/dist/components/identifier/identifier.js.map +1 -0
- package/dist/components/identifier/index.d.ts +2 -0
- package/dist/components/identifier/index.d.ts.map +1 -0
- package/dist/components/identifier/index.js +3 -0
- package/dist/components/identifier/index.js.map +1 -0
- package/dist/components/job-graph/graph-model.d.ts +27 -0
- package/dist/components/job-graph/graph-model.d.ts.map +1 -0
- package/dist/components/job-graph/graph-model.js +107 -0
- package/dist/components/job-graph/graph-model.js.map +1 -0
- package/dist/components/job-graph/index.d.ts +3 -0
- package/dist/components/job-graph/index.d.ts.map +1 -0
- package/dist/components/job-graph/index.js +3 -0
- package/dist/components/job-graph/index.js.map +1 -0
- package/dist/components/job-graph/job-duration-format.d.ts +4 -0
- package/dist/components/job-graph/job-duration-format.d.ts.map +1 -0
- package/dist/components/job-graph/job-duration-format.js +41 -0
- package/dist/components/job-graph/job-duration-format.js.map +1 -0
- package/dist/components/job-graph/job-duration-label.d.ts +5 -0
- package/dist/components/job-graph/job-duration-label.d.ts.map +1 -0
- package/dist/components/job-graph/job-duration-label.js +33 -0
- package/dist/components/job-graph/job-duration-label.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.d.ts +9 -0
- package/dist/components/job-graph/job-graph-content.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph-content.js +181 -0
- package/dist/components/job-graph/job-graph-content.js.map +1 -0
- package/dist/components/job-graph/job-graph-view.d.ts +11 -0
- package/dist/components/job-graph/job-graph-view.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph-view.js +24 -0
- package/dist/components/job-graph/job-graph-view.js.map +1 -0
- package/dist/components/job-graph/job-graph.d.ts +3 -0
- package/dist/components/job-graph/job-graph.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph.js +21 -0
- package/dist/components/job-graph/job-graph.js.map +1 -0
- package/dist/components/job-graph/job-node.d.ts +16 -0
- package/dist/components/job-graph/job-node.d.ts.map +1 -0
- package/dist/components/job-graph/job-node.js +196 -0
- package/dist/components/job-graph/job-node.js.map +1 -0
- package/dist/components/job-graph/types.d.ts +9 -0
- package/dist/components/job-graph/types.d.ts.map +1 -0
- package/dist/components/job-graph/types.js +3 -0
- package/dist/components/job-graph/types.js.map +1 -0
- package/dist/components/step-list/index.d.ts +3 -0
- package/dist/components/step-list/index.d.ts.map +1 -0
- package/dist/components/step-list/index.js +3 -0
- package/dist/components/step-list/index.js.map +1 -0
- package/dist/components/step-list/step-list-model.d.ts +36 -0
- package/dist/components/step-list/step-list-model.d.ts.map +1 -0
- package/dist/components/step-list/step-list-model.js +135 -0
- package/dist/components/step-list/step-list-model.js.map +1 -0
- package/dist/components/step-list/step-list.d.ts +32 -0
- package/dist/components/step-list/step-list.d.ts.map +1 -0
- package/dist/components/step-list/step-list.js +409 -0
- package/dist/components/step-list/step-list.js.map +1 -0
- package/dist/components/workflow-run-duration-label.d.ts +8 -0
- package/dist/components/workflow-run-duration-label.d.ts.map +1 -0
- package/dist/components/workflow-run-duration-label.js +84 -0
- package/dist/components/workflow-run-duration-label.js.map +1 -0
- package/dist/components/workflow-run-list/index.d.ts +2 -0
- package/dist/components/workflow-run-list/index.d.ts.map +1 -0
- package/dist/components/workflow-run-list/index.js +3 -0
- package/dist/components/workflow-run-list/index.js.map +1 -0
- package/dist/components/workflow-run-list/run-display.d.ts +5 -0
- package/dist/components/workflow-run-list/run-display.d.ts.map +1 -0
- package/dist/components/workflow-run-list/run-display.js +19 -0
- package/dist/components/workflow-run-list/run-display.js.map +1 -0
- package/dist/components/workflow-run-list/types.d.ts +21 -0
- package/dist/components/workflow-run-list/types.d.ts.map +1 -0
- package/dist/components/workflow-run-list/types.js +3 -0
- package/dist/components/workflow-run-list/types.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts +14 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.js +37 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts +10 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.js +55 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts +15 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.js +103 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts +3 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.js +46 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list.d.ts +3 -0
- package/dist/components/workflow-run-list/workflow-run-list.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list.js +20 -0
- package/dist/components/workflow-run-list/workflow-run-list.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-row.d.ts +14 -0
- package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-row.js +172 -0
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -0
- package/dist/components/workflow-run-summary/index.d.ts +2 -0
- package/dist/components/workflow-run-summary/index.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/index.js +3 -0
- package/dist/components/workflow-run-summary/index.js.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts +9 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +138 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +20 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.js +252 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts +7 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +1 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.js +84 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +1 -0
- package/dist/components/workflow-run-view/index.d.ts +3 -0
- package/dist/components/workflow-run-view/index.d.ts.map +1 -0
- package/dist/components/workflow-run-view/index.js +4 -0
- package/dist/components/workflow-run-view/index.js.map +1 -0
- package/dist/components/workflow-run-view/job-card.d.ts +17 -0
- package/dist/components/workflow-run-view/job-card.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-card.js +476 -0
- package/dist/components/workflow-run-view/job-card.js.map +1 -0
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts +10 -0
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-execution-switcher.js +171 -0
- package/dist/components/workflow-run-view/job-execution-switcher.js.map +1 -0
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts +6 -0
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-execution-time-text.js +24 -0
- package/dist/components/workflow-run-view/job-execution-time-text.js.map +1 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +9 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +1 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.js +152 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts +14 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.js +56 -0
- package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-states.d.ts +12 -0
- package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-states.js +91 -0
- package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +15 -0
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-view.js +285 -0
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -0
- package/dist/components/workflow-source-panel/index.d.ts +2 -0
- package/dist/components/workflow-source-panel/index.d.ts.map +1 -0
- package/dist/components/workflow-source-panel/index.js +3 -0
- package/dist/components/workflow-source-panel/index.js.map +1 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.d.ts +13 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.d.ts.map +1 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.js +91 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.js.map +1 -0
- package/dist/components/workflow-status/status-visuals.d.ts +12 -0
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -0
- package/dist/components/workflow-status/status-visuals.js +54 -0
- package/dist/components/workflow-status/status-visuals.js.map +1 -0
- package/dist/components/workflow-status/workflow-status-icon.d.ts +22 -0
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -0
- package/dist/components/workflow-status/workflow-status-icon.js +100 -0
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -0
- package/dist/core/entities/job-execution.d.ts +69 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -0
- package/dist/core/entities/job-execution.js +83 -0
- package/dist/core/entities/job-execution.js.map +1 -0
- package/dist/core/entities/job.d.ts +56 -0
- package/dist/core/entities/job.d.ts.map +1 -0
- package/dist/core/entities/job.js +71 -0
- package/dist/core/entities/job.js.map +1 -0
- package/dist/core/entities/step-attempt.d.ts +49 -0
- package/dist/core/entities/step-attempt.d.ts.map +1 -0
- package/dist/core/entities/step-attempt.js +48 -0
- package/dist/core/entities/step-attempt.js.map +1 -0
- package/dist/core/entities/step.d.ts +41 -0
- package/dist/core/entities/step.d.ts.map +1 -0
- package/dist/core/entities/step.js +51 -0
- package/dist/core/entities/step.js.map +1 -0
- package/dist/core/entities/workflow-run-attempt.d.ts +44 -0
- package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -0
- package/dist/core/entities/workflow-run-attempt.js +51 -0
- package/dist/core/entities/workflow-run-attempt.js.map +1 -0
- package/dist/core/entities/workflow-run.d.ts +61 -0
- package/dist/core/entities/workflow-run.d.ts.map +1 -0
- package/dist/core/entities/workflow-run.js +104 -0
- package/dist/core/entities/workflow-run.js.map +1 -0
- package/dist/core/workflow-run-url-state.d.ts +13 -0
- package/dist/core/workflow-run-url-state.d.ts.map +1 -0
- package/dist/core/workflow-run-url-state.js +43 -0
- package/dist/core/workflow-run-url-state.js.map +1 -0
- package/dist/core/workflow-run.d.ts +13 -0
- package/dist/core/workflow-run.d.ts.map +1 -0
- package/dist/core/workflow-run.js +8 -0
- package/dist/core/workflow-run.js.map +1 -0
- package/dist/env.d.js +2 -0
- package/dist/env.d.js.map +1 -0
- package/dist/feature.d.ts +20 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/feature.js +27 -0
- package/dist/feature.js.map +1 -0
- package/dist/hooks/api/workflow-runs.d.ts +109 -0
- package/dist/hooks/api/workflow-runs.d.ts.map +1 -0
- package/dist/hooks/api/workflow-runs.js +394 -0
- package/dist/hooks/api/workflow-runs.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/workflow-run-first-time-use.d.ts +6 -0
- package/dist/pages/workflow-run-first-time-use.d.ts.map +1 -0
- package/dist/pages/workflow-run-first-time-use.js +17 -0
- package/dist/pages/workflow-run-first-time-use.js.map +1 -0
- package/dist/pages/workflow-run-page.d.ts +8 -0
- package/dist/pages/workflow-run-page.d.ts.map +1 -0
- package/dist/pages/workflow-run-page.js +83 -0
- package/dist/pages/workflow-run-page.js.map +1 -0
- package/dist/routes/run-detail.d.ts +8 -0
- package/dist/routes/run-detail.d.ts.map +1 -0
- package/dist/routes/run-detail.js +21 -0
- package/dist/routes/run-detail.js.map +1 -0
- package/dist/routes/runs.d.ts +8 -0
- package/dist/routes/runs.d.ts.map +1 -0
- package/dist/routes/runs.js +20 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +114 -0
- package/src/components/identifier/identifier.tsx +178 -0
- package/src/components/identifier/index.ts +1 -0
- package/src/components/job-graph/graph-model.test.ts +189 -0
- package/src/components/job-graph/graph-model.ts +178 -0
- package/src/components/job-graph/index.ts +2 -0
- package/src/components/job-graph/job-duration-format.ts +54 -0
- package/src/components/job-graph/job-duration-label.tsx +29 -0
- package/src/components/job-graph/job-graph-content.tsx +225 -0
- package/src/components/job-graph/job-graph-view.test.tsx +298 -0
- package/src/components/job-graph/job-graph-view.tsx +45 -0
- package/src/components/job-graph/job-graph.stories.tsx +182 -0
- package/src/components/job-graph/job-graph.tsx +24 -0
- package/src/components/job-graph/job-node.stories.tsx +364 -0
- package/src/components/job-graph/job-node.test.tsx +347 -0
- package/src/components/job-graph/job-node.tsx +202 -0
- package/src/components/job-graph/types.ts +9 -0
- package/src/components/step-list/index.ts +6 -0
- package/src/components/step-list/step-list-model.test.ts +369 -0
- package/src/components/step-list/step-list-model.ts +205 -0
- package/src/components/step-list/step-list.stories.tsx +419 -0
- package/src/components/step-list/step-list.test.tsx +566 -0
- package/src/components/step-list/step-list.tsx +494 -0
- package/src/components/workflow-run-duration-label.tsx +118 -0
- package/src/components/workflow-run-list/index.ts +1 -0
- package/src/components/workflow-run-list/run-display.test.ts +53 -0
- package/src/components/workflow-run-list/run-display.ts +22 -0
- package/src/components/workflow-run-list/types.ts +22 -0
- package/src/components/workflow-run-list/workflow-run-list-content.tsx +58 -0
- package/src/components/workflow-run-list/workflow-run-list-header.tsx +53 -0
- package/src/components/workflow-run-list/workflow-run-list-states.tsx +86 -0
- package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +178 -0
- package/src/components/workflow-run-list/workflow-run-list-view.tsx +57 -0
- package/src/components/workflow-run-list/workflow-run-list.stories.tsx +111 -0
- package/src/components/workflow-run-list/workflow-run-list.tsx +29 -0
- package/src/components/workflow-run-list/workflow-run-row.tsx +176 -0
- package/src/components/workflow-run-summary/index.ts +1 -0
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx +230 -0
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +146 -0
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +414 -0
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +354 -0
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +295 -0
- package/src/components/workflow-run-view/agent-config-failure-callout.stories.tsx +140 -0
- package/src/components/workflow-run-view/agent-config-failure-callout.tsx +93 -0
- package/src/components/workflow-run-view/index.ts +2 -0
- package/src/components/workflow-run-view/job-card.stories.tsx +788 -0
- package/src/components/workflow-run-view/job-card.tsx +566 -0
- package/src/components/workflow-run-view/job-execution-switcher.tsx +170 -0
- package/src/components/workflow-run-view/job-execution-time-text.tsx +34 -0
- package/src/components/workflow-run-view/step-attempt-log-panel.test.tsx +290 -0
- package/src/components/workflow-run-view/step-attempt-log-panel.tsx +152 -0
- package/src/components/workflow-run-view/workflow-run-selection.test.ts +280 -0
- package/src/components/workflow-run-view/workflow-run-selection.ts +89 -0
- package/src/components/workflow-run-view/workflow-run-states.tsx +70 -0
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +1214 -0
- package/src/components/workflow-run-view/workflow-run-view.tsx +341 -0
- package/src/components/workflow-source-panel/index.ts +1 -0
- package/src/components/workflow-source-panel/workflow-source-panel.stories.tsx +110 -0
- package/src/components/workflow-source-panel/workflow-source-panel.test.tsx +96 -0
- package/src/components/workflow-source-panel/workflow-source-panel.tsx +136 -0
- package/src/components/workflow-status/status-visuals.test.ts +38 -0
- package/src/components/workflow-status/status-visuals.ts +36 -0
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +90 -0
- package/src/components/workflow-status/workflow-status-icon.tsx +135 -0
- package/src/core/entities/job-execution.ts +139 -0
- package/src/core/entities/job.ts +149 -0
- package/src/core/entities/step-attempt.ts +89 -0
- package/src/core/entities/step.ts +105 -0
- package/src/core/entities/workflow-run-attempt.ts +87 -0
- package/src/core/entities/workflow-run.ts +183 -0
- package/src/core/workflow-run-url-state.ts +61 -0
- package/src/core/workflow-run.test.ts +640 -0
- package/src/core/workflow-run.ts +66 -0
- package/src/env.d.ts +8 -0
- package/src/feature.ts +26 -0
- package/src/hooks/api/workflow-runs.test.tsx +410 -0
- package/src/hooks/api/workflow-runs.ts +485 -0
- package/src/index.ts +45 -0
- package/src/page-harness-budget.test.ts +33 -0
- package/src/pages/workflow-run-first-time-use.tsx +17 -0
- package/src/pages/workflow-run-page.test.tsx +517 -0
- package/src/pages/workflow-run-page.tsx +89 -0
- package/src/routes/run-detail.tsx +15 -0
- package/src/routes/runs.tsx +11 -0
- package/test/fixtures/logs.ts +13 -0
- package/test/fixtures/workflow-run.ts +311 -0
- package/test/pages.tsx +79 -0
- package/test/render.tsx +40 -0
- package/test/setup.ts +3 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vercel.json +8 -0
- package/vitest.config.ts +70 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
RerunWorkflowRunBodyDto,
|
|
3
|
+
WorkflowRunAttemptsResponseDto,
|
|
4
|
+
WorkflowRunDetailResponseDto,
|
|
5
|
+
WorkflowRunDto,
|
|
6
|
+
WorkflowRunListResponseDto,
|
|
7
|
+
WorkflowRunRerunModeDto,
|
|
8
|
+
WorkflowRunResponseDto,
|
|
9
|
+
} from '@shipfox/api-workflows-dto';
|
|
10
|
+
import {apiRequest} from '@shipfox/client-api';
|
|
11
|
+
import {
|
|
12
|
+
type InfiniteData,
|
|
13
|
+
keepPreviousData,
|
|
14
|
+
useInfiniteQuery,
|
|
15
|
+
useMutation,
|
|
16
|
+
useQuery,
|
|
17
|
+
useQueryClient,
|
|
18
|
+
} from '@tanstack/react-query';
|
|
19
|
+
import {
|
|
20
|
+
isWorkflowRunTerminal,
|
|
21
|
+
toWorkflowRunAttempt,
|
|
22
|
+
toWorkflowRunDetail,
|
|
23
|
+
toWorkflowRunListItem,
|
|
24
|
+
toWorkflowRunListPage,
|
|
25
|
+
type WorkflowRun,
|
|
26
|
+
type WorkflowRunAttempt,
|
|
27
|
+
type WorkflowRunDetail,
|
|
28
|
+
type WorkflowRunListPage,
|
|
29
|
+
type WorkflowRunStatus,
|
|
30
|
+
} from '#core/workflow-run.js';
|
|
31
|
+
|
|
32
|
+
export interface WorkflowRunFilters {
|
|
33
|
+
status?: WorkflowRunStatus | undefined;
|
|
34
|
+
definitionId?: string | undefined;
|
|
35
|
+
triggerSource?: string | undefined;
|
|
36
|
+
createdFrom?: string | undefined;
|
|
37
|
+
createdTo?: string | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const workflowRunsQueryKeys = {
|
|
41
|
+
all: ['workflow-runs'] as const,
|
|
42
|
+
lists: (projectId: string) => [...workflowRunsQueryKeys.all, 'list', projectId] as const,
|
|
43
|
+
list: (projectId: string, filters: WorkflowRunFilters) =>
|
|
44
|
+
[...workflowRunsQueryKeys.lists(projectId), normalizeFilters(filters)] as const,
|
|
45
|
+
detail: (workflowRunId: string, runAttempt?: number | undefined) =>
|
|
46
|
+
[...workflowRunsQueryKeys.all, 'detail', workflowRunId, runAttempt ?? null] as const,
|
|
47
|
+
attempts: (workflowRunId: string) =>
|
|
48
|
+
[...workflowRunsQueryKeys.all, 'attempts', workflowRunId] as const,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
function normalizeFilters(filters: WorkflowRunFilters) {
|
|
52
|
+
return {
|
|
53
|
+
status: filters.status ?? null,
|
|
54
|
+
definitionId: filters.definitionId ?? null,
|
|
55
|
+
triggerSource: filters.triggerSource ?? null,
|
|
56
|
+
createdFrom: filters.createdFrom ?? null,
|
|
57
|
+
createdTo: filters.createdTo ?? null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function appendFilters(params: URLSearchParams, filters: WorkflowRunFilters) {
|
|
62
|
+
if (filters.status) params.set('status', filters.status);
|
|
63
|
+
if (filters.definitionId) params.set('definition_id', filters.definitionId);
|
|
64
|
+
if (filters.triggerSource) params.set('trigger_source', filters.triggerSource);
|
|
65
|
+
if (filters.createdFrom) params.set('created_from', filters.createdFrom);
|
|
66
|
+
if (filters.createdTo) params.set('created_to', filters.createdTo);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function listWorkflowRunsDto({
|
|
70
|
+
projectId,
|
|
71
|
+
filters,
|
|
72
|
+
limit = 50,
|
|
73
|
+
cursor,
|
|
74
|
+
signal,
|
|
75
|
+
}: {
|
|
76
|
+
projectId: string;
|
|
77
|
+
filters: WorkflowRunFilters;
|
|
78
|
+
limit?: number;
|
|
79
|
+
cursor?: string | undefined;
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}) {
|
|
82
|
+
const params = new URLSearchParams({project_id: projectId, limit: String(limit)});
|
|
83
|
+
if (cursor) params.set('cursor', cursor);
|
|
84
|
+
appendFilters(params, filters);
|
|
85
|
+
return await apiRequest<WorkflowRunListResponseDto>(`/workflows/runs?${params.toString()}`, {
|
|
86
|
+
signal,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Fire the manual trigger of a workflow definition.
|
|
92
|
+
*
|
|
93
|
+
* The server resolves the manual subscription by definition id (workflows
|
|
94
|
+
* may declare at most one manual trigger). `inputs` are forwarded to the
|
|
95
|
+
* run when provided.
|
|
96
|
+
*/
|
|
97
|
+
export async function fireManualWorkflow({
|
|
98
|
+
definitionId,
|
|
99
|
+
inputs,
|
|
100
|
+
}: {
|
|
101
|
+
definitionId: string;
|
|
102
|
+
inputs?: Record<string, unknown>;
|
|
103
|
+
}) {
|
|
104
|
+
return await apiRequest<{workflow_run_id: string}>(
|
|
105
|
+
`/workflow-definitions/${definitionId}/fire-manual`,
|
|
106
|
+
{
|
|
107
|
+
method: 'POST',
|
|
108
|
+
body: inputs ? {inputs} : {},
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const ACTIVE_POLL_MS = 4_000;
|
|
114
|
+
const IDLE_POLL_MS = 30_000;
|
|
115
|
+
|
|
116
|
+
type RunListInfinite = InfiniteData<WorkflowRunListResponseDto, string | undefined>;
|
|
117
|
+
|
|
118
|
+
function toWorkflowRunInfiniteData(
|
|
119
|
+
data: InfiniteData<WorkflowRunListResponseDto, string | undefined>,
|
|
120
|
+
): InfiniteData<WorkflowRunListPage, string | undefined> {
|
|
121
|
+
return {
|
|
122
|
+
...data,
|
|
123
|
+
pages: data.pages.map(toWorkflowRunListPage),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function useWorkflowRunsInfiniteQuery(
|
|
128
|
+
projectId: string | undefined,
|
|
129
|
+
filters: WorkflowRunFilters,
|
|
130
|
+
limit = 50,
|
|
131
|
+
) {
|
|
132
|
+
// Polling is owned by react-query, not the page. Polling fast (4s) while
|
|
133
|
+
// any non-terminal run is visible covers state transitions; polling slow
|
|
134
|
+
// (30s) when idle covers brand-new external runs (webhook/schedule
|
|
135
|
+
// triggers) without leaving the list stale.
|
|
136
|
+
//
|
|
137
|
+
// We disable polling once the user has loaded more than one page. With
|
|
138
|
+
// cursor pagination the cursor that bounds page 1 was computed from
|
|
139
|
+
// page 0's last row; if a refetch shifts that boundary, a small range
|
|
140
|
+
// of rows can drop into a between-pages gap. Users who scrolled into
|
|
141
|
+
// history opted into "reading mode": pause until they refocus, filter,
|
|
142
|
+
// or scroll back.
|
|
143
|
+
return useInfiniteQuery({
|
|
144
|
+
queryKey: projectId
|
|
145
|
+
? workflowRunsQueryKeys.list(projectId, filters)
|
|
146
|
+
: [...workflowRunsQueryKeys.all, 'list'],
|
|
147
|
+
enabled: Boolean(projectId),
|
|
148
|
+
initialPageParam: undefined as string | undefined,
|
|
149
|
+
queryFn: ({pageParam, signal}) =>
|
|
150
|
+
listWorkflowRunsDto({projectId: projectId ?? '', filters, limit, cursor: pageParam, signal}),
|
|
151
|
+
getNextPageParam: (lastPage) => lastPage.next_cursor ?? undefined,
|
|
152
|
+
select: toWorkflowRunInfiniteData,
|
|
153
|
+
placeholderData: keepPreviousData,
|
|
154
|
+
staleTime: 2_000,
|
|
155
|
+
refetchOnWindowFocus: true,
|
|
156
|
+
refetchInterval: (query) => {
|
|
157
|
+
const data = query.state.data;
|
|
158
|
+
if (!data || data.pages.length > 1) return false;
|
|
159
|
+
const hasActive = data.pages.some((page) =>
|
|
160
|
+
page.runs.some((run) => !isWorkflowRunTerminal(run.status)),
|
|
161
|
+
);
|
|
162
|
+
return hasActive ? ACTIVE_POLL_MS : IDLE_POLL_MS;
|
|
163
|
+
},
|
|
164
|
+
refetchIntervalInBackground: false,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function getWorkflowRunDto({
|
|
169
|
+
workflowRunId,
|
|
170
|
+
runAttempt,
|
|
171
|
+
signal,
|
|
172
|
+
}: {
|
|
173
|
+
workflowRunId: string;
|
|
174
|
+
runAttempt?: number | undefined;
|
|
175
|
+
signal?: AbortSignal;
|
|
176
|
+
}) {
|
|
177
|
+
const params = new URLSearchParams();
|
|
178
|
+
if (runAttempt) params.set('attempt', String(runAttempt));
|
|
179
|
+
const query = params.size > 0 ? `?${params.toString()}` : '';
|
|
180
|
+
return await apiRequest<WorkflowRunDetailResponseDto>(
|
|
181
|
+
`/workflows/runs/${workflowRunId}${query}`,
|
|
182
|
+
{
|
|
183
|
+
signal,
|
|
184
|
+
},
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async function getWorkflowRunAttemptsDto({
|
|
189
|
+
workflowRunId,
|
|
190
|
+
signal,
|
|
191
|
+
}: {
|
|
192
|
+
workflowRunId: string;
|
|
193
|
+
signal?: AbortSignal;
|
|
194
|
+
}) {
|
|
195
|
+
return await apiRequest<WorkflowRunAttemptsResponseDto>(
|
|
196
|
+
`/workflows/runs/${workflowRunId}/attempts`,
|
|
197
|
+
{
|
|
198
|
+
signal,
|
|
199
|
+
},
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function cancelWorkflowRunDto({workflowRunId}: {workflowRunId: string}) {
|
|
204
|
+
return await apiRequest<WorkflowRunDto>(`/workflows/runs/${workflowRunId}/cancel`, {
|
|
205
|
+
method: 'POST',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export async function rerunWorkflowRun({
|
|
210
|
+
workflowRunId,
|
|
211
|
+
mode,
|
|
212
|
+
}: {
|
|
213
|
+
workflowRunId: string;
|
|
214
|
+
mode: WorkflowRunRerunModeDto;
|
|
215
|
+
}) {
|
|
216
|
+
return await apiRequest<WorkflowRunResponseDto>(`/workflows/runs/${workflowRunId}/rerun`, {
|
|
217
|
+
method: 'POST',
|
|
218
|
+
body: {mode} satisfies RerunWorkflowRunBodyDto,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function useRerunWorkflowRunMutation(projectId: string) {
|
|
223
|
+
const queryClient = useQueryClient();
|
|
224
|
+
|
|
225
|
+
return useMutation({
|
|
226
|
+
mutationFn: rerunWorkflowRun,
|
|
227
|
+
onSuccess: async (_run, variables) => {
|
|
228
|
+
await Promise.all([
|
|
229
|
+
queryClient.invalidateQueries({queryKey: workflowRunsQueryKeys.lists(projectId)}),
|
|
230
|
+
queryClient.invalidateQueries({
|
|
231
|
+
queryKey: workflowRunsQueryKeys.detail(variables.workflowRunId),
|
|
232
|
+
}),
|
|
233
|
+
queryClient.invalidateQueries({
|
|
234
|
+
queryKey: workflowRunsQueryKeys.attempts(variables.workflowRunId),
|
|
235
|
+
}),
|
|
236
|
+
]);
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function filtersAcceptManualPendingRun(
|
|
242
|
+
filters: WorkflowRunFilters,
|
|
243
|
+
definitionId: string,
|
|
244
|
+
now: Date,
|
|
245
|
+
): boolean {
|
|
246
|
+
if (filters.status && filters.status !== 'pending') return false;
|
|
247
|
+
if (filters.definitionId && filters.definitionId !== definitionId) return false;
|
|
248
|
+
if (filters.triggerSource && filters.triggerSource !== 'manual') return false;
|
|
249
|
+
if (filters.createdFrom && Date.parse(filters.createdFrom) > now.getTime()) return false;
|
|
250
|
+
if (filters.createdTo && Date.parse(filters.createdTo) < now.getTime()) return false;
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function buildTempRun({
|
|
255
|
+
projectId,
|
|
256
|
+
definitionId,
|
|
257
|
+
name,
|
|
258
|
+
createdAt,
|
|
259
|
+
}: {
|
|
260
|
+
projectId: string;
|
|
261
|
+
definitionId: string;
|
|
262
|
+
name: string;
|
|
263
|
+
createdAt: string;
|
|
264
|
+
}): WorkflowRunDto {
|
|
265
|
+
return {
|
|
266
|
+
id: `temp-${cryptoRandomId()}`,
|
|
267
|
+
project_id: projectId,
|
|
268
|
+
definition_id: definitionId,
|
|
269
|
+
name,
|
|
270
|
+
status: 'pending',
|
|
271
|
+
current_attempt: 1,
|
|
272
|
+
latest_attempt: 1,
|
|
273
|
+
trigger_provider: null,
|
|
274
|
+
trigger_source: 'manual',
|
|
275
|
+
trigger_event: 'fire',
|
|
276
|
+
trigger_payload: {source: 'manual', event: 'fire'},
|
|
277
|
+
inputs: null,
|
|
278
|
+
source_snapshot: null,
|
|
279
|
+
created_at: createdAt,
|
|
280
|
+
updated_at: createdAt,
|
|
281
|
+
started_at: null,
|
|
282
|
+
finished_at: null,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function cryptoRandomId(): string {
|
|
287
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
288
|
+
return crypto.randomUUID();
|
|
289
|
+
}
|
|
290
|
+
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export interface FireManualWorkflowVariables {
|
|
294
|
+
projectId: string;
|
|
295
|
+
definitionId: string;
|
|
296
|
+
inputs?: Record<string, unknown>;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function useFireManualWorkflowMutation() {
|
|
300
|
+
const queryClient = useQueryClient();
|
|
301
|
+
return useMutation({
|
|
302
|
+
mutationFn: (variables: FireManualWorkflowVariables) =>
|
|
303
|
+
fireManualWorkflow(
|
|
304
|
+
variables.inputs
|
|
305
|
+
? {definitionId: variables.definitionId, inputs: variables.inputs}
|
|
306
|
+
: {definitionId: variables.definitionId},
|
|
307
|
+
),
|
|
308
|
+
onMutate: (variables) => {
|
|
309
|
+
const definitionName = lookupDefinitionName(
|
|
310
|
+
queryClient,
|
|
311
|
+
variables.projectId,
|
|
312
|
+
variables.definitionId,
|
|
313
|
+
);
|
|
314
|
+
const createdAt = new Date().toISOString();
|
|
315
|
+
const tempRun = buildTempRun({
|
|
316
|
+
projectId: variables.projectId,
|
|
317
|
+
definitionId: variables.definitionId,
|
|
318
|
+
name: definitionName ?? 'New run',
|
|
319
|
+
createdAt,
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
const listsKey = workflowRunsQueryKeys.lists(variables.projectId);
|
|
323
|
+
const touchedQueryKeys: Array<readonly unknown[]> = [];
|
|
324
|
+
|
|
325
|
+
const entries = queryClient.getQueriesData<RunListInfinite>({queryKey: listsKey});
|
|
326
|
+
const now = new Date(createdAt);
|
|
327
|
+
for (const [queryKey] of entries) {
|
|
328
|
+
const filters = readFiltersFromKey(queryKey);
|
|
329
|
+
if (!filters) continue;
|
|
330
|
+
if (!filtersAcceptManualPendingRun(filters, variables.definitionId, now)) continue;
|
|
331
|
+
|
|
332
|
+
touchedQueryKeys.push(queryKey);
|
|
333
|
+
queryClient.setQueryData<RunListInfinite>(queryKey, (current) => {
|
|
334
|
+
if (!current || current.pages.length === 0) return current;
|
|
335
|
+
const firstPage = current.pages[0];
|
|
336
|
+
if (!firstPage) return current;
|
|
337
|
+
const nextFirstPage: WorkflowRunListResponseDto = {
|
|
338
|
+
...firstPage,
|
|
339
|
+
runs: [tempRun, ...firstPage.runs],
|
|
340
|
+
filtered_total_count:
|
|
341
|
+
firstPage.filtered_total_count != null ? firstPage.filtered_total_count + 1 : null,
|
|
342
|
+
};
|
|
343
|
+
return {...current, pages: [nextFirstPage, ...current.pages.slice(1)]};
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return {tempWorkflowRunId: tempRun.id, touchedQueryKeys};
|
|
348
|
+
},
|
|
349
|
+
onError: (_error, _variables, context) => {
|
|
350
|
+
if (!context) return;
|
|
351
|
+
for (const queryKey of context.touchedQueryKeys) {
|
|
352
|
+
queryClient.setQueryData<RunListInfinite>(queryKey, (current) => {
|
|
353
|
+
if (!current) return current;
|
|
354
|
+
let removedCount = 0;
|
|
355
|
+
const pages = current.pages.map((page) => {
|
|
356
|
+
const runs = page.runs.filter((run) => {
|
|
357
|
+
if (run.id !== context.tempWorkflowRunId) return true;
|
|
358
|
+
removedCount += 1;
|
|
359
|
+
return false;
|
|
360
|
+
});
|
|
361
|
+
if (runs.length === page.runs.length) return page;
|
|
362
|
+
return {
|
|
363
|
+
...page,
|
|
364
|
+
runs,
|
|
365
|
+
filtered_total_count:
|
|
366
|
+
page.filtered_total_count != null
|
|
367
|
+
? Math.max(0, page.filtered_total_count - removedCount)
|
|
368
|
+
: null,
|
|
369
|
+
};
|
|
370
|
+
});
|
|
371
|
+
if (removedCount === 0) return current;
|
|
372
|
+
return {...current, pages};
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
onSuccess: (_data, variables) => {
|
|
377
|
+
void queryClient.invalidateQueries({
|
|
378
|
+
queryKey: workflowRunsQueryKeys.lists(variables.projectId),
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function readFiltersFromKey(queryKey: readonly unknown[]): WorkflowRunFilters | null {
|
|
385
|
+
if (queryKey.length < 4) return null;
|
|
386
|
+
const normalized = queryKey[3];
|
|
387
|
+
if (!normalized || typeof normalized !== 'object') return null;
|
|
388
|
+
const obj = normalized as Record<string, unknown>;
|
|
389
|
+
return {
|
|
390
|
+
status: (obj.status as WorkflowRunStatus | null) ?? undefined,
|
|
391
|
+
definitionId: (obj.definitionId as string | null) ?? undefined,
|
|
392
|
+
triggerSource: (obj.triggerSource as string | null) ?? undefined,
|
|
393
|
+
createdFrom: (obj.createdFrom as string | null) ?? undefined,
|
|
394
|
+
createdTo: (obj.createdTo as string | null) ?? undefined,
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function lookupDefinitionName(
|
|
399
|
+
queryClient: ReturnType<typeof useQueryClient>,
|
|
400
|
+
projectId: string,
|
|
401
|
+
definitionId: string,
|
|
402
|
+
): string | undefined {
|
|
403
|
+
const entries = queryClient.getQueriesData<
|
|
404
|
+
InfiniteData<{definitions: Array<{id: string; project_id: string; name: string}>}>
|
|
405
|
+
>({queryKey: ['definitions', 'list', projectId]});
|
|
406
|
+
for (const [, data] of entries) {
|
|
407
|
+
if (!data) continue;
|
|
408
|
+
for (const page of data.pages) {
|
|
409
|
+
const match = page.definitions.find((d) => d.id === definitionId);
|
|
410
|
+
if (match) return match.name;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export function useWorkflowRunQuery(workflowRunId: string | undefined) {
|
|
417
|
+
return useWorkflowRunAttemptQuery({workflowRunId, runAttempt: undefined});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function useWorkflowRunAttemptQuery({
|
|
421
|
+
workflowRunId,
|
|
422
|
+
runAttempt,
|
|
423
|
+
}: {
|
|
424
|
+
workflowRunId: string | undefined;
|
|
425
|
+
runAttempt?: number | undefined;
|
|
426
|
+
}) {
|
|
427
|
+
// Poll a non-terminal run so the open run detail stays live (same cadence as the run
|
|
428
|
+
// list); stop once the run is terminal.
|
|
429
|
+
return useQuery({
|
|
430
|
+
queryKey: workflowRunId
|
|
431
|
+
? workflowRunsQueryKeys.detail(workflowRunId, runAttempt)
|
|
432
|
+
: [...workflowRunsQueryKeys.all, 'detail'],
|
|
433
|
+
enabled: Boolean(workflowRunId),
|
|
434
|
+
queryFn: ({signal}) =>
|
|
435
|
+
getWorkflowRunDto({workflowRunId: workflowRunId ?? '', runAttempt, signal}),
|
|
436
|
+
select: toWorkflowRunDetail,
|
|
437
|
+
staleTime: 2_000,
|
|
438
|
+
refetchOnWindowFocus: true,
|
|
439
|
+
refetchInterval: (query) => {
|
|
440
|
+
const status: WorkflowRunDetail['runAttempt']['status'] | undefined =
|
|
441
|
+
query.state.data?.run_attempt.status;
|
|
442
|
+
if (!status) return false;
|
|
443
|
+
return isWorkflowRunTerminal(status) ? false : ACTIVE_POLL_MS;
|
|
444
|
+
},
|
|
445
|
+
refetchIntervalInBackground: false,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export function useWorkflowRunAttemptsQuery({
|
|
450
|
+
workflowRunId,
|
|
451
|
+
enabled,
|
|
452
|
+
}: {
|
|
453
|
+
workflowRunId: string | undefined;
|
|
454
|
+
enabled: boolean;
|
|
455
|
+
}) {
|
|
456
|
+
return useQuery({
|
|
457
|
+
queryKey: workflowRunId
|
|
458
|
+
? workflowRunsQueryKeys.attempts(workflowRunId)
|
|
459
|
+
: [...workflowRunsQueryKeys.all, 'attempts'],
|
|
460
|
+
enabled: Boolean(workflowRunId) && enabled,
|
|
461
|
+
queryFn: ({signal}) => getWorkflowRunAttemptsDto({workflowRunId: workflowRunId ?? '', signal}),
|
|
462
|
+
select: (dto): WorkflowRunAttempt[] => dto.attempts.map(toWorkflowRunAttempt),
|
|
463
|
+
staleTime: 0,
|
|
464
|
+
refetchOnMount: true,
|
|
465
|
+
refetchOnWindowFocus: false,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export function useCancelWorkflowRunMutation(run: WorkflowRun | undefined) {
|
|
470
|
+
const queryClient = useQueryClient();
|
|
471
|
+
return useMutation({
|
|
472
|
+
mutationFn: async () => {
|
|
473
|
+
if (!run) throw new Error('Workflow run is not loaded');
|
|
474
|
+
return toWorkflowRunListItem(await cancelWorkflowRunDto({workflowRunId: run.id}));
|
|
475
|
+
},
|
|
476
|
+
onSuccess: async () => {
|
|
477
|
+
if (!run) return;
|
|
478
|
+
await Promise.all([
|
|
479
|
+
queryClient.invalidateQueries({queryKey: workflowRunsQueryKeys.detail(run.id)}),
|
|
480
|
+
queryClient.invalidateQueries({queryKey: workflowRunsQueryKeys.lists(run.projectId)}),
|
|
481
|
+
queryClient.invalidateQueries({queryKey: workflowRunsQueryKeys.attempts(run.id)}),
|
|
482
|
+
]);
|
|
483
|
+
},
|
|
484
|
+
});
|
|
485
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
AgentConfigIssue,
|
|
3
|
+
JobDisplayDuration,
|
|
4
|
+
JobExecutionDisplayDuration,
|
|
5
|
+
JobExecutionStatus,
|
|
6
|
+
JobExecutionTime,
|
|
7
|
+
JobStatus,
|
|
8
|
+
Step,
|
|
9
|
+
StepAttempt,
|
|
10
|
+
StepAttemptDisplayDuration,
|
|
11
|
+
StepError,
|
|
12
|
+
StepErrorCategory,
|
|
13
|
+
StepErrorReason,
|
|
14
|
+
StepGateResult,
|
|
15
|
+
StepSourceLocation,
|
|
16
|
+
WorkflowRun,
|
|
17
|
+
WorkflowRunAttempt,
|
|
18
|
+
WorkflowRunDetail,
|
|
19
|
+
WorkflowRunListPage,
|
|
20
|
+
WorkflowRunStatus,
|
|
21
|
+
WorkflowSourceSnapshot,
|
|
22
|
+
WorkflowStatus,
|
|
23
|
+
} from '#core/workflow-run.js';
|
|
24
|
+
export {
|
|
25
|
+
isWorkflowRunTerminal,
|
|
26
|
+
isWorkflowStatus,
|
|
27
|
+
Job,
|
|
28
|
+
JobExecution,
|
|
29
|
+
TERMINAL_WORKFLOW_RUN_STATUSES,
|
|
30
|
+
WORKFLOW_RUN_STATUSES,
|
|
31
|
+
workflowRunShortId,
|
|
32
|
+
workflowRunTriggerLabel,
|
|
33
|
+
} from '#core/workflow-run.js';
|
|
34
|
+
export {
|
|
35
|
+
type FireManualWorkflowVariables,
|
|
36
|
+
fireManualWorkflow,
|
|
37
|
+
useCancelWorkflowRunMutation,
|
|
38
|
+
useFireManualWorkflowMutation,
|
|
39
|
+
useWorkflowRunAttemptsQuery,
|
|
40
|
+
useWorkflowRunQuery,
|
|
41
|
+
useWorkflowRunsInfiniteQuery,
|
|
42
|
+
type WorkflowRunFilters,
|
|
43
|
+
workflowRunsQueryKeys,
|
|
44
|
+
} from './hooks/api/workflow-runs.js';
|
|
45
|
+
export {WorkflowRunPage} from './pages/workflow-run-page.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {readdirSync, readFileSync} from 'node:fs';
|
|
2
|
+
import {dirname, join, relative} from 'node:path';
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
|
+
|
|
5
|
+
// Keeps page-harness imports intentional because each one mounts router, query,
|
|
6
|
+
// and API-client providers around the test.
|
|
7
|
+
const PAGE_HARNESS_ALLOWLIST = [
|
|
8
|
+
'src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx',
|
|
9
|
+
'src/components/workflow-run-view/workflow-run-view.test.tsx',
|
|
10
|
+
'src/pages/workflow-run-page.test.tsx',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const srcDir = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const packageRoot = dirname(srcDir);
|
|
15
|
+
|
|
16
|
+
function collectTestFiles(dir: string): string[] {
|
|
17
|
+
return readdirSync(dir, {withFileTypes: true}).flatMap((entry) => {
|
|
18
|
+
const entryPath = join(dir, entry.name);
|
|
19
|
+
if (entry.isDirectory()) return collectTestFiles(entryPath);
|
|
20
|
+
return entry.isFile() && entry.name.endsWith('.test.tsx') ? [entryPath] : [];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe('page harness budget', () => {
|
|
25
|
+
it('is imported only by the allowlisted page-wiring tests', () => {
|
|
26
|
+
const harnessImporters = collectTestFiles(srcDir)
|
|
27
|
+
.filter((file) => readFileSync(file, 'utf8').includes("'#test/pages"))
|
|
28
|
+
.map((file) => relative(packageRoot, file))
|
|
29
|
+
.sort();
|
|
30
|
+
|
|
31
|
+
expect(harnessImporters).toEqual(PAGE_HARNESS_ALLOWLIST);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {EmptyState} from '@shipfox/react-ui/empty-state';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shown when a project has no workflow runs yet, in place of the empty rail and the
|
|
5
|
+
* perpetual detail skeleton the loading-driven layout would otherwise leave behind.
|
|
6
|
+
*/
|
|
7
|
+
export function WorkflowRunFirstTimeUse() {
|
|
8
|
+
return (
|
|
9
|
+
<div className="flex min-h-0 flex-1 items-center justify-center p-16">
|
|
10
|
+
<EmptyState
|
|
11
|
+
icon="pulseLine"
|
|
12
|
+
title="No workflow runs yet"
|
|
13
|
+
description="Runs will appear here once this project's workflows start running."
|
|
14
|
+
/>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|