@nvent-addon/app 0.5.15 → 1.0.0-alpha.1

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 (95) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +3 -2
  3. package/dist/runtime/app/components/DashboardCard.d.vue.ts +1 -1
  4. package/dist/runtime/app/components/DashboardCard.vue.d.ts +1 -1
  5. package/dist/runtime/app/composables/useWorkers.d.ts +57 -0
  6. package/dist/runtime/app/composables/useWorkers.js +42 -0
  7. package/dist/runtime/app/pages/dashboard.vue +1 -654
  8. package/dist/runtime/app/pages/index.vue +25 -41
  9. package/dist/runtime/app/pages/workers.vue +458 -0
  10. package/dist/runtime/server/api/_workers/index.get.d.ts +8 -0
  11. package/dist/runtime/server/api/_workers/index.get.js +14 -0
  12. package/package.json +12 -11
  13. package/dist/runtime/app/components/ComponentRouter.d.vue.ts +0 -46
  14. package/dist/runtime/app/components/ComponentRouter.vue +0 -26
  15. package/dist/runtime/app/components/ComponentRouter.vue.d.ts +0 -46
  16. package/dist/runtime/app/components/ComponentShell.d.vue.ts +0 -23
  17. package/dist/runtime/app/components/ComponentShell.vue +0 -97
  18. package/dist/runtime/app/components/ComponentShell.vue.d.ts +0 -23
  19. package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +0 -33
  20. package/dist/runtime/app/components/ConfirmDialog.vue +0 -120
  21. package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +0 -33
  22. package/dist/runtime/app/composables/useComponentRouter.d.ts +0 -46
  23. package/dist/runtime/app/composables/useComponentRouter.js +0 -248
  24. package/dist/runtime/app/pages/flows/[name].vue +0 -750
  25. package/dist/runtime/app/pages/flows/index.d.vue.ts +0 -3
  26. package/dist/runtime/app/pages/flows/index.vue +0 -381
  27. package/dist/runtime/app/pages/flows/index.vue.d.ts +0 -3
  28. package/dist/runtime/app/pages/queues/index.d.vue.ts +0 -3
  29. package/dist/runtime/app/pages/queues/index.vue +0 -236
  30. package/dist/runtime/app/pages/queues/index.vue.d.ts +0 -3
  31. package/dist/runtime/app/pages/queues/job.d.vue.ts +0 -3
  32. package/dist/runtime/app/pages/queues/job.vue +0 -261
  33. package/dist/runtime/app/pages/queues/job.vue.d.ts +0 -3
  34. package/dist/runtime/app/pages/queues/jobs.d.vue.ts +0 -3
  35. package/dist/runtime/app/pages/queues/jobs.vue +0 -595
  36. package/dist/runtime/app/pages/queues/jobs.vue.d.ts +0 -3
  37. package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +0 -3
  38. package/dist/runtime/app/pages/settings/scheduler.vue +0 -310
  39. package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +0 -3
  40. package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +0 -3
  41. package/dist/runtime/app/pages/triggers/[name]/edit.vue +0 -429
  42. package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +0 -3
  43. package/dist/runtime/app/pages/triggers/[name].d.vue.ts +0 -3
  44. package/dist/runtime/app/pages/triggers/[name].vue +0 -870
  45. package/dist/runtime/app/pages/triggers/[name].vue.d.ts +0 -3
  46. package/dist/runtime/app/pages/triggers/index.d.vue.ts +0 -3
  47. package/dist/runtime/app/pages/triggers/index.vue +0 -525
  48. package/dist/runtime/app/pages/triggers/index.vue.d.ts +0 -3
  49. package/dist/runtime/app/pages/triggers/new.d.vue.ts +0 -3
  50. package/dist/runtime/app/pages/triggers/new.vue +0 -610
  51. package/dist/runtime/app/pages/triggers/new.vue.d.ts +0 -3
  52. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
  53. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -49
  54. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +0 -2
  55. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +0 -21
  56. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.d.ts +0 -2
  57. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/restart.post.js +0 -21
  58. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -17
  59. package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -64
  60. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
  61. package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
  62. package/dist/runtime/server/api/_flows/index.get.d.ts +0 -7
  63. package/dist/runtime/server/api/_flows/index.get.js +0 -5
  64. package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +0 -15
  65. package/dist/runtime/server/api/_flows/recent-runs.get.js +0 -67
  66. package/dist/runtime/server/api/_flows/ws.d.ts +0 -80
  67. package/dist/runtime/server/api/_flows/ws.js +0 -309
  68. package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
  69. package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -14
  70. package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
  71. package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -39
  72. package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
  73. package/dist/runtime/server/api/_queues/index.get.js +0 -106
  74. package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
  75. package/dist/runtime/server/api/_queues/ws.js +0 -215
  76. package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +0 -19
  77. package/dist/runtime/server/api/_scheduler/jobs.get.js +0 -36
  78. package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +0 -6
  79. package/dist/runtime/server/api/_triggers/[name]/events.get.js +0 -43
  80. package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +0 -6
  81. package/dist/runtime/server/api/_triggers/[name]/index.get.js +0 -76
  82. package/dist/runtime/server/api/_triggers/[name].delete.d.ts +0 -7
  83. package/dist/runtime/server/api/_triggers/[name].delete.js +0 -37
  84. package/dist/runtime/server/api/_triggers/[name].patch.d.ts +0 -7
  85. package/dist/runtime/server/api/_triggers/[name].patch.js +0 -117
  86. package/dist/runtime/server/api/_triggers/index.get.d.ts +0 -6
  87. package/dist/runtime/server/api/_triggers/index.get.js +0 -44
  88. package/dist/runtime/server/api/_triggers/index.post.d.ts +0 -7
  89. package/dist/runtime/server/api/_triggers/index.post.js +0 -124
  90. package/dist/runtime/server/api/_triggers/stats.get.d.ts +0 -6
  91. package/dist/runtime/server/api/_triggers/stats.get.js +0 -41
  92. package/dist/runtime/server/api/_triggers/ws.d.ts +0 -74
  93. package/dist/runtime/server/api/_triggers/ws.js +0 -315
  94. /package/dist/runtime/app/pages/{flows/[name].d.vue.ts → workers.d.vue.ts} +0 -0
  95. /package/dist/runtime/app/pages/{flows/[name].vue.d.ts → workers.vue.d.ts} +0 -0
