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,54 @@
1
+ import { useRuntimeConfig } from "#imports";
2
+ import { consola } from "consola";
3
+ const LOG_LEVELS = {
4
+ debug: 0,
5
+ info: 1,
6
+ warn: 2,
7
+ error: 3
8
+ };
9
+ const loggerCache = /* @__PURE__ */ new Map();
10
+ export function useServerLogger(scope) {
11
+ const rc = useRuntimeConfig();
12
+ const debugConfig = rc?.queue?.debug;
13
+ const configLevel = debugConfig?.level || process.env.NQ_DEBUG_LEVEL || "info";
14
+ const globalLevelNum = configLevel === "silent" ? Infinity : LOG_LEVELS[configLevel] ?? LOG_LEVELS.info;
15
+ const scopeKey = scope.replace(/[^a-z0-9]/gi, "_").toLowerCase();
16
+ const envKey = `NQ_DEBUG_${scopeKey.toUpperCase()}`;
17
+ const isScopeDebugEnabled = debugConfig?.[scopeKey] === true || process.env[envKey] === "1";
18
+ let scopedConsola = loggerCache.get(scope);
19
+ if (!scopedConsola) {
20
+ scopedConsola = consola.withTag(scope);
21
+ loggerCache.set(scope, scopedConsola);
22
+ }
23
+ const logger = scopedConsola;
24
+ function isEnabled(level) {
25
+ const levelNum = LOG_LEVELS[level];
26
+ if (isScopeDebugEnabled && level === "debug") {
27
+ return true;
28
+ }
29
+ return levelNum >= globalLevelNum;
30
+ }
31
+ function log(level, message, context) {
32
+ if (!isEnabled(level)) return;
33
+ if (context && Object.keys(context).length > 0) {
34
+ logger[level](message, context);
35
+ } else {
36
+ logger[level](message);
37
+ }
38
+ }
39
+ return {
40
+ debug: (message, context) => log("debug", message, context),
41
+ info: (message, context) => log("info", message, context),
42
+ warn: (message, context) => log("warn", message, context),
43
+ error: (message, context) => log("error", message, context),
44
+ log,
45
+ isEnabled,
46
+ consola: logger
47
+ };
48
+ }
49
+ export function isDebugEnabled() {
50
+ const rc = useRuntimeConfig();
51
+ const debugConfig = rc?.queue?.debug;
52
+ const level = debugConfig?.level || process.env.NQ_DEBUG_LEVEL;
53
+ return level === "debug" || Object.keys(debugConfig || {}).some((key) => key !== "level");
54
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * WebSocket Peer Manager
3
+ *
4
+ * Tracks active WebSocket connections for graceful shutdown during HMR.
5
+ * Auto-imported in Nitro server context.
6
+ */
7
+ /**
8
+ * Register a peer to be tracked for graceful shutdown
9
+ */
10
+ export declare function registerWsPeer(peer: any): void;
11
+ /**
12
+ * Unregister a peer (called when connection closes normally)
13
+ */
14
+ export declare function unregisterWsPeer(peer: any): void;
15
+ /**
16
+ * Get all currently active WebSocket peers
17
+ */
18
+ export declare function getActivePeers(): any[];
19
+ /**
20
+ * Check if server is currently shutting down
21
+ */
22
+ export declare function isServerShuttingDown(): boolean;
23
+ /**
24
+ * Set the shutdown state
25
+ */
26
+ export declare function setShuttingDown(state: boolean): void;
27
+ /**
28
+ * Clear all tracked peers
29
+ */
30
+ export declare function clearAllPeers(): void;
31
+ /**
32
+ * Get the count of active peers
33
+ */
34
+ export declare function getActivePeerCount(): number;
@@ -0,0 +1,23 @@
1
+ const activePeers = /* @__PURE__ */ new Set();
2
+ let isShuttingDown = false;
3
+ export function registerWsPeer(peer) {
4
+ activePeers.add(peer);
5
+ }
6
+ export function unregisterWsPeer(peer) {
7
+ activePeers.delete(peer);
8
+ }
9
+ export function getActivePeers() {
10
+ return Array.from(activePeers);
11
+ }
12
+ export function isServerShuttingDown() {
13
+ return isShuttingDown;
14
+ }
15
+ export function setShuttingDown(state) {
16
+ isShuttingDown = state;
17
+ }
18
+ export function clearAllPeers() {
19
+ activePeers.clear();
20
+ }
21
+ export function getActivePeerCount() {
22
+ return activePeers.size;
23
+ }
@@ -0,0 +1,4 @@
1
+ import { Worker } from 'bullmq';
2
+ import { type NodeHandler } from './runner/node.js';
3
+ export declare function closeAllWorkers(): Promise<void>;
4
+ export declare function registerTsWorker(queueName: string, jobName: string, handler: NodeHandler, opts?: any): Promise<Worker<any, any, string>>;
@@ -0,0 +1,65 @@
1
+ import { Worker } from "bullmq";
2
+ import { createBullMQProcessor } from "./runner/node.js";
3
+ import { useRuntimeConfig, useServerLogger } from "#imports";
4
+ const registeredWorkers = /* @__PURE__ */ new Map();
5
+ const logger = useServerLogger("worker-adapter");
6
+ export async function closeAllWorkers() {
7
+ const closePromises = [];
8
+ for (const [queueName, info] of registeredWorkers.entries()) {
9
+ closePromises.push(
10
+ info.worker.close().catch((err) => {
11
+ if (err.code !== "EPIPE" && !err.message?.includes("Connection is closed")) {
12
+ logger.warn("Error closing worker for queue", { queueName, error: err });
13
+ }
14
+ })
15
+ );
16
+ }
17
+ await Promise.allSettled(closePromises);
18
+ registeredWorkers.clear();
19
+ logger.info("[closeAllWorkers] All workers closed");
20
+ }
21
+ export async function registerTsWorker(queueName, jobName, handler, opts) {
22
+ let info = registeredWorkers.get(queueName);
23
+ if (info) {
24
+ logger.info(`[registerTsWorker] Adding handler for job "${jobName}" to existing worker for queue "${queueName}"`);
25
+ info.handlers.set(jobName, handler);
26
+ return info.worker;
27
+ }
28
+ logger.info(`[registerTsWorker] Creating new worker for queue: ${queueName}`);
29
+ const handlers = /* @__PURE__ */ new Map();
30
+ handlers.set(jobName, handler);
31
+ const dispatcher = async (job) => {
32
+ const handler2 = handlers.get(job.name);
33
+ if (!handler2) {
34
+ const error = `[Worker] No handler registered for job "${job.name}" on queue "${queueName}". Available handlers: ${Array.from(handlers.keys()).join(", ")}`;
35
+ logger.error(error);
36
+ throw new Error(error);
37
+ }
38
+ const processor = createBullMQProcessor(handler2, queueName);
39
+ return processor(job);
40
+ };
41
+ const rc = useRuntimeConfig();
42
+ const connection = rc?.queue?.queue?.redis;
43
+ const shouldPause = opts?.autorun === false;
44
+ const worker = new Worker(queueName, dispatcher, { connection, ...opts || {} });
45
+ if (shouldPause) {
46
+ await worker.pause();
47
+ logger.info(`[registerTsWorker] Worker for queue "${queueName}" created but paused (autorun: false)`);
48
+ } else {
49
+ logger.info(`[registerTsWorker] Worker for queue "${queueName}" created and running`);
50
+ }
51
+ worker.on("error", (err) => {
52
+ logger.error(`[Worker] Error in worker for queue "${queueName}":`, err);
53
+ });
54
+ worker.on("failed", (job, err) => {
55
+ logger.error(`[Worker] Job failed in worker for queue "${queueName}":`, {
56
+ jobId: job?.id,
57
+ jobName: job?.name,
58
+ error: err.message,
59
+ stack: err.stack
60
+ });
61
+ });
62
+ info = { worker, handlers };
63
+ registeredWorkers.set(queueName, info);
64
+ return worker;
65
+ }
@@ -0,0 +1,27 @@
1
+ import type { Job as BullJob } from 'bullmq';
2
+ import { useFlowEngine } from '#imports';
3
+ export interface RunLogger {
4
+ log: (level: 'debug' | 'info' | 'warn' | 'error', msg: string, meta?: any) => void;
5
+ }
6
+ export interface RunState {
7
+ get<T = any>(key: string): Promise<T | null>;
8
+ set<T = any>(key: string, value: T, opts?: {
9
+ ttl?: number;
10
+ }): Promise<void>;
11
+ delete(key: string): Promise<void>;
12
+ }
13
+ export interface RunContext {
14
+ jobId?: string;
15
+ queue?: string;
16
+ flowId?: string;
17
+ flowName?: string;
18
+ stepName?: string;
19
+ stepId?: string;
20
+ attempt?: number;
21
+ logger: RunLogger;
22
+ state: RunState;
23
+ flow: ReturnType<typeof useFlowEngine>;
24
+ }
25
+ export declare function buildContext(partial?: Partial<RunContext>): RunContext;
26
+ export type NodeHandler = (input: any, ctx: RunContext) => Promise<any>;
27
+ export declare function createBullMQProcessor(handler: NodeHandler, queueName: string): (job: BullJob) => Promise<any>;
@@ -0,0 +1,196 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { getStateProvider } from "../../state/stateFactory.js";
3
+ import { useRuntimeConfig, useLogs, useFlowEngine, useEventManager, useServerLogger } from "#imports";
4
+ const logger = useServerLogger("node-runner");
5
+ const defaultState = {
6
+ async get() {
7
+ return null;
8
+ },
9
+ async set() {
10
+ },
11
+ async delete() {
12
+ }
13
+ };
14
+ function scopeKey(baseKey, flowId) {
15
+ if (!flowId) return baseKey;
16
+ return `flow:${flowId}:${baseKey}`;
17
+ }
18
+ export function buildContext(partial) {
19
+ const state = partial?.state || (() => {
20
+ try {
21
+ const state2 = getStateProvider();
22
+ const rc = useRuntimeConfig();
23
+ const cleanupCfg = rc?.queue?.state?.cleanup || { strategy: "never" };
24
+ return {
25
+ async get(key) {
26
+ return state2.get(scopeKey(key, partial?.flowId));
27
+ },
28
+ async set(key, value, opts) {
29
+ const ttl = opts?.ttl ?? (cleanupCfg?.strategy === "ttl" ? cleanupCfg?.ttlMs : void 0);
30
+ return state2.set(scopeKey(key, partial?.flowId), value, ttl ? { ttl } : void 0);
31
+ },
32
+ async delete(key) {
33
+ return state2.delete(scopeKey(key, partial?.flowId));
34
+ }
35
+ };
36
+ } catch {
37
+ return defaultState;
38
+ }
39
+ })();
40
+ const logger2 = partial?.logger || (() => {
41
+ const logs = useLogs();
42
+ return {
43
+ log: (level, msg, meta) => {
44
+ const mergedMeta = { ...meta || {} };
45
+ void logs.publishLog(level, msg, mergedMeta, { queue: partial?.queue, jobId: partial?.jobId, flowId: partial?.flowId });
46
+ }
47
+ };
48
+ })();
49
+ const baseFlowEngine = useFlowEngine();
50
+ const flow = {
51
+ ...baseFlowEngine,
52
+ emit: async (trigger, payload = {}) => {
53
+ const enrichedPayload = {
54
+ ...payload,
55
+ flowId: payload.flowId || partial?.flowId,
56
+ flowName: payload.flowName || partial?.flowName
57
+ };
58
+ return baseFlowEngine.emit(trigger, enrichedPayload);
59
+ }
60
+ };
61
+ return {
62
+ jobId: partial?.jobId,
63
+ queue: partial?.queue,
64
+ flowId: partial?.flowId,
65
+ flowName: partial?.flowName,
66
+ stepName: partial?.stepName,
67
+ stepId: partial?.stepId,
68
+ attempt: partial?.attempt,
69
+ logger: logger2,
70
+ state,
71
+ flow
72
+ };
73
+ }
74
+ export function createBullMQProcessor(handler, queueName) {
75
+ return async function processor(job) {
76
+ if (job.data?.__scheduledFlowStart) {
77
+ const { __flowName, __flowInput } = job.data;
78
+ try {
79
+ const { startFlow } = useFlowEngine();
80
+ const result2 = await startFlow(__flowName, __flowInput || {});
81
+ return {
82
+ scheduled: true,
83
+ flowId: result2.flowId,
84
+ flowName: __flowName
85
+ };
86
+ } catch (err) {
87
+ logger.error("[scheduled-flow] Failed to start flow:", err);
88
+ throw err;
89
+ }
90
+ }
91
+ const eventMgr = useEventManager();
92
+ const rc = useRuntimeConfig();
93
+ const autoScope = rc?.queue?.state?.autoScope || "always";
94
+ const providedFlow = job.data?.flowId;
95
+ const flowId = providedFlow || (autoScope === "always" ? randomUUID() : void 0);
96
+ const attempt = (job.attemptsMade || 0) + 1;
97
+ const maxAttempts = job.opts?.attempts || 1;
98
+ const isFinalAttempt = attempt >= maxAttempts;
99
+ const stepRunId = `${String(flowId || job.id)}__${job.name}__attempt-${attempt}`;
100
+ const flowName = job.data?.flowName || "unknown";
101
+ const ctx = buildContext({
102
+ jobId: job.id,
103
+ queue: queueName,
104
+ flowId,
105
+ flowName,
106
+ stepName: job.name,
107
+ stepId: stepRunId,
108
+ attempt
109
+ });
110
+ const attemptLogger = {
111
+ log: (level, msg, meta) => {
112
+ const enriched = { ...meta || {}, stepName: job.name, attempt, stepRunId, flowName };
113
+ ctx.logger.log(level, msg, enriched);
114
+ }
115
+ };
116
+ try {
117
+ await eventMgr.publishBus({
118
+ type: "step.started",
119
+ runId: flowId || "unknown",
120
+ flowName,
121
+ stepName: job.name,
122
+ stepId: stepRunId,
123
+ attempt,
124
+ data: { jobId: job.id, name: job.name, queue: queueName }
125
+ });
126
+ } catch {
127
+ }
128
+ let result;
129
+ try {
130
+ const workerInput = job.data?.input !== void 0 ? job.data.input : job.data;
131
+ result = await handler(workerInput, { ...ctx, logger: attemptLogger });
132
+ } catch (err) {
133
+ logger.error(`[worker] Job failed: ${job.name} (${job.id})`, {
134
+ queue: queueName,
135
+ flowId,
136
+ flowName,
137
+ stepName: job.name,
138
+ error: err?.message || String(err),
139
+ stack: err?.stack
140
+ });
141
+ const willRetry = !isFinalAttempt;
142
+ try {
143
+ await eventMgr.publishBus({
144
+ type: "step.failed",
145
+ runId: flowId || "unknown",
146
+ flowName,
147
+ stepName: job.name,
148
+ stepId: stepRunId,
149
+ attempt,
150
+ data: {
151
+ error: String(err?.message || err),
152
+ stack: err?.stack
153
+ }
154
+ });
155
+ } catch {
156
+ }
157
+ if (willRetry) {
158
+ try {
159
+ await eventMgr.publishBus({
160
+ type: "step.retry",
161
+ runId: flowId || "unknown",
162
+ flowName,
163
+ stepName: job.name,
164
+ stepId: stepRunId,
165
+ attempt,
166
+ data: {
167
+ stepName: job.name,
168
+ queue: queueName,
169
+ error: String(err?.message || err),
170
+ stack: err?.stack,
171
+ attempt,
172
+ maxAttempts,
173
+ nextAttempt: attempt + 1
174
+ }
175
+ });
176
+ } catch {
177
+ }
178
+ }
179
+ throw err;
180
+ }
181
+ try {
182
+ const eventMgr2 = useEventManager();
183
+ await eventMgr2.publishBus({
184
+ type: "step.completed",
185
+ runId: flowId || "unknown",
186
+ flowName,
187
+ stepName: job.name,
188
+ stepId: stepRunId,
189
+ attempt,
190
+ data: { result }
191
+ });
192
+ } catch {
193
+ }
194
+ return result;
195
+ };
196
+ }
@@ -0,0 +1,132 @@
1
+ import type { WorkerOptions as BullmqWorkerOptions } from 'bullmq'
2
+ import type z from 'zod'
3
+ import type colors from 'tailwindcss/colors'
4
+ import type { JobSchemaArray, JobSchema } from './schema'
5
+
6
+ type NeutralColor = 'slate' | 'gray' | 'zinc' | 'neutral' | 'stone'
7
+ export type Color = Exclude<keyof typeof colors, 'inherit' | 'current' | 'transparent' | 'black' | 'white' | NeutralColor> | NeutralColor
8
+
9
+ export type Jobs = z.infer<typeof JobSchemaArray>
10
+ export type Job = z.infer<typeof JobSchema>
11
+
12
+ export type WorkerOptions = Omit<BullmqWorkerOptions, 'connection' | 'useWorkerThreads'>
13
+
14
+ export type WorkerConfig = Record<string, WorkerOptions>
15
+
16
+ export type QueueData = {
17
+ name: string
18
+ origin: 'remote' | 'local'
19
+ active: boolean
20
+ jobs: JobCounts
21
+ worker: number
22
+ }
23
+
24
+ // Declarations for worker authoring helpers available via auto-imports at runtime
25
+ // These declarations make TS happy in worker files and tests.
26
+ export declare function defineQueueWorker(processor: (...args: any[]) => any): any
27
+ export declare function defineQueueConfig(cfg: any): any
28
+
29
+ // v0.4 Event Schema
30
+ export type EventType = 'flow.start' | 'flow.completed' | 'flow.failed' | 'step.started' | 'step.completed' | 'step.failed' | 'step.retry' | 'log' | 'emit' | 'state'
31
+
32
+ export interface BaseEvent {
33
+ id?: string // Redis stream ID (auto-generated, not present for ingress events)
34
+ ts?: string // ISO timestamp (auto-generated, not present for ingress events)
35
+ type: EventType
36
+ runId: string // Flow run UUID
37
+ flowName: string // Flow definition name
38
+ }
39
+
40
+ export interface StepEvent extends BaseEvent {
41
+ stepName: string
42
+ stepId: string
43
+ attempt: number
44
+ }
45
+
46
+ export interface FlowStartEvent extends BaseEvent {
47
+ type: 'flow.start'
48
+ data?: {
49
+ input?: any
50
+ }
51
+ }
52
+
53
+ export interface FlowCompletedEvent extends BaseEvent {
54
+ type: 'flow.completed'
55
+ data?: {
56
+ result?: any
57
+ }
58
+ }
59
+
60
+ export interface FlowFailedEvent extends BaseEvent {
61
+ type: 'flow.failed'
62
+ data?: {
63
+ error?: string
64
+ stack?: string
65
+ }
66
+ }
67
+
68
+ export interface StepStartedEvent extends StepEvent {
69
+ type: 'step.started'
70
+ data?: {
71
+ input?: any
72
+ }
73
+ }
74
+
75
+ export interface StepCompletedEvent extends StepEvent {
76
+ type: 'step.completed'
77
+ data?: {
78
+ result?: any
79
+ }
80
+ }
81
+
82
+ export interface StepFailedEvent extends StepEvent {
83
+ type: 'step.failed'
84
+ data?: {
85
+ error?: string
86
+ stack?: string
87
+ }
88
+ }
89
+
90
+ export interface StepRetryEvent extends StepEvent {
91
+ type: 'step.retry'
92
+ data?: {
93
+ stepName: string
94
+ queue: string
95
+ error?: string
96
+ stack?: string
97
+ attempt: number
98
+ maxAttempts: number
99
+ nextAttempt: number
100
+ }
101
+ }
102
+
103
+ export interface LogEvent extends StepEvent {
104
+ type: 'log'
105
+ data: {
106
+ level: 'debug' | 'info' | 'warn' | 'error'
107
+ message: string
108
+ [key: string]: any
109
+ }
110
+ }
111
+
112
+ export interface EmitEvent extends StepEvent {
113
+ type: 'emit'
114
+ data: {
115
+ topic: string
116
+ payload: any
117
+ }
118
+ }
119
+
120
+ export interface StateEvent extends StepEvent {
121
+ type: 'state'
122
+ data: {
123
+ operation: 'get' | 'set' | 'delete'
124
+ scope?: string
125
+ key: string
126
+ value?: any
127
+ }
128
+ }
129
+
130
+ export type FlowEvent = FlowStartEvent | FlowCompletedEvent | FlowFailedEvent | StepStartedEvent | StepCompletedEvent | StepFailedEvent | StepRetryEvent | LogEvent | EmitEvent | StateEvent
131
+
132
+ export type EventRecord = FlowEvent
@@ -0,0 +1,3 @@
1
+ export { default } from './module.mjs'
2
+
3
+ export { type ModuleOptions } from './module.mjs'
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "nvent",
3
+ "version": "0.4.0",
4
+ "description": "Nuxt queue service based on Bullmq",
5
+ "repository": "DevJoghurt/nuxt-queue",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/types.d.mts",
11
+ "import": "./dist/module.mjs"
12
+ }
13
+ },
14
+ "main": "./dist/module.mjs",
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "yarn dev:prepare && nuxt-module-build build",
20
+ "dev": "nuxi dev playground",
21
+ "dev:build": "nuxi build playground",
22
+ "dev:preview": "nuxi preview playground",
23
+ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
24
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
25
+ "test": "vitest",
26
+ "lint": "eslint --ext .ts,.js,.mjs,.cjs,.vue .",
27
+ "cleanup": "rimraf dist*/ **/node_modules .nuxt* playground/.data",
28
+ "bumpp": "bumpp"
29
+ },
30
+ "dependencies": {
31
+ "@babel/parser": "^7.28.5",
32
+ "@iconify-json/devicon": "^1.2.46",
33
+ "@iconify-json/heroicons": "1.2.3",
34
+ "@iconify-json/lucide": "^1.2.72",
35
+ "@nuxt/kit": "4.2.1",
36
+ "@vue-flow/background": "^1.3.2",
37
+ "@vue-flow/controls": "^1.1.3",
38
+ "@vue-flow/core": "^1.47.0",
39
+ "@vue-flow/minimap": "^1.5.4",
40
+ "bullmq": "^5.63.0",
41
+ "chokidar": "^4.0.3",
42
+ "defu": "^6.1.4",
43
+ "globby": "15.0.0",
44
+ "ioredis": "^5.8.2",
45
+ "json-editor-vue": "^0.18.1",
46
+ "magicast": "^0.5.1",
47
+ "mlly": "^1.8.0",
48
+ "node-ts": "8.0.8",
49
+ "nuxt": "4.2.1",
50
+ "pathe": "^2.0.3",
51
+ "perfect-debounce": "^2.0.0",
52
+ "pkg-types": "^2.3.0",
53
+ "semver": "^7.7.3",
54
+ "zod": "^4.1.12"
55
+ },
56
+ "devDependencies": {
57
+ "@nuxt/devtools": "^3.0.1",
58
+ "@nuxt/eslint-config": "^1.10.0",
59
+ "@nuxt/module-builder": "^1.0.2",
60
+ "@nuxt/schema": "4.2.1",
61
+ "@nuxt/test-utils": "^3.20.1",
62
+ "@nuxt/ui": "4.1.0",
63
+ "@types/node": "^24.10.0",
64
+ "bumpp": "10.3.1",
65
+ "changelogen": "^0.6.2",
66
+ "eslint": "^9.39.1",
67
+ "nuxi": "^3.30.0",
68
+ "nuxt-mcp": "0.2.6",
69
+ "rimraf": "^6.1.0",
70
+ "typescript": "latest",
71
+ "vitest": "^4.0.7",
72
+ "vue-tsc": "^3.1.3"
73
+ },
74
+ "packageManager": "yarn@4.10.3"
75
+ }