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,42 @@
1
+ import { defineEventHandler, getRouterParam, createError, useRuntimeConfig, $useQueueRegistry } from "#imports";
2
+ import { Queue } from "bullmq";
3
+ export default defineEventHandler(async (event) => {
4
+ const flowName = getRouterParam(event, "name");
5
+ const scheduleId = getRouterParam(event, "id");
6
+ if (!flowName || !scheduleId) {
7
+ throw createError({ statusCode: 400, statusMessage: "Flow name and schedule ID are required" });
8
+ }
9
+ const registry = $useQueueRegistry();
10
+ const flow = registry?.flows?.[flowName];
11
+ if (!flow || !flow.entry) {
12
+ throw createError({ statusCode: 404, statusMessage: `Flow '${flowName}' not found` });
13
+ }
14
+ const queueName = typeof flow.entry.queue === "string" ? flow.entry.queue : flow.entry.queue?.name || flow.entry.queue;
15
+ const rc = useRuntimeConfig();
16
+ const connection = rc.queue?.redis;
17
+ let prefix;
18
+ try {
19
+ if (registry && Array.isArray(registry.workers)) {
20
+ const worker = registry.workers.find((w) => w?.queue?.name === queueName);
21
+ if (worker?.queue?.prefix) {
22
+ prefix = worker.queue.prefix;
23
+ }
24
+ }
25
+ } catch {
26
+ }
27
+ const queue = new Queue(queueName, { connection, prefix });
28
+ try {
29
+ await queue.removeRepeatableByKey(scheduleId);
30
+ await queue.close();
31
+ return {
32
+ success: true,
33
+ message: "Schedule deleted successfully"
34
+ };
35
+ } catch (error) {
36
+ await queue.close();
37
+ throw createError({
38
+ statusCode: 500,
39
+ statusMessage: `Failed to delete schedule: ${error.message}`
40
+ });
41
+ }
42
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,48 @@
1
+ import { defineEventHandler, getRouterParam, createError, useRuntimeConfig, $useQueueRegistry } from "#imports";
2
+ import { Queue } from "bullmq";
3
+ export default defineEventHandler(async (event) => {
4
+ const flowName = getRouterParam(event, "name");
5
+ if (!flowName) {
6
+ throw createError({ statusCode: 400, statusMessage: "Flow name is required" });
7
+ }
8
+ const registry = $useQueueRegistry();
9
+ const flow = registry?.flows?.[flowName];
10
+ if (!flow || !flow.entry) {
11
+ throw createError({ statusCode: 404, statusMessage: `Flow '${flowName}' not found` });
12
+ }
13
+ const rc = useRuntimeConfig();
14
+ const connection = rc.queue?.redis;
15
+ const queueName = typeof flow.entry.queue === "string" ? flow.entry.queue : flow.entry.queue?.name || flow.entry.queue;
16
+ let prefix;
17
+ try {
18
+ if (registry && Array.isArray(registry.workers)) {
19
+ const worker = registry.workers.find((w) => w?.queue?.name === queueName);
20
+ if (worker?.queue?.prefix) {
21
+ prefix = worker.queue.prefix;
22
+ }
23
+ }
24
+ } catch {
25
+ }
26
+ const queue = new Queue(queueName, { connection, prefix });
27
+ try {
28
+ const repeatableJobs = await queue.getRepeatableJobs();
29
+ const schedules = repeatableJobs.filter((job) => job.name === flow.entry.step).map((job) => ({
30
+ id: job.key,
31
+ flowName,
32
+ queue: queueName,
33
+ step: flow.entry.step,
34
+ schedule: {
35
+ cron: job.pattern
36
+ },
37
+ nextRun: job.next ? new Date(job.next).toISOString() : void 0
38
+ }));
39
+ await queue.close();
40
+ return schedules;
41
+ } catch (error) {
42
+ await queue.close();
43
+ throw createError({
44
+ statusCode: 500,
45
+ statusMessage: `Failed to list schedules: ${error.message}`
46
+ });
47
+ }
48
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { defineEventHandler, getRouterParam, createError, readBody, useFlowEngine } from "#imports";
2
+ export default defineEventHandler(async (event) => {
3
+ const flowName = getRouterParam(event, "name");
4
+ if (!flowName) throw createError({ statusCode: 400, statusMessage: "Flow name is required" });
5
+ const { startFlow } = useFlowEngine();
6
+ const body = await readBody(event);
7
+ const result = await startFlow(flowName, body || {});
8
+ return result;
9
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns pre-analyzed flows from the build-time registry.
3
+ * Flows are analyzed during the build process for optimal performance.
4
+ */
5
+ declare const _default: any;
6
+ export default _default;
@@ -0,0 +1,5 @@
1
+ import { defineEventHandler, $useAnalyzedFlows } from "#imports";
2
+ export default defineEventHandler(() => {
3
+ const flows = $useAnalyzedFlows();
4
+ return flows || [];
5
+ });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * WebSocket endpoint for flow run events
3
+ * Supports subscribing to specific flow runs and receiving real-time updates
4
+ *
5
+ * Message format (client -> server):
6
+ * {
7
+ * "type": "subscribe",
8
+ * "flowName": "example",
9
+ * "runId": "abc123"
10
+ * }
11
+ *
12
+ * {
13
+ * "type": "unsubscribe",
14
+ * "flowName": "example",
15
+ * "runId": "abc123"
16
+ * }
17
+ *
18
+ * {
19
+ * "type": "ping"
20
+ * }
21
+ *
22
+ * Message format (server -> client):
23
+ * {
24
+ * "type": "event",
25
+ * "flowName": "example",
26
+ * "runId": "abc123",
27
+ * "event": { v: 1, eventType: "...", record: {...} }
28
+ * }
29
+ *
30
+ * {
31
+ * "type": "history",
32
+ * "flowName": "example",
33
+ * "runId": "abc123",
34
+ * "events": [ ...historicalEvents ]
35
+ * }
36
+ *
37
+ * {
38
+ * "type": "subscribed",
39
+ * "flowName": "example",
40
+ * "runId": "abc123"
41
+ * }
42
+ *
43
+ * {
44
+ * "type": "unsubscribed",
45
+ * "flowName": "example",
46
+ * "runId": "abc123"
47
+ * }
48
+ *
49
+ * {
50
+ * "type": "pong",
51
+ * "timestamp": 1234567890
52
+ * }
53
+ *
54
+ * {
55
+ * "type": "error",
56
+ * "message": "error description"
57
+ * }
58
+ */
59
+ declare const _default: any;
60
+ export default _default;
@@ -0,0 +1,183 @@
1
+ import {
2
+ defineWebSocketHandler,
3
+ useEventStore,
4
+ registerWsPeer,
5
+ unregisterWsPeer,
6
+ useServerLogger
7
+ } from "#imports";
8
+ const logger = useServerLogger("api-flows-ws");
9
+ const peerContexts = /* @__PURE__ */ new WeakMap();
10
+ function safeSend(peer, data) {
11
+ try {
12
+ peer.send(JSON.stringify(data));
13
+ return true;
14
+ } catch {
15
+ return false;
16
+ }
17
+ }
18
+ export default defineWebSocketHandler({
19
+ open(peer) {
20
+ logger.info("[ws] client connected:", { peerId: peer.id });
21
+ registerWsPeer(peer);
22
+ peerContexts.set(peer, {
23
+ subscriptions: /* @__PURE__ */ new Map()
24
+ });
25
+ safeSend(peer, {
26
+ type: "connected",
27
+ timestamp: Date.now()
28
+ });
29
+ },
30
+ async message(peer, message) {
31
+ const context = peerContexts.get(peer);
32
+ if (!context) {
33
+ logger.error("[ws] no context for peer:", { peerId: peer.id });
34
+ return;
35
+ }
36
+ let data;
37
+ try {
38
+ data = JSON.parse(message.text());
39
+ } catch {
40
+ safeSend(peer, {
41
+ type: "error",
42
+ message: "Invalid JSON"
43
+ });
44
+ return;
45
+ }
46
+ const { type, flowName, runId } = data;
47
+ if (type === "subscribe") {
48
+ if (!flowName || !runId) {
49
+ safeSend(peer, {
50
+ type: "error",
51
+ message: "Missing flowName or runId"
52
+ });
53
+ return;
54
+ }
55
+ const store = useEventStore();
56
+ const names = store.names();
57
+ const flowStream = names.flow(runId);
58
+ const subscriptionKey = `${flowName}:${runId}`;
59
+ const existingUnsub = context.subscriptions.get(subscriptionKey);
60
+ if (existingUnsub) {
61
+ try {
62
+ existingUnsub();
63
+ } catch (err) {
64
+ logger.error("[ws] error unsubscribing:", { error: err });
65
+ }
66
+ }
67
+ const unsub = store.subscribe(flowStream, async (event) => {
68
+ safeSend(peer, {
69
+ type: "event",
70
+ flowName,
71
+ runId,
72
+ event: {
73
+ v: 1,
74
+ eventType: event.type,
75
+ record: event
76
+ }
77
+ });
78
+ });
79
+ context.subscriptions.set(subscriptionKey, unsub);
80
+ try {
81
+ const historicalEvents = await store.read(flowStream, {
82
+ limit: 100,
83
+ direction: "forward"
84
+ });
85
+ safeSend(peer, {
86
+ type: "history",
87
+ flowName,
88
+ runId,
89
+ events: historicalEvents.map((e) => ({
90
+ v: 1,
91
+ eventType: e.kind || e.type,
92
+ record: e
93
+ }))
94
+ });
95
+ } catch (err) {
96
+ logger.error("[ws] error sending history:", { error: err });
97
+ safeSend(peer, {
98
+ type: "error",
99
+ message: "Failed to load history"
100
+ });
101
+ }
102
+ safeSend(peer, {
103
+ type: "subscribed",
104
+ flowName,
105
+ runId
106
+ });
107
+ } else if (type === "unsubscribe") {
108
+ if (!flowName || !runId) {
109
+ safeSend(peer, {
110
+ type: "error",
111
+ message: "Missing flowName or runId"
112
+ });
113
+ return;
114
+ }
115
+ const subscriptionKey = `${flowName}:${runId}`;
116
+ const unsub = context.subscriptions.get(subscriptionKey);
117
+ if (unsub) {
118
+ try {
119
+ unsub();
120
+ context.subscriptions.delete(subscriptionKey);
121
+ safeSend(peer, {
122
+ type: "unsubscribed",
123
+ flowName,
124
+ runId
125
+ });
126
+ } catch (err) {
127
+ logger.error("[ws] error unsubscribing:", { error: err });
128
+ safeSend(peer, {
129
+ type: "error",
130
+ message: "Failed to unsubscribe"
131
+ });
132
+ }
133
+ }
134
+ } else if (type === "ping") {
135
+ safeSend(peer, {
136
+ type: "pong",
137
+ timestamp: Date.now()
138
+ });
139
+ } else {
140
+ safeSend(peer, {
141
+ type: "error",
142
+ message: `Unknown message type: ${type}`
143
+ });
144
+ }
145
+ },
146
+ close(peer, event) {
147
+ const isNormalClosure = event?.code === 1e3 || event?.code === 1001;
148
+ if (!isNormalClosure) {
149
+ logger.info("[ws] client disconnected:", { peerId: peer.id, code: event?.code, reason: event?.reason });
150
+ }
151
+ unregisterWsPeer(peer);
152
+ const context = peerContexts.get(peer);
153
+ if (context) {
154
+ for (const unsub of context.subscriptions.values()) {
155
+ try {
156
+ unsub();
157
+ } catch (err) {
158
+ if (!isNormalClosure) {
159
+ logger.error("[ws] error unsubscribing on close:", { error: err });
160
+ }
161
+ }
162
+ }
163
+ context.subscriptions.clear();
164
+ peerContexts.delete(peer);
165
+ }
166
+ },
167
+ error(peer, error) {
168
+ logger.error("[ws] error for peer:", { peerId: peer.id, error });
169
+ unregisterWsPeer(peer);
170
+ const context = peerContexts.get(peer);
171
+ if (context) {
172
+ for (const unsub of context.subscriptions.values()) {
173
+ try {
174
+ unsub();
175
+ } catch (err) {
176
+ logger.error("[ws] error unsubscribing on error:", { error: err });
177
+ }
178
+ }
179
+ context.subscriptions.clear();
180
+ peerContexts.delete(peer);
181
+ }
182
+ }
183
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import { defineEventHandler, getRouterParam, useQueue } from "#imports";
2
+ export default defineEventHandler(async (event) => {
3
+ const name = getRouterParam(event, "name") || "";
4
+ const id = getRouterParam(event, "id") || "";
5
+ const { getJob } = useQueue();
6
+ const job = await getJob(name, id);
7
+ if (!job) return null;
8
+ return { ...job, queue: name };
9
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,18 @@
1
+ import { defineEventHandler, getRouterParam, getQuery, useQueue, createError } from "#imports";
2
+ export default defineEventHandler(async (event) => {
3
+ const name = getRouterParam(event, "name");
4
+ if (!name) {
5
+ throw createError({ statusCode: 400, statusMessage: "Missing queue name" });
6
+ }
7
+ const query = getQuery(event);
8
+ const state = query.state;
9
+ const { getJobs } = useQueue();
10
+ const jobs = await getJobs(name, {
11
+ state: state ? [state] : void 0,
12
+ limit: 1e3
13
+ // Fetch all jobs, pagination happens client-side
14
+ });
15
+ return {
16
+ jobs
17
+ };
18
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,63 @@
1
+ import { defineEventHandler, useRuntimeConfig, $useQueueRegistry, useQueue, useServerLogger } from "#imports";
2
+ const logger = useServerLogger("api-queues-index");
3
+ export default defineEventHandler(async () => {
4
+ const rc = useRuntimeConfig();
5
+ const cfgQueues = rc?.queue?.queues || {};
6
+ const registry = $useQueueRegistry();
7
+ const queue = useQueue();
8
+ const names = /* @__PURE__ */ new Set();
9
+ for (const q in cfgQueues) names.add(q);
10
+ if (registry?.workers?.length) {
11
+ for (const w of registry.workers) names.add(w.queue.name);
12
+ }
13
+ const queuesWithCounts = await Promise.all(
14
+ Array.from(names).map(async (name) => {
15
+ try {
16
+ const counts = await queue.getJobCounts(name);
17
+ const isPaused = await queue.isPaused(name);
18
+ const worker = registry?.workers?.find((w) => w.queue.name === name);
19
+ const queueConfig = worker?.queue || {};
20
+ const workerConfig = worker?.worker || {};
21
+ return {
22
+ name,
23
+ counts,
24
+ isPaused,
25
+ config: {
26
+ queue: {
27
+ prefix: queueConfig.prefix,
28
+ defaultJobOptions: queueConfig.defaultJobOptions,
29
+ limiter: queueConfig.limiter
30
+ },
31
+ worker: {
32
+ concurrency: workerConfig.concurrency,
33
+ lockDurationMs: workerConfig.lockDurationMs,
34
+ maxStalledCount: workerConfig.maxStalledCount,
35
+ drainDelayMs: workerConfig.drainDelayMs,
36
+ autorun: workerConfig.autorun,
37
+ pollingIntervalMs: workerConfig.pollingIntervalMs
38
+ }
39
+ }
40
+ };
41
+ } catch (err) {
42
+ logger.error(`Failed to get counts for queue ${name}:`, { error: err });
43
+ return {
44
+ name,
45
+ counts: {
46
+ active: 0,
47
+ completed: 0,
48
+ failed: 0,
49
+ delayed: 0,
50
+ waiting: 0,
51
+ paused: 0
52
+ },
53
+ isPaused: false,
54
+ config: {
55
+ queue: {},
56
+ worker: {}
57
+ }
58
+ };
59
+ }
60
+ })
61
+ );
62
+ return queuesWithCounts;
63
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * WebSocket endpoint for queue events
3
+ * Supports subscribing to specific queues and receiving real-time job updates
4
+ *
5
+ * Message format (client -> server):
6
+ * {
7
+ * "type": "subscribe",
8
+ * "queueName": "test"
9
+ * }
10
+ *
11
+ * {
12
+ * "type": "unsubscribe",
13
+ * "queueName": "test"
14
+ * }
15
+ *
16
+ * {
17
+ * "type": "ping"
18
+ * }
19
+ *
20
+ * Message format (server -> client):
21
+ * {
22
+ * "type": "event",
23
+ * "queueName": "test",
24
+ * "event": { eventType: "waiting|active|completed|failed", jobId: "...", ... }
25
+ * }
26
+ *
27
+ * {
28
+ * "type": "subscribed",
29
+ * "queueName": "test"
30
+ * }
31
+ *
32
+ * {
33
+ * "type": "unsubscribed",
34
+ * "queueName": "test"
35
+ * }
36
+ *
37
+ * {
38
+ * "type": "pong",
39
+ * "timestamp": 1234567890
40
+ * }
41
+ *
42
+ * {
43
+ * "type": "error",
44
+ * "message": "error description"
45
+ * }
46
+ */
47
+ declare const _default: any;
48
+ export default _default;