@@ -1,21 +0,0 @@
1
- import { defineEventHandler, getRouterParam, createError, useFlow } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const flowName = getRouterParam(event, "name");
4
- const runId = getRouterParam(event, "runId");
5
- if (!flowName || !runId) {
6
- throw createError({
7
- statusCode: 400,
8
- statusMessage: "Flow name and run ID are required"
9
- });
10
- }
11
- const flowEngine = useFlow();
12
- try {
13
- const result = await flowEngine.cancelFlow(flowName, runId);
14
- return result;
15
- } catch (error) {
16
- throw createError({
17
- statusCode: 500,
18
- statusMessage: `Failed to cancel flow: ${error.message}`
19
- });
20
- }
21
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,21 +0,0 @@
1
- import { defineEventHandler, getRouterParam, createError, useFlow } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const flowName = getRouterParam(event, "name");
4
- const runId = getRouterParam(event, "runId");
5
- if (!flowName || !runId) {
6
- throw createError({
7
- statusCode: 400,
8
- statusMessage: "Flow name and run ID are required"
9
- });
10
- }
11
- const flowEngine = useFlow();
12
- try {
13
- const result = await flowEngine.restartFlow(flowName, runId);
14
- return result;
15
- } catch (error) {
16
- throw createError({
17
- statusCode: 500,
18
- statusMessage: `Failed to restart flow: ${error.message}`
19
- });
20
- }
21
- });
@@ -1,17 +0,0 @@
1
- /**
2
- * GET /api/_flows/:flowName/runs
3
- *
4
- * Returns a list of flow runs with their metadata from the sorted set index.
5
- * Supports pagination via offset/limit query params.
6
- *
7
- * Query params:
8
- * - limit: number (default: 50)
9
- * - offset: number (default: 0)
10
- *
11
- * Returns:
12
- * {
13
- * runs: Array<{ id, score, metadata }>
14
- * }
15
- */
16
- declare const _default: any;
17
- export default _default;
@@ -1,64 +0,0 @@
1
- import { defineEventHandler, getRouterParam, getQuery, useStoreAdapter, useNventLogger, useStreamTopics } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const logger = useNventLogger("api-flows-runs");
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
- let store;
15
- let StoreSubjects;
16
- try {
17
- store = useStoreAdapter();
18
- const topics = useStreamTopics();
19
- StoreSubjects = topics.StoreSubjects;
20
- } catch (err) {
21
- logger.error("[flows/runs] Adapters not initialized yet:", { error: err });
22
- return {
23
- error: "Server initializing",
24
- message: "Please retry in a moment"
25
- };
26
- }
27
- try {
28
- const runIndexKey = StoreSubjects.flowRunIndex(flowName);
29
- let totalCount = 0;
30
- try {
31
- const allEntries = await store.index.read(runIndexKey, { limit: 1e4 });
32
- totalCount = allEntries.length;
33
- } catch {
34
- totalCount = 0;
35
- }
36
- const entries = await store.index.read(runIndexKey, { offset, limit });
37
- const filteredEntries = status ? entries.filter((e) => e.metadata?.status === status) : entries;
38
- const items = filteredEntries.map((entry) => ({
39
- id: entry.id,
40
- flowName,
41
- status: entry.metadata?.status || "unknown",
42
- createdAt: new Date(entry.score).toISOString(),
43
- startedAt: entry.metadata?.startedAt ? new Date(entry.metadata.startedAt).toISOString() : void 0,
44
- completedAt: entry.metadata?.completedAt ? new Date(entry.metadata.completedAt).toISOString() : void 0,
45
- stepCount: entry.metadata?.stepCount || 0,
46
- completedSteps: entry.metadata?.completedSteps || 0
47
- }));
48
- return {
49
- flowName,
50
- count: items.length,
51
- total: totalCount,
52
- offset,
53
- limit,
54
- hasMore: offset + items.length < totalCount,
55
- items
56
- };
57
- } catch (err) {
58
- logger.error("[flows/runs] error:", { error: err });
59
- return {
60
- error: "Failed to list runs",
61
- message: err instanceof Error ? err.message : String(err)
62
- };
63
- }
64
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,9 +0,0 @@
1
- import { defineEventHandler, getRouterParam, createError, readBody, useFlow } 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 } = useFlow();
6
- const body = await readBody(event);
7
- const result = await startFlow(flowName, body || {});
8
- return result;
9
- });
@@ -1,7 +0,0 @@
1
- /**
2
- * Returns pre-analyzed flows from the build-time registry.
3
- * Flows are analyzed during the build process for optimal performance.
4
- * Runtime statistics are provided via WebSocket (see ws.ts).
5
- */
6
- declare const _default: any;
7
- export default _default;
@@ -1,5 +0,0 @@
1
- import { defineEventHandler, $useAnalyzedFlows } from "#imports";
2
- export default defineEventHandler(() => {
3
- const analyzedFlows = $useAnalyzedFlows();
4
- return analyzedFlows || [];
5
- });
@@ -1,15 +0,0 @@
1
- /**
2
- * GET /api/_flows/recent-runs
3
- *
4
- * Returns a list of recent flow runs across all flows.
5
- *
6
- * Query params:
7
- * - limit: number (default: 10)
8
- *
9
- * Returns:
10
- * {
11
- * runs: Array<{ id, flowName, status, createdAt, ... }>
12
- * }
13
- */
14
- declare const _default: any;
15
- export default _default;
@@ -1,67 +0,0 @@
1
- import { defineEventHandler, getQuery, useStoreAdapter, useNventLogger, useStreamTopics, $useAnalyzedFlows } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const logger = useNventLogger("api-flows-recent-runs");
4
- const query = getQuery(event);
5
- const limit = Math.min(Number.parseInt(query.limit) || 10, 50);
6
- event.node.res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
7
- event.node.res.setHeader("Pragma", "no-cache");
8
- let store;
9
- let StoreSubjects;
10
- let flows;
11
- try {
12
- store = useStoreAdapter();
13
- const topics = useStreamTopics();
14
- StoreSubjects = topics.StoreSubjects;
15
- flows = $useAnalyzedFlows();
16
- } catch (err) {
17
- logger.error("[flows/recent-runs] Adapters not initialized yet:", { error: err });
18
- return {
19
- error: "Server initializing",
20
- message: "Please retry in a moment"
21
- };
22
- }
23
- try {
24
- const flowsList = flows || [];
25
- const allRuns = [];
26
- for (const flow of flowsList) {
27
- try {
28
- const flowName = flow.id || flow.name;
29
- const runIndexKey = StoreSubjects.flowRunIndex(flowName);
30
- const entries = await store.index.read(runIndexKey, { offset: 0, limit: 5 });
31
- const flowRuns = entries.map((entry) => ({
32
- id: entry.id,
33
- flowName,
34
- flowDisplayName: flow.displayName || flowName,
35
- status: entry.metadata?.status || "unknown",
36
- createdAt: entry.score,
37
- // timestamp
38
- startedAt: entry.metadata?.startedAt,
39
- completedAt: entry.metadata?.completedAt,
40
- stepCount: entry.metadata?.stepCount || 0,
41
- completedSteps: entry.metadata?.completedSteps || 0
42
- }));
43
- allRuns.push(...flowRuns);
44
- } catch (err) {
45
- const flowName = flow.id || flow.name;
46
- logger.debug(`No runs found for flow ${flowName}`, { error: err });
47
- }
48
- }
49
- allRuns.sort((a, b) => b.createdAt - a.createdAt);
50
- const recentRuns = allRuns.slice(0, limit);
51
- return {
52
- count: recentRuns.length,
53
- items: recentRuns.map((run) => ({
54
- ...run,
55
- createdAt: new Date(run.createdAt).toISOString(),
56
- startedAt: run.startedAt ? new Date(run.startedAt).toISOString() : void 0,
57
- completedAt: run.completedAt ? new Date(run.completedAt).toISOString() : void 0
58
- }))
59
- };
60
- } catch (err) {
61
- logger.error("[flows/recent-runs] error:", { error: err });
62
- return {
63
- error: "Failed to list recent runs",
64
- message: err instanceof Error ? err.message : String(err)
65
- };
66
- }
67
- });
@@ -1,80 +0,0 @@
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": "subscribe.stats"
20
- * }
21
- *
22
- * {
23
- * "type": "unsubscribe.stats"
24
- * }
25
- *
26
- * {
27
- * "type": "ping"
28
- * }
29
- *
30
- * Message format (server -> client):
31
- * {
32
- * "type": "event",
33
- * "flowName": "example",
34
- * "runId": "abc123",
35
- * "event": { v: 1, eventType: "...", record: {...} }
36
- * }
37
- *
38
- * {
39
- * "type": "history",
40
- * "flowName": "example",
41
- * "runId": "abc123",
42
- * "events": [ ...historicalEvents ]
43
- * }
44
- *
45
- * {
46
- * "type": "subscribed",
47
- * "flowName": "example",
48
- * "runId": "abc123"
49
- * }
50
- *
51
- * {
52
- * "type": "unsubscribed",
53
- * "flowName": "example",
54
- * "runId": "abc123"
55
- * }
56
- *
57
- * {
58
- * "type": "pong",
59
- * "timestamp": 1234567890
60
- * }
61
- *
62
- * {
63
- * "type": "flow.stats.initial",
64
- * "data": { id: "flowName", metadata: {...} },
65
- * "timestamp": 1234567890
66
- * }
67
- *
68
- * {
69
- * "type": "flow.stats.update",
70
- * "data": { id: "flowName", metadata: {...} },
71
- * "timestamp": 1234567890
72
- * }
73
- *
74
- * {
75
- * "type": "error",
76
- * "message": "error description"
77
- * }
78
- */
79
- declare const _default: any;
80
- export default _default;
@@ -1,309 +0,0 @@
1
- import {
2
- defineWebSocketHandler,
3
- usePeerManager,
4
- useNventLogger,
5
- useStreamAdapter,
6
- useStoreAdapter,
7
- useStreamTopics,
8
- useFlow
9
- } from "#imports";
10
- const peerContexts = /* @__PURE__ */ new WeakMap();
11
- function safeSend(peer, data) {
12
- try {
13
- peer.send(JSON.stringify(data));
14
- return true;
15
- } catch {
16
- return false;
17
- }
18
- }
19
- export default defineWebSocketHandler({
20
- async open(peer) {
21
- const logger = useNventLogger("api-flows-ws");
22
- logger.info("[ws] client connected:", { peerId: peer.id });
23
- const { registerWsPeer } = usePeerManager();
24
- registerWsPeer(peer);
25
- peerContexts.set(peer, {
26
- subscriptions: /* @__PURE__ */ new Map()
27
- });
28
- safeSend(peer, {
29
- type: "connected",
30
- timestamp: Date.now()
31
- });
32
- },
33
- async message(peer, message) {
34
- const logger = useNventLogger("api-flows-ws");
35
- const context = peerContexts.get(peer);
36
- if (!context) {
37
- logger.error("[ws] no context for peer:", { peerId: peer.id });
38
- return;
39
- }
40
- let data;
41
- try {
42
- data = JSON.parse(message.text());
43
- } catch {
44
- safeSend(peer, {
45
- type: "error",
46
- message: "Invalid JSON"
47
- });
48
- return;
49
- }
50
- const { type, flowName, runId } = data;
51
- if (type === "subscribe") {
52
- if (!flowName || !runId) {
53
- safeSend(peer, {
54
- type: "error",
55
- message: "Missing flowName or runId"
56
- });
57
- return;
58
- }
59
- let stream;
60
- let store;
61
- try {
62
- stream = useStreamAdapter();
63
- store = useStoreAdapter();
64
- } catch (err) {
65
- logger.error("[ws] Adapters not initialized yet:", { error: err });
66
- safeSend(peer, {
67
- type: "error",
68
- message: "Server initializing, please retry"
69
- });
70
- return;
71
- }
72
- const subscriptionKey = `flow:${flowName}:${runId}`;
73
- const existingUnsub = context.subscriptions.get(subscriptionKey);
74
- if (existingUnsub) {
75
- try {
76
- existingUnsub();
77
- } catch (err) {
78
- logger.error("[ws] error unsubscribing:", { error: err });
79
- }
80
- }
81
- const { StoreSubjects, StreamTopics } = useStreamTopics();
82
- const subject = StoreSubjects.flowRun(runId);
83
- const topic = StreamTopics.flowEvents(runId);
84
- const handle = await stream.subscribe(topic, async (message2) => {
85
- const event = message2.data?.event;
86
- if (!event) {
87
- logger.warn("[ws] Received message without event data:", message2);
88
- return;
89
- }
90
- safeSend(peer, {
91
- type: "event",
92
- flowName,
93
- runId,
94
- event: {
95
- v: 1,
96
- eventType: event.type,
97
- record: event
98
- }
99
- });
100
- });
101
- const unsub = async () => {
102
- try {
103
- await handle.unsubscribe();
104
- } catch (err) {
105
- logger.error("[ws] error in unsub:", { error: err });
106
- }
107
- };
108
- context.subscriptions.set(subscriptionKey, unsub);
109
- try {
110
- const historicalEvents = await store.stream.read(subject, {
111
- limit: 100,
112
- order: "asc"
113
- // forward order
114
- });
115
- safeSend(peer, {
116
- type: "history",
117
- flowName,
118
- runId,
119
- events: historicalEvents.map((e) => ({
120
- v: 1,
121
- eventType: e.kind || e.type,
122
- record: e
123
- }))
124
- });
125
- } catch (err) {
126
- logger.error("[ws] error sending history:", { error: err });
127
- safeSend(peer, {
128
- type: "error",
129
- message: "Failed to load history"
130
- });
131
- }
132
- safeSend(peer, {
133
- type: "subscribed",
134
- flowName,
135
- runId
136
- });
137
- } else if (type === "unsubscribe") {
138
- if (!flowName || !runId) {
139
- safeSend(peer, {
140
- type: "error",
141
- message: "Missing flowName or runId"
142
- });
143
- return;
144
- }
145
- const subscriptionKey = `flow:${flowName}:${runId}`;
146
- const unsub = context.subscriptions.get(subscriptionKey);
147
- if (unsub) {
148
- try {
149
- await unsub();
150
- context.subscriptions.delete(subscriptionKey);
151
- safeSend(peer, {
152
- type: "unsubscribed",
153
- flowName,
154
- runId
155
- });
156
- } catch (err) {
157
- logger.error("[ws] error unsubscribing:", { error: err });
158
- safeSend(peer, {
159
- type: "error",
160
- message: "Failed to unsubscribe"
161
- });
162
- }
163
- }
164
- } else if (type === "subscribe.stats") {
165
- const statsKey = "stats";
166
- const existingUnsub = context.subscriptions.get(statsKey);
167
- if (existingUnsub) {
168
- safeSend(peer, {
169
- type: "error",
170
- message: "Already subscribed to stats"
171
- });
172
- return;
173
- }
174
- try {
175
- const stream = useStreamAdapter();
176
- const { StreamTopics } = useStreamTopics();
177
- const topic = StreamTopics.flowStats();
178
- const handle = await stream.subscribe(topic, (message2) => {
179
- safeSend(peer, {
180
- type: "flow.stats.update",
181
- data: message2,
182
- timestamp: Date.now()
183
- });
184
- });
185
- const unsub = async () => {
186
- try {
187
- await handle.unsubscribe();
188
- } catch (err) {
189
- logger.error("[ws] error in stats unsub:", { error: err });
190
- }
191
- };
192
- context.subscriptions.set(statsKey, unsub);
193
- try {
194
- const flow = useFlow();
195
- const allFlowStats = await flow.getAllFlowStats();
196
- if (allFlowStats && allFlowStats.length > 0) {
197
- for (const flowStat of allFlowStats) {
198
- safeSend(peer, {
199
- type: "flow.stats.initial",
200
- data: {
201
- id: flowStat.name,
202
- metadata: {
203
- name: flowStat.name,
204
- displayName: flowStat.displayName,
205
- registeredAt: flowStat.registeredAt,
206
- lastRunAt: flowStat.lastRunAt,
207
- lastCompletedAt: flowStat.lastCompletedAt,
208
- stats: {
209
- total: flowStat.stats.total,
210
- success: flowStat.stats.success,
211
- failure: flowStat.stats.failure,
212
- cancel: flowStat.stats.cancel,
213
- running: flowStat.stats.running,
214
- awaiting: flowStat.stats.awaiting
215
- },
216
- version: flowStat.version
217
- }
218
- },
219
- timestamp: Date.now()
220
- });
221
- }
222
- }
223
- } catch (err) {
224
- logger.error("[ws] error fetching initial stats:", { error: err });
225
- }
226
- safeSend(peer, {
227
- type: "stats.subscribed",
228
- timestamp: Date.now()
229
- });
230
- } catch (err) {
231
- logger.error("[ws] error subscribing to stats:", { error: err });
232
- safeSend(peer, {
233
- type: "error",
234
- message: "Failed to subscribe to stats"
235
- });
236
- }
237
- } else if (type === "unsubscribe.stats") {
238
- const statsKey = "stats";
239
- const unsub = context.subscriptions.get(statsKey);
240
- if (unsub) {
241
- try {
242
- await unsub();
243
- context.subscriptions.delete(statsKey);
244
- safeSend(peer, {
245
- type: "stats.unsubscribed",
246
- timestamp: Date.now()
247
- });
248
- } catch (err) {
249
- logger.error("[ws] error unsubscribing from stats:", { error: err });
250
- safeSend(peer, {
251
- type: "error",
252
- message: "Failed to unsubscribe from stats"
253
- });
254
- }
255
- }
256
- } else if (type === "ping") {
257
- safeSend(peer, {
258
- type: "pong",
259
- timestamp: Date.now()
260
- });
261
- } else {
262
- safeSend(peer, {
263
- type: "error",
264
- message: `Unknown message type: ${type}`
265
- });
266
- }
267
- },
268
- async close(peer, event) {
269
- const logger = useNventLogger("api-flows-ws");
270
- const isNormalClosure = event?.code === 1e3 || event?.code === 1001;
271
- if (!isNormalClosure) {
272
- logger.info("[ws] client disconnected:", { peerId: peer.id, code: event?.code, reason: event?.reason });
273
- }
274
- const { unregisterWsPeer } = usePeerManager();
275
- unregisterWsPeer(peer);
276
- const context = peerContexts.get(peer);
277
- if (context) {
278
- for (const unsub of Array.from(context.subscriptions.values())) {
279
- try {
280
- await unsub();
281
- } catch (err) {
282
- if (!isNormalClosure) {
283
- logger.error("[ws] error unsubscribing on close:", { error: err });
284
- }
285
- }
286
- }
287
- context.subscriptions.clear();
288
- peerContexts.delete(peer);
289
- }
290
- },
291
- async error(peer, error) {
292
- const logger = useNventLogger("api-flows-ws");
293
- logger.error("[ws] error for peer:", { peerId: peer.id, error });
294
- const { unregisterWsPeer } = usePeerManager();
295
- unregisterWsPeer(peer);
296
- const context = peerContexts.get(peer);
297
- if (context) {
298
- for (const unsub of Array.from(context.subscriptions.values())) {
299
- try {
300
- await unsub();
301
- } catch (err) {
302
- logger.error("[ws] error unsubscribing on error:", { error: err });
303
- }
304
- }
305
- context.subscriptions.clear();
306
- peerContexts.delete(peer);
307
- }
308
- }
309
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,14 +0,0 @@
1
- import { defineEventHandler, getRouterParam, useQueueAdapter } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const name = getRouterParam(event, "name") || "";
4
- const id = getRouterParam(event, "id") || "";
5
- let queue;
6
- try {
7
- queue = useQueueAdapter();
8
- } catch {
9
- return null;
10
- }
11
- const job = await queue.getJob(name, id);
12
- if (!job) return null;
13
- return { ...job, queue: name };
14
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;