nvent 0.4.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 (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +389 -0
  3. package/dist/module.d.mts +193 -0
  4. package/dist/module.json +9 -0
  5. package/dist/module.mjs +974 -0
  6. package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +33 -0
  7. package/dist/runtime/app/components/ConfirmDialog.vue +121 -0
  8. package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +33 -0
  9. package/dist/runtime/app/components/FlowDiagram.d.vue.ts +64 -0
  10. package/dist/runtime/app/components/FlowDiagram.vue +338 -0
  11. package/dist/runtime/app/components/FlowDiagram.vue.d.ts +64 -0
  12. package/dist/runtime/app/components/FlowNodeCard.d.vue.ts +29 -0
  13. package/dist/runtime/app/components/FlowNodeCard.vue +156 -0
  14. package/dist/runtime/app/components/FlowNodeCard.vue.d.ts +29 -0
  15. package/dist/runtime/app/components/FlowRunOverview.d.vue.ts +9 -0
  16. package/dist/runtime/app/components/FlowRunOverview.vue +291 -0
  17. package/dist/runtime/app/components/FlowRunOverview.vue.d.ts +9 -0
  18. package/dist/runtime/app/components/FlowRunStatusBadge.d.vue.ts +14 -0
  19. package/dist/runtime/app/components/FlowRunStatusBadge.vue +60 -0
  20. package/dist/runtime/app/components/FlowRunStatusBadge.vue.d.ts +14 -0
  21. package/dist/runtime/app/components/FlowRunTimeline.d.vue.ts +12 -0
  22. package/dist/runtime/app/components/FlowRunTimeline.vue +127 -0
  23. package/dist/runtime/app/components/FlowRunTimeline.vue.d.ts +12 -0
  24. package/dist/runtime/app/components/FlowScheduleDialog.d.vue.ts +16 -0
  25. package/dist/runtime/app/components/FlowScheduleDialog.vue +226 -0
  26. package/dist/runtime/app/components/FlowScheduleDialog.vue.d.ts +16 -0
  27. package/dist/runtime/app/components/FlowSchedulesList.d.vue.ts +12 -0
  28. package/dist/runtime/app/components/FlowSchedulesList.vue +99 -0
  29. package/dist/runtime/app/components/FlowSchedulesList.vue.d.ts +12 -0
  30. package/dist/runtime/app/components/JobScheduling.d.vue.ts +6 -0
  31. package/dist/runtime/app/components/JobScheduling.vue +203 -0
  32. package/dist/runtime/app/components/JobScheduling.vue.d.ts +6 -0
  33. package/dist/runtime/app/components/ListItem.d.vue.ts +23 -0
  34. package/dist/runtime/app/components/ListItem.vue +70 -0
  35. package/dist/runtime/app/components/ListItem.vue.d.ts +23 -0
  36. package/dist/runtime/app/components/QueueConfigDetails.d.vue.ts +45 -0
  37. package/dist/runtime/app/components/QueueConfigDetails.vue +412 -0
  38. package/dist/runtime/app/components/QueueConfigDetails.vue.d.ts +45 -0
  39. package/dist/runtime/app/components/StatCounter.d.vue.ts +9 -0
  40. package/dist/runtime/app/components/StatCounter.vue +25 -0
  41. package/dist/runtime/app/components/StatCounter.vue.d.ts +9 -0
  42. package/dist/runtime/app/components/TimelineList.d.vue.ts +7 -0
  43. package/dist/runtime/app/components/TimelineList.vue +210 -0
  44. package/dist/runtime/app/components/TimelineList.vue.d.ts +7 -0
  45. package/dist/runtime/app/components/nhealth/component-router.d.vue.ts +46 -0
  46. package/dist/runtime/app/components/nhealth/component-router.vue +26 -0
  47. package/dist/runtime/app/components/nhealth/component-router.vue.d.ts +46 -0
  48. package/dist/runtime/app/components/nhealth/component-shell.d.vue.ts +24 -0
  49. package/dist/runtime/app/components/nhealth/component-shell.vue +89 -0
  50. package/dist/runtime/app/components/nhealth/component-shell.vue.d.ts +24 -0
  51. package/dist/runtime/app/composables/useAnalyzedFlows.d.ts +14 -0
  52. package/dist/runtime/app/composables/useAnalyzedFlows.js +7 -0
  53. package/dist/runtime/app/composables/useComponentRouter.d.ts +38 -0
  54. package/dist/runtime/app/composables/useComponentRouter.js +240 -0
  55. package/dist/runtime/app/composables/useFlowRunTimeline.d.ts +15 -0
  56. package/dist/runtime/app/composables/useFlowRunTimeline.js +66 -0
  57. package/dist/runtime/app/composables/useFlowRuns.d.ts +11 -0
  58. package/dist/runtime/app/composables/useFlowRuns.js +31 -0
  59. package/dist/runtime/app/composables/useFlowRunsInfinite.d.ts +24 -0
  60. package/dist/runtime/app/composables/useFlowRunsInfinite.js +123 -0
  61. package/dist/runtime/app/composables/useFlowRunsPolling.d.ts +8 -0
  62. package/dist/runtime/app/composables/useFlowRunsPolling.js +26 -0
  63. package/dist/runtime/app/composables/useFlowState.d.ts +125 -0
  64. package/dist/runtime/app/composables/useFlowState.js +211 -0
  65. package/dist/runtime/app/composables/useFlowWebSocket.d.ts +27 -0
  66. package/dist/runtime/app/composables/useFlowWebSocket.js +205 -0
  67. package/dist/runtime/app/composables/useFlowsNavigation.d.ts +10 -0
  68. package/dist/runtime/app/composables/useFlowsNavigation.js +57 -0
  69. package/dist/runtime/app/composables/useQueueJobs.d.ts +20 -0
  70. package/dist/runtime/app/composables/useQueueJobs.js +20 -0
  71. package/dist/runtime/app/composables/useQueueUpdates.d.ts +26 -0
  72. package/dist/runtime/app/composables/useQueueUpdates.js +122 -0
  73. package/dist/runtime/app/composables/useQueues.d.ts +43 -0
  74. package/dist/runtime/app/composables/useQueues.js +26 -0
  75. package/dist/runtime/app/composables/useQueuesLive.d.ts +19 -0
  76. package/dist/runtime/app/composables/useQueuesLive.js +143 -0
  77. package/dist/runtime/app/pages/flows/index.d.vue.ts +3 -0
  78. package/dist/runtime/app/pages/flows/index.vue +645 -0
  79. package/dist/runtime/app/pages/flows/index.vue.d.ts +3 -0
  80. package/dist/runtime/app/pages/index.d.vue.ts +3 -0
  81. package/dist/runtime/app/pages/index.vue +34 -0
  82. package/dist/runtime/app/pages/index.vue.d.ts +3 -0
  83. package/dist/runtime/app/pages/queues/index.d.vue.ts +3 -0
  84. package/dist/runtime/app/pages/queues/index.vue +229 -0
  85. package/dist/runtime/app/pages/queues/index.vue.d.ts +3 -0
  86. package/dist/runtime/app/pages/queues/job.d.vue.ts +3 -0
  87. package/dist/runtime/app/pages/queues/job.vue +262 -0
  88. package/dist/runtime/app/pages/queues/job.vue.d.ts +3 -0
  89. package/dist/runtime/app/pages/queues/jobs.d.vue.ts +3 -0
  90. package/dist/runtime/app/pages/queues/jobs.vue +291 -0
  91. package/dist/runtime/app/pages/queues/jobs.vue.d.ts +3 -0
  92. package/dist/runtime/app/plugins/vueflow.client.d.ts +6 -0
  93. package/dist/runtime/app/plugins/vueflow.client.js +15 -0
  94. package/dist/runtime/constants.d.ts +11 -0
  95. package/dist/runtime/constants.js +11 -0
  96. package/dist/runtime/python/get_config.py +64 -0
  97. package/dist/runtime/schema.d.ts +37 -0
  98. package/dist/runtime/schema.js +20 -0
  99. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +10 -0
  100. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +44 -0
  101. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +7 -0
  102. package/dist/runtime/server/api/_flows/[name]/runs.get.js +53 -0
  103. package/dist/runtime/server/api/_flows/[name]/schedule.post.d.ts +2 -0
  104. package/dist/runtime/server/api/_flows/[name]/schedule.post.js +57 -0
  105. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.d.ts +2 -0
  106. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.js +42 -0
  107. package/dist/runtime/server/api/_flows/[name]/schedules.get.d.ts +2 -0
  108. package/dist/runtime/server/api/_flows/[name]/schedules.get.js +48 -0
  109. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +2 -0
  110. package/dist/runtime/server/api/_flows/[name]/start.post.js +9 -0
  111. package/dist/runtime/server/api/_flows/index.get.d.ts +6 -0
  112. package/dist/runtime/server/api/_flows/index.get.js +5 -0
  113. package/dist/runtime/server/api/_flows/ws.d.ts +60 -0
  114. package/dist/runtime/server/api/_flows/ws.js +183 -0
  115. package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +2 -0
  116. package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +9 -0
  117. package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +2 -0
  118. package/dist/runtime/server/api/_queues/[name]/job/index.get.js +18 -0
  119. package/dist/runtime/server/api/_queues/index.get.d.ts +2 -0
  120. package/dist/runtime/server/api/_queues/index.get.js +63 -0
  121. package/dist/runtime/server/api/_queues/ws.d.ts +48 -0
  122. package/dist/runtime/server/api/_queues/ws.js +200 -0
  123. package/dist/runtime/server/events/adapters/fileAdapter.d.ts +2 -0
  124. package/dist/runtime/server/events/adapters/fileAdapter.js +382 -0
  125. package/dist/runtime/server/events/adapters/memoryAdapter.d.ts +2 -0
  126. package/dist/runtime/server/events/adapters/memoryAdapter.js +171 -0
  127. package/dist/runtime/server/events/adapters/redis/redisAdapter.d.ts +2 -0
  128. package/dist/runtime/server/events/adapters/redis/redisAdapter.js +348 -0
  129. package/dist/runtime/server/events/adapters/redis/redisPubSubGateway.d.ts +29 -0
  130. package/dist/runtime/server/events/adapters/redis/redisPubSubGateway.js +82 -0
  131. package/dist/runtime/server/events/eventBus.d.ts +20 -0
  132. package/dist/runtime/server/events/eventBus.js +35 -0
  133. package/dist/runtime/server/events/eventStoreFactory.d.ts +19 -0
  134. package/dist/runtime/server/events/eventStoreFactory.js +44 -0
  135. package/dist/runtime/server/events/streamNames.d.ts +17 -0
  136. package/dist/runtime/server/events/streamNames.js +17 -0
  137. package/dist/runtime/server/events/types.d.ts +63 -0
  138. package/dist/runtime/server/events/types.js +0 -0
  139. package/dist/runtime/server/events/wiring/flowWiring.d.ts +33 -0
  140. package/dist/runtime/server/events/wiring/flowWiring.js +406 -0
  141. package/dist/runtime/server/events/wiring/registry.d.ts +10 -0
  142. package/dist/runtime/server/events/wiring/registry.js +24 -0
  143. package/dist/runtime/server/plugins/00.event-store.d.ts +13 -0
  144. package/dist/runtime/server/plugins/00.event-store.js +16 -0
  145. package/dist/runtime/server/plugins/00.ws-lifecycle.d.ts +5 -0
  146. package/dist/runtime/server/plugins/00.ws-lifecycle.js +66 -0
  147. package/dist/runtime/server/plugins/flow-management.d.ts +13 -0
  148. package/dist/runtime/server/plugins/flow-management.js +65 -0
  149. package/dist/runtime/server/plugins/queue-management.d.ts +2 -0
  150. package/dist/runtime/server/plugins/queue-management.js +27 -0
  151. package/dist/runtime/server/plugins/state-cleanup.d.ts +11 -0
  152. package/dist/runtime/server/plugins/state-cleanup.js +93 -0
  153. package/dist/runtime/server/plugins/worker-management.d.ts +2 -0
  154. package/dist/runtime/server/plugins/worker-management.js +33 -0
  155. package/dist/runtime/server/queue/adapters/bullmq.d.ts +17 -0
  156. package/dist/runtime/server/queue/adapters/bullmq.js +164 -0
  157. package/dist/runtime/server/queue/queueFactory.d.ts +3 -0
  158. package/dist/runtime/server/queue/queueFactory.js +10 -0
  159. package/dist/runtime/server/queue/types.d.ts +47 -0
  160. package/dist/runtime/server/queue/types.js +0 -0
  161. package/dist/runtime/server/state/adapters/redis.d.ts +2 -0
  162. package/dist/runtime/server/state/adapters/redis.js +42 -0
  163. package/dist/runtime/server/state/stateFactory.d.ts +3 -0
  164. package/dist/runtime/server/state/stateFactory.js +17 -0
  165. package/dist/runtime/server/state/types.d.ts +23 -0
  166. package/dist/runtime/server/state/types.js +0 -0
  167. package/dist/runtime/server/tsconfig.json +3 -0
  168. package/dist/runtime/server/utils/defineQueueConfig.d.ts +154 -0
  169. package/dist/runtime/server/utils/defineQueueConfig.js +2 -0
  170. package/dist/runtime/server/utils/defineQueueWorker.d.ts +10 -0
  171. package/dist/runtime/server/utils/defineQueueWorker.js +17 -0
  172. package/dist/runtime/server/utils/useEventManager.d.ts +15 -0
  173. package/dist/runtime/server/utils/useEventManager.js +26 -0
  174. package/dist/runtime/server/utils/useEventStore.d.ts +20 -0
  175. package/dist/runtime/server/utils/useEventStore.js +119 -0
  176. package/dist/runtime/server/utils/useFlowEngine.d.ts +9 -0
  177. package/dist/runtime/server/utils/useFlowEngine.js +44 -0
  178. package/dist/runtime/server/utils/useLogs.d.ts +41 -0
  179. package/dist/runtime/server/utils/useLogs.js +74 -0
  180. package/dist/runtime/server/utils/useQueue.d.ts +31 -0
  181. package/dist/runtime/server/utils/useQueue.js +24 -0
  182. package/dist/runtime/server/utils/useServerLogger.d.ts +42 -0
  183. package/dist/runtime/server/utils/useServerLogger.js +54 -0
  184. package/dist/runtime/server/utils/wsPeerManager.d.ts +34 -0
  185. package/dist/runtime/server/utils/wsPeerManager.js +23 -0
  186. package/dist/runtime/server/worker/adapter.d.ts +4 -0
  187. package/dist/runtime/server/worker/adapter.js +65 -0
  188. package/dist/runtime/server/worker/runner/node.d.ts +27 -0
  189. package/dist/runtime/server/worker/runner/node.js +196 -0
  190. package/dist/runtime/types.d.ts +132 -0
  191. package/dist/types.d.mts +3 -0
  192. package/package.json +75 -0
@@ -0,0 +1,291 @@
1
+ <template>
2
+ <div class="h-full flex flex-col overflow-hidden">
3
+ <!-- Header -->
4
+ <div class="border-b border-gray-200 dark:border-gray-800 px-6 py-3 shrink-0">
5
+ <div class="flex items-center justify-between">
6
+ <div class="flex items-center gap-4">
7
+ <UButton
8
+ icon="i-lucide-arrow-left"
9
+ size="xs"
10
+ color="neutral"
11
+ variant="ghost"
12
+ @click="back"
13
+ />
14
+ <div>
15
+ <h1 class="text-lg font-semibold">
16
+ {{ queueName }}
17
+ </h1>
18
+ <p class="text-xs text-gray-500">
19
+ Queue Jobs
20
+ </p>
21
+ </div>
22
+ </div>
23
+ <div class="flex items-center gap-3">
24
+ <div
25
+ v-if="isConnected"
26
+ class="flex items-center gap-1.5 text-xs text-emerald-600 dark:text-emerald-400"
27
+ >
28
+ <div class="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
29
+ <span>Live</span>
30
+ <span
31
+ v-if="isAutoRefreshing"
32
+ class="text-[10px] text-gray-400"
33
+ >
34
+ (updating...)
35
+ </span>
36
+ </div>
37
+ <div
38
+ v-else-if="isReconnecting"
39
+ class="flex items-center gap-1.5 text-xs text-amber-600 dark:text-amber-400"
40
+ >
41
+ <div class="w-2 h-2 rounded-full bg-amber-500 animate-pulse" />
42
+ <span>Reconnecting...</span>
43
+ </div>
44
+ <UBadge
45
+ :label="counts?.active.toString() || '0'"
46
+ color="warning"
47
+ variant="subtle"
48
+ >
49
+ <template #leading>
50
+ Active
51
+ </template>
52
+ </UBadge>
53
+ <UBadge
54
+ :label="counts?.waiting.toString() || '0'"
55
+ color="info"
56
+ variant="subtle"
57
+ >
58
+ <template #leading>
59
+ Waiting
60
+ </template>
61
+ </UBadge>
62
+ <UBadge
63
+ :label="counts?.completed.toString() || '0'"
64
+ color="success"
65
+ variant="subtle"
66
+ >
67
+ <template #leading>
68
+ Completed
69
+ </template>
70
+ </UBadge>
71
+ <UBadge
72
+ :label="counts?.failed.toString() || '0'"
73
+ color="error"
74
+ variant="subtle"
75
+ >
76
+ <template #leading>
77
+ Failed
78
+ </template>
79
+ </UBadge>
80
+ <USelectMenu
81
+ v-model="selectedStateOption"
82
+ :items="stateOptions"
83
+ placeholder="All States"
84
+ size="xs"
85
+ class="w-32"
86
+ />
87
+ <UButton
88
+ icon="i-lucide-refresh-cw"
89
+ size="xs"
90
+ color="neutral"
91
+ variant="ghost"
92
+ :loading="status === 'pending'"
93
+ @click.prevent="onRefresh"
94
+ >
95
+ Refresh
96
+ </UButton>
97
+ </div>
98
+ </div>
99
+ </div>
100
+
101
+ <!-- Main Content -->
102
+ <div class="flex-1 min-h-0 overflow-hidden flex flex-col">
103
+ <div
104
+ v-if="!data || !data.jobs || data.jobs.length === 0"
105
+ class="flex-1 flex items-center justify-center text-sm text-gray-400"
106
+ >
107
+ No jobs found
108
+ </div>
109
+ <template v-else>
110
+ <div class="flex-1 min-h-0 p-4 overflow-auto">
111
+ <UTable
112
+ ref="table"
113
+ v-model:pagination="pagination"
114
+ :data="data.jobs"
115
+ :columns="columns"
116
+ :loading="status === 'pending'"
117
+ :pagination-options="{
118
+ getPaginationRowModel: getPaginationRowModel()
119
+ }"
120
+ :ui="{
121
+ base: 'table-fixed border-separate border-spacing-0',
122
+ thead: '[&>tr]:bg-elevated/50 [&>tr]:after:content-none',
123
+ tbody: '[&>tr]:last:[&>td]:border-b-0',
124
+ th: 'py-2 first:rounded-l-lg last:rounded-r-lg border-y border-default first:border-l last:border-r',
125
+ td: 'border-b border-default',
126
+ separator: 'h-0'
127
+ }"
128
+ />
129
+ </div>
130
+
131
+ <div class="flex items-center justify-between gap-3 border-t border-default p-4 shrink-0">
132
+ <div class="text-sm text-muted">
133
+ Showing {{ Math.min(pagination.pageIndex * pagination.pageSize + pagination.pageSize, data.jobs.length) }} of {{ data.jobs.length }} job(s)
134
+ <span
135
+ v-if="selectedState"
136
+ class="text-gray-400"
137
+ >
138
+ (filtered by {{ selectedStateOption?.label }})
139
+ </span>
140
+ </div>
141
+ <div class="flex items-center gap-1.5">
142
+ <UPagination
143
+ :default-page="(table?.tableApi?.getState().pagination.pageIndex || 0) + 1"
144
+ :items-per-page="table?.tableApi?.getState().pagination.pageSize || 20"
145
+ :total="data.jobs.length"
146
+ @update:page="(p) => table?.tableApi?.setPageIndex(p - 1)"
147
+ />
148
+ </div>
149
+ </div>
150
+ </template>
151
+ </div>
152
+ </div>
153
+ </template>
154
+
155
+ <script setup>
156
+ import { ref, computed, watch } from "#imports";
157
+ import { getPaginationRowModel } from "@tanstack/table-core";
158
+ import { UTable, UButton, UBadge, UPagination, USelectMenu } from "#components";
159
+ import { useQueueJobs } from "../../composables/useQueueJobs";
160
+ import { useQueueUpdates } from "../../composables/useQueueUpdates";
161
+ import { useComponentRouter } from "../../composables/useComponentRouter";
162
+ const UBadgeComponent = resolveComponent("UBadge");
163
+ const UButtonComponent = resolveComponent("UButton");
164
+ const router = useComponentRouter();
165
+ const queueName = computed(() => router.route.value?.params?.name || "");
166
+ const stateOptions = [
167
+ { label: "All States", value: null },
168
+ { label: "Waiting", value: "waiting" },
169
+ { label: "Active", value: "active" },
170
+ { label: "Completed", value: "completed" },
171
+ { label: "Failed", value: "failed" },
172
+ { label: "Delayed", value: "delayed" },
173
+ { label: "Paused", value: "paused" }
174
+ ];
175
+ const selectedStateOption = ref(stateOptions[0]);
176
+ const selectedState = computed(() => selectedStateOption.value?.value ?? null);
177
+ const { data, refresh, status } = useQueueJobs(queueName, selectedState);
178
+ const { counts, isConnected, isReconnecting, shouldRefreshJobs, resetRefreshFlag } = useQueueUpdates(queueName);
179
+ const isAutoRefreshing = ref(false);
180
+ watch(selectedState, () => {
181
+ if (table.value?.tableApi) {
182
+ table.value.tableApi.setPageIndex(0);
183
+ }
184
+ });
185
+ watch(shouldRefreshJobs, async (shouldRefresh) => {
186
+ if (shouldRefresh) {
187
+ isAutoRefreshing.value = true;
188
+ await refresh();
189
+ resetRefreshFlag();
190
+ setTimeout(() => {
191
+ isAutoRefreshing.value = false;
192
+ }, 500);
193
+ }
194
+ });
195
+ const table = useTemplateRef("table");
196
+ const pagination = ref({
197
+ pageIndex: 0,
198
+ pageSize: 20
199
+ });
200
+ const onRefresh = async () => {
201
+ await refresh();
202
+ };
203
+ const back = () => {
204
+ router.push("/queues");
205
+ };
206
+ const selectJob = (jobId) => {
207
+ router.push(`/queues/${queueName.value}/jobs/${jobId}`);
208
+ };
209
+ const columns = [
210
+ {
211
+ accessorKey: "id",
212
+ header: "Job ID",
213
+ cell: ({ row }) => {
214
+ const id = row.original.id;
215
+ return h("div", {
216
+ class: "font-mono text-xs cursor-pointer hover:underline",
217
+ onClick: () => selectJob(row.original.id)
218
+ }, id.length > 16 ? `${id.substring(0, 8)}...${id.substring(id.length - 8)}` : id);
219
+ }
220
+ },
221
+ {
222
+ accessorKey: "name",
223
+ header: "Name",
224
+ cell: ({ row }) => {
225
+ return h("div", {
226
+ class: "font-medium cursor-pointer hover:underline",
227
+ onClick: () => selectJob(row.original.id)
228
+ }, row.original.name);
229
+ }
230
+ },
231
+ {
232
+ accessorKey: "state",
233
+ header: "State",
234
+ cell: ({ row }) => {
235
+ const state = row.original.state;
236
+ const colorMap = {
237
+ waiting: "info",
238
+ active: "warning",
239
+ completed: "success",
240
+ failed: "error",
241
+ delayed: "secondary",
242
+ paused: "warning"
243
+ };
244
+ return h(UBadgeComponent, {
245
+ label: state || "unknown",
246
+ color: colorMap[state || ""] || "neutral",
247
+ variant: "subtle",
248
+ class: "capitalize"
249
+ });
250
+ }
251
+ },
252
+ {
253
+ accessorKey: "timestamp",
254
+ header: "Created",
255
+ cell: ({ row }) => {
256
+ const timestamp = row.original.timestamp;
257
+ if (!timestamp) return h("div", { class: "text-gray-400 text-xs" }, "-");
258
+ const date = new Date(timestamp);
259
+ return h(
260
+ "div",
261
+ { class: "text-xs" },
262
+ date.toLocaleString("de-DE", {
263
+ timeZone: "Europe/Berlin",
264
+ day: "2-digit",
265
+ month: "2-digit",
266
+ year: "numeric",
267
+ hour: "2-digit",
268
+ minute: "2-digit",
269
+ second: "2-digit"
270
+ })
271
+ );
272
+ }
273
+ },
274
+ {
275
+ id: "actions",
276
+ header: "",
277
+ cell: ({ row }) => {
278
+ return h(UButtonComponent, {
279
+ icon: "i-lucide-arrow-right",
280
+ size: "xs",
281
+ color: "neutral",
282
+ variant: "ghost",
283
+ square: true,
284
+ onClick: () => {
285
+ selectJob(row.original.id);
286
+ }
287
+ });
288
+ }
289
+ }
290
+ ];
291
+ </script>
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,6 @@
1
+ import '@vue-flow/core/dist/style.css';
2
+ import '@vue-flow/core/dist/theme-default.css';
3
+ import '@vue-flow/controls/dist/style.css';
4
+ import '@vue-flow/minimap/dist/style.css';
5
+ declare const _default: import("#app").Plugin<Record<string, unknown>> & import("#app").ObjectPlugin<Record<string, unknown>>;
6
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ import { VueFlow } from "@vue-flow/core";
3
+ import { Controls } from "@vue-flow/controls";
4
+ import { MiniMap } from "@vue-flow/minimap";
5
+ import { Background } from "@vue-flow/background";
6
+ import "@vue-flow/core/dist/style.css";
7
+ import "@vue-flow/core/dist/theme-default.css";
8
+ import "@vue-flow/controls/dist/style.css";
9
+ import "@vue-flow/minimap/dist/style.css";
10
+ export default defineNuxtPlugin((nuxtApp) => {
11
+ nuxtApp.vueApp.component("VueFlow", VueFlow);
12
+ nuxtApp.vueApp.component("Controls", Controls);
13
+ nuxtApp.vueApp.component("MiniMap", MiniMap);
14
+ nuxtApp.vueApp.component("Background", Background);
15
+ });
@@ -0,0 +1,11 @@
1
+ export declare const QUEUE_STATUSES: {
2
+ readonly latest: "latest";
3
+ readonly active: "active";
4
+ readonly waiting: "waiting";
5
+ readonly waitingChildren: "waiting-children";
6
+ readonly prioritized: "prioritized";
7
+ readonly completed: "completed";
8
+ readonly failed: "failed";
9
+ readonly delayed: "delayed";
10
+ readonly paused: "paused";
11
+ };
@@ -0,0 +1,11 @@
1
+ export const QUEUE_STATUSES = {
2
+ latest: "latest",
3
+ active: "active",
4
+ waiting: "waiting",
5
+ waitingChildren: "waiting-children",
6
+ prioritized: "prioritized",
7
+ completed: "completed",
8
+ failed: "failed",
9
+ delayed: "delayed",
10
+ paused: "paused"
11
+ };
@@ -0,0 +1,64 @@
1
+ import sys
2
+ import json
3
+ import importlib.util
4
+ import os
5
+ import platform
6
+
7
+
8
+ def send_message(payload):
9
+ """Send a JSON line to the parent process.
10
+
11
+ On Unix-like systems, write to the file descriptor provided via env
12
+ NODE_CHANNEL_FD. On Windows, write to stdout.
13
+ """
14
+ bytes_message = (json.dumps(payload) + "\n").encode("utf-8")
15
+
16
+ if platform.system() == "Windows":
17
+ # On Windows, write to stdout
18
+ sys.stdout.buffer.write(bytes_message)
19
+ sys.stdout.buffer.flush()
20
+ else:
21
+ # On Unix systems, use the provided file descriptor
22
+ fd = int(os.environ["NODE_CHANNEL_FD"]) # expected to be set by parent
23
+ os.write(fd, bytes_message)
24
+
25
+
26
+ async def run_python_module(file_path: str) -> None:
27
+ try:
28
+ module_dir = os.path.dirname(os.path.abspath(file_path))
29
+
30
+ if module_dir not in sys.path:
31
+ sys.path.insert(0, module_dir)
32
+
33
+ spec = importlib.util.spec_from_file_location(
34
+ os.path.splitext(os.path.basename(file_path))[0], file_path
35
+ )
36
+ if spec is None or spec.loader is None:
37
+ raise ImportError(f"Could not load module from {file_path}")
38
+
39
+ module = importlib.util.module_from_spec(spec)
40
+ # Set a basic package name to allow relative imports from same dir
41
+ module.__package__ = os.path.basename(module_dir)
42
+ spec.loader.exec_module(module)
43
+
44
+ if not hasattr(module, "config"):
45
+ raise AttributeError(f"No 'config' found in module {file_path}")
46
+
47
+ cfg = getattr(module, "config")
48
+ # Remove keys that are not serializable or not needed
49
+ if isinstance(cfg, dict) and "middleware" in cfg:
50
+ del cfg["middleware"]
51
+
52
+ send_message(cfg)
53
+ except Exception as error:
54
+ print("Error running Python module:", str(error), file=sys.stderr)
55
+ sys.exit(1)
56
+
57
+
58
+ if __name__ == "__main__":
59
+ if len(sys.argv) < 2:
60
+ sys.exit(1)
61
+ file_path = sys.argv[1]
62
+ import asyncio
63
+
64
+ asyncio.run(run_python_module(file_path))
@@ -0,0 +1,37 @@
1
+ import z from 'zod';
2
+ export declare const JobSchema: z.ZodObject<{
3
+ id: z.ZodString;
4
+ name: z.ZodString;
5
+ data: z.ZodAny;
6
+ progress: z.ZodNumber;
7
+ opts: z.ZodObject<{
8
+ attempts: z.ZodNumber;
9
+ delay: z.ZodOptional<z.ZodNumber>;
10
+ }, z.core.$strip>;
11
+ state: z.ZodAny;
12
+ returnvalue: z.ZodAny;
13
+ attemptsStarted: z.ZodNumber;
14
+ attemptsMade: z.ZodNumber;
15
+ delay: z.ZodNumber;
16
+ timestamp: z.ZodNumber;
17
+ finishedOn: z.ZodOptional<z.ZodNumber>;
18
+ processedOn: z.ZodOptional<z.ZodNumber>;
19
+ }, z.core.$strip>;
20
+ export declare const JobSchemaArray: z.ZodArray<z.ZodObject<{
21
+ id: z.ZodString;
22
+ name: z.ZodString;
23
+ data: z.ZodAny;
24
+ progress: z.ZodNumber;
25
+ opts: z.ZodObject<{
26
+ attempts: z.ZodNumber;
27
+ delay: z.ZodOptional<z.ZodNumber>;
28
+ }, z.core.$strip>;
29
+ state: z.ZodAny;
30
+ returnvalue: z.ZodAny;
31
+ attemptsStarted: z.ZodNumber;
32
+ attemptsMade: z.ZodNumber;
33
+ delay: z.ZodNumber;
34
+ timestamp: z.ZodNumber;
35
+ finishedOn: z.ZodOptional<z.ZodNumber>;
36
+ processedOn: z.ZodOptional<z.ZodNumber>;
37
+ }, z.core.$strip>>;
@@ -0,0 +1,20 @@
1
+ import z from "zod";
2
+ export const JobSchema = z.object({
3
+ id: z.string(),
4
+ name: z.string(),
5
+ data: z.any(),
6
+ progress: z.number(),
7
+ opts: z.object({
8
+ attempts: z.number(),
9
+ delay: z.number().optional()
10
+ }),
11
+ state: z.any(),
12
+ returnvalue: z.any(),
13
+ attemptsStarted: z.number(),
14
+ attemptsMade: z.number(),
15
+ delay: z.number(),
16
+ timestamp: z.number(),
17
+ finishedOn: z.number().optional(),
18
+ processedOn: z.number().optional()
19
+ });
20
+ export const JobSchemaArray = z.array(JobSchema);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * DELETE /api/_flows/:flowName/clear-history
3
+ *
4
+ * Clears all event history for a specific flow.
5
+ * This deletes:
6
+ * - All flow run streams (nq:flow:run-*)
7
+ * - The flow runs index (nq:flows:<flowName>)
8
+ */
9
+ declare const _default: any;
10
+ export default _default;
@@ -0,0 +1,44 @@
1
+ import { defineEventHandler, createError, useEventStore } from "#imports";
2
+ export default defineEventHandler(async (event) => {
3
+ const flowName = event.context.params?.name;
4
+ if (!flowName) {
5
+ throw createError({ statusCode: 400, statusMessage: "Flow name required" });
6
+ }
7
+ try {
8
+ const store = useEventStore();
9
+ const names = store.names();
10
+ let deletedStreams = 0;
11
+ let deletedIndex = false;
12
+ const indexKey = names.flowIndex(flowName);
13
+ if (store.indexRead) {
14
+ const runs = await store.indexRead(indexKey, { limit: 1e4 });
15
+ if (store.deleteStream) {
16
+ for (const run of runs) {
17
+ const streamName = names.flow(run.id);
18
+ await store.deleteStream(streamName);
19
+ if (store.deleteIndex) {
20
+ const metaKey = `${indexKey}:meta:${run.id}`;
21
+ await store.deleteIndex(metaKey);
22
+ }
23
+ deletedStreams++;
24
+ }
25
+ }
26
+ }
27
+ if (store.deleteIndex) {
28
+ await store.deleteIndex(indexKey);
29
+ deletedIndex = true;
30
+ }
31
+ return {
32
+ success: true,
33
+ flowName,
34
+ deletedStreams,
35
+ deletedIndex
36
+ };
37
+ } catch (error) {
38
+ throw createError({
39
+ statusCode: 500,
40
+ statusMessage: "Failed to clear flow history",
41
+ data: error instanceof Error ? error.message : String(error)
42
+ });
43
+ }
44
+ });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * GET /api/_flows/:name/runs?limit=50&offset=0
3
+ *
4
+ * List runs for a specific flow with pagination support
5
+ */
6
+ declare const _default: any;
7
+ export default _default;
@@ -0,0 +1,53 @@
1
+ import { defineEventHandler, getRouterParam, getQuery, useEventStore, useServerLogger } from "#imports";
2
+ const logger = useServerLogger("api-flows-runs");
3
+ export default defineEventHandler(async (event) => {
4
+ const flowName = getRouterParam(event, "name");
5
+ const query = getQuery(event);
6
+ const limit = Math.min(Number.parseInt(query.limit) || 50, 100);
7
+ const offset = Math.max(Number.parseInt(query.offset) || 0, 0);
8
+ const status = query.status;
9
+ event.node.res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
10
+ event.node.res.setHeader("Pragma", "no-cache");
11
+ if (!flowName) {
12
+ return { error: "Missing flow name" };
13
+ }
14
+ const store = useEventStore();
15
+ const names = store.names();
16
+ try {
17
+ const runIndexKey = names.flowIndex(flowName);
18
+ let totalCount = 0;
19
+ try {
20
+ const allEntries = await store.indexRead(runIndexKey, { limit: 1e4 });
21
+ totalCount = allEntries.length;
22
+ } catch {
23
+ totalCount = 0;
24
+ }
25
+ const entries = await store.indexRead(runIndexKey, { offset, limit });
26
+ const filteredEntries = status ? entries.filter((e) => e.metadata?.status === status) : entries;
27
+ const items = filteredEntries.map((entry) => ({
28
+ id: entry.id,
29
+ flowName,
30
+ status: entry.metadata?.status || "unknown",
31
+ createdAt: new Date(entry.score).toISOString(),
32
+ startedAt: entry.metadata?.startedAt ? new Date(entry.metadata.startedAt).toISOString() : void 0,
33
+ completedAt: entry.metadata?.completedAt ? new Date(entry.metadata.completedAt).toISOString() : void 0,
34
+ stepCount: entry.metadata?.stepCount || 0,
35
+ completedSteps: entry.metadata?.completedSteps || 0
36
+ }));
37
+ return {
38
+ flowName,
39
+ count: items.length,
40
+ total: totalCount,
41
+ offset,
42
+ limit,
43
+ hasMore: offset + items.length < totalCount,
44
+ items
45
+ };
46
+ } catch (err) {
47
+ logger.error("[flows/runs] error:", { error: err });
48
+ return {
49
+ error: "Failed to list runs",
50
+ message: err instanceof Error ? err.message : String(err)
51
+ };
52
+ }
53
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,57 @@
1
+ import { defineEventHandler, readBody, getRouterParam, createError, useQueue, $useQueueRegistry } from "#imports";
2
+ export default defineEventHandler(async (event) => {
3
+ const flowName = getRouterParam(event, "name");
4
+ if (!flowName) {
5
+ throw createError({ statusCode: 400, statusMessage: "Flow name is required" });
6
+ }
7
+ const body = await readBody(event);
8
+ const { input, cron, delay, jobId, metadata } = body;
9
+ if (cron && delay) {
10
+ throw createError({
11
+ statusCode: 400,
12
+ statusMessage: "Cannot specify both cron and delay"
13
+ });
14
+ }
15
+ if (!cron && !delay) {
16
+ throw createError({
17
+ statusCode: 400,
18
+ statusMessage: "Must specify either cron or delay"
19
+ });
20
+ }
21
+ const registry = $useQueueRegistry();
22
+ const flow = registry?.flows?.[flowName];
23
+ if (!flow || !flow.entry) {
24
+ throw createError({ statusCode: 404, statusMessage: `Flow '${flowName}' not found` });
25
+ }
26
+ const queueName = typeof flow.entry.queue === "string" ? flow.entry.queue : flow.entry.queue?.name || flow.entry.queue;
27
+ const queue = useQueue();
28
+ const scheduleOpts = {};
29
+ if (cron) scheduleOpts.cron = cron;
30
+ if (delay) scheduleOpts.delay = delay;
31
+ const jobData = {
32
+ __scheduledFlowStart: true,
33
+ __flowName: flowName,
34
+ __flowInput: input || {},
35
+ __schedule: {
36
+ metadata,
37
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
38
+ }
39
+ };
40
+ const id = await queue.schedule(
41
+ queueName,
42
+ {
43
+ name: flow.entry.step,
44
+ data: jobData,
45
+ opts: jobId ? { jobId } : void 0
46
+ },
47
+ scheduleOpts
48
+ );
49
+ return {
50
+ id,
51
+ flowName,
52
+ queue: queueName,
53
+ step: flow.entry.step,
54
+ schedule: scheduleOpts,
55
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
56
+ };
57
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;