@nvent-addon/app 0.4.5 → 0.5.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 (153) hide show
  1. package/dist/module.d.mts +19 -1
  2. package/dist/module.mjs +20 -8
  3. package/dist/runtime/app/components/{nhealth/component-router.d.vue.ts → ComponentRouter.d.vue.ts} +1 -5
  4. package/dist/runtime/app/components/{nhealth/component-router.vue.d.ts → ComponentRouter.vue.d.ts} +1 -5
  5. package/dist/runtime/app/components/{nhealth/component-shell.d.vue.ts → ComponentShell.d.vue.ts} +4 -9
  6. package/dist/runtime/app/components/ComponentShell.vue +87 -0
  7. package/dist/runtime/app/components/{nhealth/component-shell.vue.d.ts → ComponentShell.vue.d.ts} +4 -9
  8. package/dist/runtime/app/components/ConfirmDialog.d.vue.ts +1 -6
  9. package/dist/runtime/app/components/ConfirmDialog.vue.d.ts +1 -6
  10. package/dist/runtime/app/components/ListItem.d.vue.ts +3 -6
  11. package/dist/runtime/app/components/ListItem.vue.d.ts +3 -6
  12. package/dist/runtime/app/components/LiveIndicator.d.vue.ts +7 -0
  13. package/dist/runtime/app/components/LiveIndicator.vue +30 -0
  14. package/dist/runtime/app/components/LiveIndicator.vue.d.ts +7 -0
  15. package/dist/runtime/app/components/{QueueConfigDetails.d.vue.ts → QueueConfiguration.d.vue.ts} +1 -10
  16. package/dist/runtime/app/components/QueueConfiguration.vue +387 -0
  17. package/dist/runtime/app/components/{QueueConfigDetails.vue.d.ts → QueueConfiguration.vue.d.ts} +1 -10
  18. package/dist/runtime/app/components/StatCard.d.vue.ts +9 -0
  19. package/dist/runtime/app/components/StatCard.vue +57 -0
  20. package/dist/runtime/app/components/StatCard.vue.d.ts +9 -0
  21. package/dist/runtime/app/components/TimelineList.vue +67 -0
  22. package/dist/runtime/app/components/flow/AwaitNode.d.vue.ts +18 -0
  23. package/dist/runtime/app/components/flow/AwaitNode.vue +91 -0
  24. package/dist/runtime/app/components/flow/AwaitNode.vue.d.ts +18 -0
  25. package/dist/runtime/app/components/{FlowDiagram.d.vue.ts → flow/Diagram.d.vue.ts} +12 -1
  26. package/dist/runtime/app/components/{FlowDiagram.vue → flow/Diagram.vue} +92 -11
  27. package/dist/runtime/app/components/{FlowDiagram.vue.d.ts → flow/Diagram.vue.d.ts} +12 -1
  28. package/dist/runtime/app/components/{FlowRunOverview.d.vue.ts → flow/RunOverview.d.vue.ts} +3 -0
  29. package/dist/runtime/app/components/{FlowRunOverview.vue → flow/RunOverview.vue} +94 -8
  30. package/dist/runtime/app/components/{FlowRunOverview.vue.d.ts → flow/RunOverview.vue.d.ts} +3 -0
  31. package/dist/runtime/app/components/{FlowRunStatusBadge.d.vue.ts → flow/RunStatusBadge.d.vue.ts} +2 -8
  32. package/dist/runtime/app/components/{FlowRunStatusBadge.vue → flow/RunStatusBadge.vue} +8 -1
  33. package/dist/runtime/app/components/{FlowRunStatusBadge.vue.d.ts → flow/RunStatusBadge.vue.d.ts} +2 -8
  34. package/dist/runtime/app/components/{FlowRunTimeline.vue → flow/RunTimeline.vue} +1 -1
  35. package/dist/runtime/app/components/{FlowStepSelector.d.vue.ts → flow/StepSelector.d.vue.ts} +1 -0
  36. package/dist/runtime/app/components/flow/StepSelector.vue +553 -0
  37. package/dist/runtime/app/components/{FlowStepSelector.vue.d.ts → flow/StepSelector.vue.d.ts} +1 -0
  38. package/dist/runtime/app/components/trigger/BasicInfoCard.d.vue.ts +33 -0
  39. package/dist/runtime/app/components/trigger/BasicInfoCard.vue +168 -0
  40. package/dist/runtime/app/components/trigger/BasicInfoCard.vue.d.ts +33 -0
  41. package/dist/runtime/app/components/{FlowSchedulesList.d.vue.ts → trigger/DangerZone.d.vue.ts} +4 -6
  42. package/dist/runtime/app/components/trigger/DangerZone.vue +46 -0
  43. package/dist/runtime/app/components/{FlowSchedulesList.vue.d.ts → trigger/DangerZone.vue.d.ts} +4 -6
  44. package/dist/runtime/app/components/trigger/EditHeader.d.vue.ts +15 -0
  45. package/dist/runtime/app/components/trigger/EditHeader.vue +55 -0
  46. package/dist/runtime/app/components/trigger/EditHeader.vue.d.ts +15 -0
  47. package/dist/runtime/app/components/trigger/EventConfig.d.vue.ts +24 -0
  48. package/dist/runtime/app/components/trigger/EventConfig.vue +68 -0
  49. package/dist/runtime/app/components/trigger/EventConfig.vue.d.ts +24 -0
  50. package/dist/runtime/app/components/trigger/FlowSubscriptions.d.vue.ts +14 -0
  51. package/dist/runtime/app/components/trigger/FlowSubscriptions.vue +128 -0
  52. package/dist/runtime/app/components/trigger/FlowSubscriptions.vue.d.ts +14 -0
  53. package/dist/runtime/app/components/trigger/ScheduleConfig.d.vue.ts +27 -0
  54. package/dist/runtime/app/components/trigger/ScheduleConfig.vue +375 -0
  55. package/dist/runtime/app/components/trigger/ScheduleConfig.vue.d.ts +27 -0
  56. package/dist/runtime/app/components/{FlowScheduleDialog.d.vue.ts → trigger/StatusConfig.d.vue.ts} +6 -6
  57. package/dist/runtime/app/components/trigger/StatusConfig.vue +78 -0
  58. package/dist/runtime/app/components/{FlowScheduleDialog.vue.d.ts → trigger/StatusConfig.vue.d.ts} +6 -6
  59. package/dist/runtime/app/components/trigger/WebhookConfig.d.vue.ts +30 -0
  60. package/dist/runtime/app/components/trigger/WebhookConfig.vue +97 -0
  61. package/dist/runtime/app/components/trigger/WebhookConfig.vue.d.ts +30 -0
  62. package/dist/runtime/app/composables/useAnalyzedFlows.d.ts +5 -0
  63. package/dist/runtime/app/composables/useAnalyzedFlows.js +15 -1
  64. package/dist/runtime/app/composables/useComponentRouter.d.ts +8 -0
  65. package/dist/runtime/app/composables/useComponentRouter.js +10 -2
  66. package/dist/runtime/app/composables/useFlowRunsInfinite.d.ts +1 -1
  67. package/dist/runtime/app/composables/useFlowState.js +65 -0
  68. package/dist/runtime/app/composables/useFlowWebSocket.d.ts +11 -2
  69. package/dist/runtime/app/composables/useFlowWebSocket.js +181 -65
  70. package/dist/runtime/app/composables/useQueueJobs.d.ts +12 -1
  71. package/dist/runtime/app/composables/useQueueJobs.js +13 -7
  72. package/dist/runtime/app/composables/useTrigger.d.ts +137 -0
  73. package/dist/runtime/app/composables/useTrigger.js +116 -0
  74. package/dist/runtime/app/composables/useTriggerWebSocket.d.ts +35 -0
  75. package/dist/runtime/app/composables/useTriggerWebSocket.js +333 -0
  76. package/dist/runtime/app/pages/dashboard.d.vue.ts +3 -0
  77. package/dist/runtime/app/pages/dashboard.vue +738 -0
  78. package/dist/runtime/app/pages/dashboard.vue.d.ts +3 -0
  79. package/dist/runtime/app/pages/flows/[name].d.vue.ts +3 -0
  80. package/dist/runtime/app/pages/flows/[name].vue +680 -0
  81. package/dist/runtime/app/pages/flows/[name].vue.d.ts +3 -0
  82. package/dist/runtime/app/pages/flows/index.vue +321 -620
  83. package/dist/runtime/app/pages/index.vue +39 -9
  84. package/dist/runtime/app/pages/queues/index.vue +202 -194
  85. package/dist/runtime/app/pages/queues/jobs.vue +534 -207
  86. package/dist/runtime/app/pages/settings/scheduler.d.vue.ts +3 -0
  87. package/dist/runtime/app/pages/settings/scheduler.vue +310 -0
  88. package/dist/runtime/app/pages/settings/scheduler.vue.d.ts +3 -0
  89. package/dist/runtime/app/pages/triggers/[name]/edit.d.vue.ts +3 -0
  90. package/dist/runtime/app/pages/triggers/[name]/edit.vue +429 -0
  91. package/dist/runtime/app/pages/triggers/[name]/edit.vue.d.ts +3 -0
  92. package/dist/runtime/app/pages/triggers/[name].d.vue.ts +3 -0
  93. package/dist/runtime/app/pages/triggers/[name].vue +898 -0
  94. package/dist/runtime/app/pages/triggers/[name].vue.d.ts +3 -0
  95. package/dist/runtime/app/pages/triggers/index.d.vue.ts +3 -0
  96. package/dist/runtime/app/pages/triggers/index.vue +528 -0
  97. package/dist/runtime/app/pages/triggers/index.vue.d.ts +3 -0
  98. package/dist/runtime/app/pages/triggers/new.d.vue.ts +3 -0
  99. package/dist/runtime/app/pages/triggers/new.vue +610 -0
  100. package/dist/runtime/app/pages/triggers/new.vue.d.ts +3 -0
  101. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +10 -0
  102. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +49 -0
  103. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +2 -0
  104. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +21 -0
  105. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +17 -0
  106. package/dist/runtime/server/api/_flows/[name]/runs.get.js +64 -0
  107. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +2 -0
  108. package/dist/runtime/server/api/_flows/[name]/start.post.js +9 -0
  109. package/dist/runtime/server/api/_flows/index.get.d.ts +7 -0
  110. package/dist/runtime/server/api/_flows/index.get.js +5 -0
  111. package/dist/runtime/server/api/_flows/recent-runs.get.d.ts +15 -0
  112. package/dist/runtime/server/api/_flows/recent-runs.get.js +67 -0
  113. package/dist/runtime/server/api/_flows/ws.d.ts +80 -0
  114. package/dist/runtime/server/api/_flows/ws.js +309 -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 +14 -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 +39 -0
  119. package/dist/runtime/server/api/_queues/index.get.d.ts +2 -0
  120. package/dist/runtime/server/api/_queues/index.get.js +106 -0
  121. package/dist/runtime/server/api/_queues/ws.d.ts +48 -0
  122. package/dist/runtime/server/api/_queues/ws.js +215 -0
  123. package/dist/runtime/server/api/_scheduler/jobs.get.d.ts +19 -0
  124. package/dist/runtime/server/api/_scheduler/jobs.get.js +36 -0
  125. package/dist/runtime/server/api/_triggers/[name]/events.get.d.ts +6 -0
  126. package/dist/runtime/server/api/_triggers/[name]/events.get.js +43 -0
  127. package/dist/runtime/server/api/_triggers/[name]/index.get.d.ts +6 -0
  128. package/dist/runtime/server/api/_triggers/[name]/index.get.js +76 -0
  129. package/dist/runtime/server/api/_triggers/[name].delete.d.ts +7 -0
  130. package/dist/runtime/server/api/_triggers/[name].delete.js +37 -0
  131. package/dist/runtime/server/api/_triggers/[name].patch.d.ts +7 -0
  132. package/dist/runtime/server/api/_triggers/[name].patch.js +117 -0
  133. package/dist/runtime/server/api/_triggers/index.get.d.ts +6 -0
  134. package/dist/runtime/server/api/_triggers/index.get.js +44 -0
  135. package/dist/runtime/server/api/_triggers/index.post.d.ts +7 -0
  136. package/dist/runtime/server/api/_triggers/index.post.js +124 -0
  137. package/dist/runtime/server/api/_triggers/stats.get.d.ts +6 -0
  138. package/dist/runtime/server/api/_triggers/stats.get.js +41 -0
  139. package/dist/runtime/server/api/_triggers/ws.d.ts +74 -0
  140. package/dist/runtime/server/api/_triggers/ws.js +315 -0
  141. package/dist/runtime/server/tsconfig.json +7 -0
  142. package/package.json +8 -8
  143. package/dist/runtime/app/components/FlowScheduleDialog.vue +0 -226
  144. package/dist/runtime/app/components/FlowSchedulesList.vue +0 -99
  145. package/dist/runtime/app/components/FlowStepSelector.vue +0 -238
  146. package/dist/runtime/app/components/QueueConfigDetails.vue +0 -412
  147. package/dist/runtime/app/components/nhealth/component-shell.vue +0 -89
  148. /package/dist/runtime/app/components/{nhealth/component-router.vue → ComponentRouter.vue} +0 -0
  149. /package/dist/runtime/app/components/{FlowNodeCard.d.vue.ts → flow/NodeCard.d.vue.ts} +0 -0
  150. /package/dist/runtime/app/components/{FlowNodeCard.vue → flow/NodeCard.vue} +0 -0
  151. /package/dist/runtime/app/components/{FlowNodeCard.vue.d.ts → flow/NodeCard.vue.d.ts} +0 -0
  152. /package/dist/runtime/app/components/{FlowRunTimeline.d.vue.ts → flow/RunTimeline.d.vue.ts} +0 -0
  153. /package/dist/runtime/app/components/{FlowRunTimeline.vue.d.ts → flow/RunTimeline.vue.d.ts} +0 -0
@@ -0,0 +1,137 @@
1
+ import { type Ref } from '#imports';
2
+ import type { FetchError } from 'ofetch';
3
+ export interface TriggerStats {
4
+ totalFires: number;
5
+ totalFlowsStarted: number;
6
+ activeSubscribers: number;
7
+ lastFiredAt?: string;
8
+ }
9
+ export interface TriggerInfo {
10
+ name: string;
11
+ type: 'event' | 'webhook' | 'schedule' | 'manual';
12
+ scope: 'flow' | 'run';
13
+ displayName?: string;
14
+ description?: string;
15
+ source?: string;
16
+ status: 'active' | 'inactive' | 'retired';
17
+ registeredAt?: number;
18
+ lastActivityAt?: number;
19
+ webhook?: {
20
+ path: string;
21
+ method?: string;
22
+ auth?: any;
23
+ };
24
+ schedule?: {
25
+ cron: string;
26
+ timezone?: string;
27
+ enabled?: boolean;
28
+ };
29
+ config?: any;
30
+ subscribedFlows: string[];
31
+ subscriptionCount: number;
32
+ stats: TriggerStats;
33
+ }
34
+ export interface TriggerDetail {
35
+ name: string;
36
+ type: 'event' | 'webhook' | 'schedule' | 'manual';
37
+ scope: 'flow' | 'run';
38
+ displayName?: string;
39
+ description?: string;
40
+ source?: string;
41
+ status: 'active' | 'inactive' | 'retired';
42
+ registeredAt?: number;
43
+ registeredBy?: string;
44
+ lastActivityAt?: number;
45
+ webhook?: {
46
+ path: string;
47
+ method?: string;
48
+ auth?: any;
49
+ };
50
+ schedule?: {
51
+ cron: string;
52
+ timezone?: string;
53
+ enabled?: boolean;
54
+ };
55
+ config?: any;
56
+ version?: number;
57
+ subscribedFlows: string[];
58
+ subscriptions: Array<{
59
+ triggerName: string;
60
+ flowName: string;
61
+ mode: 'auto' | 'manual';
62
+ source: string;
63
+ registeredAt?: number;
64
+ }>;
65
+ subscriptionCount: number;
66
+ stats: TriggerStats;
67
+ }
68
+ export interface TriggerStatsOverview {
69
+ total: number;
70
+ active: number;
71
+ inactive: number;
72
+ retired: number;
73
+ byType: Record<string, number>;
74
+ byScope: Record<string, number>;
75
+ byStatus: Record<string, number>;
76
+ totalSubscriptions: number;
77
+ totalFires: number;
78
+ withSubscribers: number;
79
+ }
80
+ export interface TriggerEvent {
81
+ type: string;
82
+ timestamp: number;
83
+ data: any;
84
+ triggerName?: string;
85
+ [key: string]: any;
86
+ }
87
+ export interface TriggerEventsResponse {
88
+ triggerName: string;
89
+ events: TriggerEvent[];
90
+ count: number;
91
+ total: number;
92
+ hasMore: boolean;
93
+ }
94
+ /**
95
+ * Composable for fetching trigger detail
96
+ */
97
+ export declare function useTrigger(name: Ref<string | null>): {
98
+ trigger: Ref<TriggerDetail | null | undefined>;
99
+ refresh: () => Promise<void>;
100
+ status: Ref<'idle' | 'pending' | 'success' | 'error'>;
101
+ error: Ref<FetchError | null | undefined>;
102
+ };
103
+ /**
104
+ * Composable for fetching trigger events
105
+ */
106
+ export declare function useTriggerEvents(name: Ref<string | null>, options?: Ref<{
107
+ limit?: number;
108
+ offset?: number;
109
+ types?: string[];
110
+ }> | {
111
+ limit?: number;
112
+ offset?: number;
113
+ types?: string[];
114
+ }): {
115
+ events: Ref<TriggerEventsResponse | null | undefined>;
116
+ refresh: () => Promise<void>;
117
+ status: Ref<'idle' | 'pending' | 'success' | 'error'>;
118
+ error: Ref<FetchError | null | undefined>;
119
+ };
120
+ /**
121
+ * Composable for fetching trigger list
122
+ */
123
+ export declare function useTriggers(): {
124
+ triggers: Ref<TriggerInfo[] | null | undefined>;
125
+ refresh: () => Promise<void>;
126
+ status: Ref<'idle' | 'pending' | 'success' | 'error'>;
127
+ error: Ref<FetchError | null | undefined>;
128
+ };
129
+ /**
130
+ * Composable for fetching aggregate trigger statistics
131
+ */
132
+ export declare function useTriggersStats(): {
133
+ stats: Ref<TriggerStatsOverview | null | undefined>;
134
+ refresh: () => Promise<void>;
135
+ status: Ref<'idle' | 'pending' | 'success' | 'error'>;
136
+ error: Ref<FetchError | null | undefined>;
137
+ };
@@ -0,0 +1,116 @@
1
+ import { ref, useFetch, isRef } from "#imports";
2
+ export function useTrigger(name) {
3
+ const refreshCounter = ref(0);
4
+ const { data: trigger, refresh: _refresh, status, error } = useFetch(
5
+ () => {
6
+ if (!name.value) return "/api/_triggers/__invalid__";
7
+ return `/api/_triggers/${encodeURIComponent(name.value)}?_t=${refreshCounter.value}`;
8
+ },
9
+ {
10
+ immediate: false,
11
+ watch: false,
12
+ server: false
13
+ // Client-only
14
+ }
15
+ );
16
+ const refresh = async () => {
17
+ if (!name.value) return;
18
+ refreshCounter.value++;
19
+ await _refresh();
20
+ };
21
+ if (import.meta.client && name.value) {
22
+ refresh();
23
+ }
24
+ return {
25
+ trigger,
26
+ refresh,
27
+ status,
28
+ error
29
+ };
30
+ }
31
+ export function useTriggerEvents(name, options) {
32
+ const refreshCounter = ref(0);
33
+ const opts = isRef(options) ? options : ref(options || {});
34
+ const buildUrl = () => {
35
+ if (!name.value) return "/api/_triggers/null/events";
36
+ const params = new URLSearchParams();
37
+ params.append("_t", refreshCounter.value.toString());
38
+ if (opts.value.limit) params.append("limit", opts.value.limit.toString());
39
+ if (opts.value.offset) params.append("offset", opts.value.offset.toString());
40
+ if (opts.value.types) params.append("types", opts.value.types.join(","));
41
+ return `/api/_triggers/${encodeURIComponent(name.value)}/events?${params.toString()}`;
42
+ };
43
+ const { data: events, refresh: _refresh, status, error } = useFetch(
44
+ buildUrl,
45
+ {
46
+ immediate: false,
47
+ watch: false,
48
+ server: false
49
+ // Client-only
50
+ }
51
+ );
52
+ const refresh = async () => {
53
+ if (!name.value) return;
54
+ refreshCounter.value++;
55
+ await _refresh();
56
+ };
57
+ if (import.meta.client && name.value) {
58
+ refresh();
59
+ }
60
+ return {
61
+ events,
62
+ refresh,
63
+ status,
64
+ error
65
+ };
66
+ }
67
+ export function useTriggers() {
68
+ const refreshCounter = ref(0);
69
+ const { data: triggers, refresh: _refresh, status, error } = useFetch(
70
+ () => `/api/_triggers?_t=${refreshCounter.value}`,
71
+ {
72
+ immediate: false,
73
+ watch: false,
74
+ server: false
75
+ // Client-only
76
+ }
77
+ );
78
+ const refresh = async () => {
79
+ refreshCounter.value++;
80
+ await _refresh();
81
+ };
82
+ if (import.meta.client) {
83
+ refresh();
84
+ }
85
+ return {
86
+ triggers,
87
+ refresh,
88
+ status,
89
+ error
90
+ };
91
+ }
92
+ export function useTriggersStats() {
93
+ const refreshCounter = ref(0);
94
+ const { data: stats, refresh: _refresh, status, error } = useFetch(
95
+ () => `/api/_triggers/stats?_t=${refreshCounter.value}`,
96
+ {
97
+ immediate: false,
98
+ watch: false,
99
+ server: false
100
+ // Client-only
101
+ }
102
+ );
103
+ const refresh = async () => {
104
+ refreshCounter.value++;
105
+ await _refresh();
106
+ };
107
+ if (import.meta.client) {
108
+ refresh();
109
+ }
110
+ return {
111
+ stats,
112
+ refresh,
113
+ status,
114
+ error
115
+ };
116
+ }
@@ -0,0 +1,35 @@
1
+ export interface UseTriggerWebSocketOptions {
2
+ autoReconnect?: boolean;
3
+ maxRetries?: number;
4
+ baseDelayMs?: number;
5
+ maxDelayMs?: number;
6
+ onOpen?: () => void;
7
+ onError?: (err?: any) => void;
8
+ onClose?: (event?: CloseEvent) => void;
9
+ }
10
+ export interface TriggerSubscription {
11
+ triggerName: string;
12
+ onEvent: (event: any) => void;
13
+ onHistory?: (events: any[]) => void;
14
+ }
15
+ export interface TriggerStatsSubscription {
16
+ onInitial?: (data: any) => void;
17
+ onUpdate?: (data: any) => void;
18
+ }
19
+ /**
20
+ * WebSocket composable for trigger events and trigger stats
21
+ * Architecture: Client (this) → WebSocket → Server Handler → StreamAdapter.subscribe(StreamTopics.triggerEvents)
22
+ * Supports subscribing to specific triggers and global trigger statistics
23
+ * Uses a singleton connection shared across all instances
24
+ */
25
+ export declare function useTriggerWebSocket(): {
26
+ subscribe: (subscription: TriggerSubscription, opts?: UseTriggerWebSocketOptions) => void;
27
+ unsubscribe: () => void;
28
+ subscribeStats: (subscription: TriggerStatsSubscription, opts?: UseTriggerWebSocketOptions) => void;
29
+ unsubscribeStats: () => void;
30
+ stop: () => void;
31
+ forceClose: () => void;
32
+ connected: import("vue").Ref<boolean, boolean>;
33
+ reconnecting: import("vue").Ref<boolean, boolean>;
34
+ };
35
+ export default useTriggerWebSocket;
@@ -0,0 +1,333 @@
1
+ import { ref, onBeforeUnmount } from "#imports";
2
+ let sharedWs = null;
3
+ let sharedConnected = false;
4
+ let sharedReconnecting = false;
5
+ let retry = 0;
6
+ let reconnectTimer = null;
7
+ let currentOptions;
8
+ let currentSubscription = null;
9
+ let currentStatsSubscription = null;
10
+ let pendingStatsSubscription = false;
11
+ let isStatsSubscribed = false;
12
+ let statsCache = [];
13
+ let pingInterval = null;
14
+ let isServerRestarting = false;
15
+ let refCount = 0;
16
+ export function useTriggerWebSocket() {
17
+ const ws = ref(sharedWs);
18
+ const connected = ref(sharedConnected);
19
+ const reconnecting = ref(sharedReconnecting);
20
+ refCount++;
21
+ const computeDelay = (opts) => {
22
+ const base = Math.max(100, opts?.baseDelayMs ?? 1e3);
23
+ const max = Math.max(base, opts?.maxDelayMs ?? 1e4);
24
+ const exp = Math.min(max, base * Math.pow(2, retry));
25
+ const jitter = Math.floor(Math.random() * Math.min(1e3, exp / 4));
26
+ return exp + jitter;
27
+ };
28
+ const clearTimers = () => {
29
+ if (reconnectTimer) {
30
+ try {
31
+ clearTimeout(reconnectTimer);
32
+ } catch {
33
+ }
34
+ reconnectTimer = null;
35
+ }
36
+ if (pingInterval) {
37
+ try {
38
+ clearInterval(pingInterval);
39
+ } catch {
40
+ }
41
+ pingInterval = null;
42
+ }
43
+ };
44
+ const updateRefs = () => {
45
+ ws.value = sharedWs;
46
+ connected.value = sharedConnected;
47
+ reconnecting.value = sharedReconnecting;
48
+ };
49
+ const send = (data) => {
50
+ if (sharedWs && sharedWs.readyState === WebSocket.OPEN) {
51
+ try {
52
+ sharedWs.send(JSON.stringify(data));
53
+ return true;
54
+ } catch (err) {
55
+ console.error("[useTriggerWebSocket] Error sending message:", err);
56
+ return false;
57
+ }
58
+ }
59
+ return false;
60
+ };
61
+ const startPingInterval = () => {
62
+ clearTimers();
63
+ pingInterval = setInterval(() => {
64
+ if (sharedWs && sharedWs.readyState === WebSocket.OPEN) {
65
+ send({ type: "ping" });
66
+ }
67
+ }, 3e4);
68
+ };
69
+ const stop = () => {
70
+ refCount = Math.max(0, refCount - 1);
71
+ };
72
+ const forceClose = () => {
73
+ clearTimers();
74
+ isServerRestarting = false;
75
+ try {
76
+ if (sharedWs) {
77
+ sharedWs.close(1e3, "Client closing");
78
+ }
79
+ } catch (err) {
80
+ console.warn("[useTriggerWebSocket] Error closing WebSocket:", err);
81
+ }
82
+ sharedWs = null;
83
+ sharedConnected = false;
84
+ sharedReconnecting = false;
85
+ updateRefs();
86
+ retry = 0;
87
+ refCount = 0;
88
+ currentSubscription = null;
89
+ currentStatsSubscription = null;
90
+ isStatsSubscribed = false;
91
+ pendingStatsSubscription = false;
92
+ statsCache = [];
93
+ };
94
+ const attemptReconnect = () => {
95
+ if (!currentOptions?.autoReconnect) {
96
+ stop();
97
+ return;
98
+ }
99
+ const max = Math.max(0, currentOptions?.maxRetries ?? 10);
100
+ if (retry >= max) {
101
+ console.error("[useTriggerWebSocket] Max retries reached");
102
+ stop();
103
+ return;
104
+ }
105
+ retry++;
106
+ sharedReconnecting = true;
107
+ updateRefs();
108
+ const baseDelay = isServerRestarting ? 2e3 : computeDelay(currentOptions);
109
+ const delay = baseDelay;
110
+ clearTimers();
111
+ reconnectTimer = setTimeout(() => {
112
+ if (currentSubscription || currentStatsSubscription) {
113
+ connect(currentOptions);
114
+ }
115
+ }, delay);
116
+ };
117
+ const setupWebSocket = (socket, opts) => {
118
+ socket.onopen = () => {
119
+ console.log("[useTriggerWebSocket] Connected");
120
+ sharedConnected = true;
121
+ sharedReconnecting = false;
122
+ updateRefs();
123
+ retry = 0;
124
+ startPingInterval();
125
+ if (currentSubscription) {
126
+ send({
127
+ type: "subscribe",
128
+ triggerName: currentSubscription.triggerName
129
+ });
130
+ }
131
+ if (currentStatsSubscription || pendingStatsSubscription) {
132
+ send({
133
+ type: "subscribe.stats"
134
+ });
135
+ pendingStatsSubscription = false;
136
+ }
137
+ opts?.onOpen?.();
138
+ };
139
+ socket.onmessage = (event) => {
140
+ try {
141
+ const data = JSON.parse(event.data);
142
+ switch (data.type) {
143
+ case "connected":
144
+ break;
145
+ case "subscribed":
146
+ break;
147
+ case "unsubscribed":
148
+ break;
149
+ case "stats.subscribed":
150
+ isStatsSubscribed = true;
151
+ break;
152
+ case "stats.unsubscribed":
153
+ isStatsSubscribed = false;
154
+ break;
155
+ case "trigger.stats.initial": {
156
+ const existingIndex = statsCache.findIndex((s) => s.id === data.data.id);
157
+ if (existingIndex >= 0) {
158
+ statsCache[existingIndex] = data.data;
159
+ } else {
160
+ statsCache.push(data.data);
161
+ }
162
+ if (currentStatsSubscription?.onInitial) {
163
+ currentStatsSubscription.onInitial(data.data);
164
+ } else {
165
+ console.warn("[useTriggerWebSocket] No onInitial handler for stats:", data.data);
166
+ }
167
+ break;
168
+ }
169
+ case "trigger.stats.update": {
170
+ const cacheIndex = statsCache.findIndex((s) => s.id === data.data.id);
171
+ if (cacheIndex >= 0) {
172
+ statsCache[cacheIndex] = data.data;
173
+ } else {
174
+ statsCache.push(data.data);
175
+ }
176
+ if (currentStatsSubscription?.onUpdate) {
177
+ currentStatsSubscription.onUpdate(data.data);
178
+ } else {
179
+ console.warn("[useTriggerWebSocket] No onUpdate handler for stats:", data.data);
180
+ }
181
+ break;
182
+ }
183
+ case "history":
184
+ if (currentSubscription) {
185
+ if (currentSubscription.onHistory) {
186
+ currentSubscription.onHistory(data.events);
187
+ } else {
188
+ for (const eventData of data.events) {
189
+ currentSubscription.onEvent(eventData);
190
+ }
191
+ }
192
+ }
193
+ break;
194
+ case "event":
195
+ if (currentSubscription) {
196
+ currentSubscription.onEvent(data.event);
197
+ }
198
+ break;
199
+ case "pong":
200
+ break;
201
+ case "server-restart":
202
+ isServerRestarting = true;
203
+ break;
204
+ case "error":
205
+ console.error("[useTriggerWebSocket] Server error:", data.message);
206
+ opts?.onError?.(new Error(data.message));
207
+ break;
208
+ default:
209
+ console.warn("[useTriggerWebSocket] Unknown message type:", data.type);
210
+ }
211
+ } catch (err) {
212
+ console.error("[useTriggerWebSocket] Error parsing message:", err);
213
+ }
214
+ };
215
+ socket.onerror = (err) => {
216
+ console.error("[useTriggerWebSocket] WebSocket error:", err);
217
+ opts?.onError?.(err);
218
+ };
219
+ socket.onclose = (event) => {
220
+ console.log("[useTriggerWebSocket] Connection closed:", event.code, event.reason);
221
+ sharedConnected = false;
222
+ updateRefs();
223
+ clearTimers();
224
+ opts?.onClose?.(event);
225
+ const shouldReconnect = event.code !== 1e3 && opts?.autoReconnect;
226
+ if (shouldReconnect) {
227
+ attemptReconnect();
228
+ } else {
229
+ isServerRestarting = false;
230
+ }
231
+ };
232
+ };
233
+ const connect = (opts) => {
234
+ if (import.meta.server || typeof WebSocket === "undefined") {
235
+ console.warn("[useTriggerWebSocket] WebSocket not available (SSR context)");
236
+ return;
237
+ }
238
+ if (sharedWs && (sharedWs.readyState === WebSocket.OPEN || sharedWs.readyState === WebSocket.CONNECTING)) {
239
+ return;
240
+ }
241
+ if (sharedWs) {
242
+ try {
243
+ sharedWs.close();
244
+ } catch {
245
+ }
246
+ }
247
+ currentOptions = opts;
248
+ try {
249
+ const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
250
+ const wsUrl = `${protocol}//${window.location.host}/api/_triggers/ws`;
251
+ const socket = new WebSocket(wsUrl);
252
+ sharedWs = socket;
253
+ updateRefs();
254
+ setupWebSocket(socket, opts);
255
+ } catch (err) {
256
+ console.error("[useTriggerWebSocket] Error creating WebSocket:", err);
257
+ opts?.onError?.(err);
258
+ attemptReconnect();
259
+ }
260
+ };
261
+ const subscribe = (subscription, opts) => {
262
+ if (currentSubscription && sharedWs && sharedWs.readyState === WebSocket.OPEN) {
263
+ send({
264
+ type: "unsubscribe",
265
+ triggerName: currentSubscription.triggerName
266
+ });
267
+ }
268
+ currentSubscription = subscription;
269
+ if (sharedWs && sharedWs.readyState === WebSocket.OPEN) {
270
+ send({
271
+ type: "subscribe",
272
+ triggerName: subscription.triggerName
273
+ });
274
+ return;
275
+ }
276
+ connect(opts);
277
+ };
278
+ const unsubscribe = () => {
279
+ if (currentSubscription && sharedWs && sharedWs.readyState === WebSocket.OPEN) {
280
+ send({
281
+ type: "unsubscribe",
282
+ triggerName: currentSubscription.triggerName
283
+ });
284
+ }
285
+ currentSubscription = null;
286
+ };
287
+ const subscribeStats = (subscription, opts) => {
288
+ currentStatsSubscription = subscription;
289
+ if (sharedWs && sharedWs.readyState === WebSocket.OPEN) {
290
+ if (isStatsSubscribed) {
291
+ if (subscription.onInitial && statsCache.length > 0) {
292
+ for (const cachedStat of statsCache) {
293
+ subscription.onInitial(cachedStat);
294
+ }
295
+ }
296
+ return;
297
+ }
298
+ send({
299
+ type: "subscribe.stats"
300
+ });
301
+ return;
302
+ }
303
+ if (sharedWs && sharedWs.readyState === WebSocket.CONNECTING) {
304
+ pendingStatsSubscription = true;
305
+ return;
306
+ }
307
+ pendingStatsSubscription = true;
308
+ connect(opts);
309
+ };
310
+ const unsubscribeStats = () => {
311
+ if (currentStatsSubscription && sharedWs && sharedWs.readyState === WebSocket.OPEN) {
312
+ send({
313
+ type: "unsubscribe.stats"
314
+ });
315
+ }
316
+ currentStatsSubscription = null;
317
+ isStatsSubscribed = false;
318
+ };
319
+ onBeforeUnmount(() => {
320
+ stop();
321
+ });
322
+ return {
323
+ subscribe,
324
+ unsubscribe,
325
+ subscribeStats,
326
+ unsubscribeStats,
327
+ stop,
328
+ forceClose,
329
+ connected,
330
+ reconnecting
331
+ };
332
+ }
333
+ export default useTriggerWebSocket;
@@ -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;