nvent 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 (124) hide show
  1. package/dist/module.d.mts +1 -1
  2. package/dist/module.mjs +433 -180
  3. package/dist/runtime/adapters/base/index.d.ts +6 -0
  4. package/dist/runtime/adapters/base/index.js +1 -0
  5. package/dist/runtime/adapters/base/store-validator.d.ts +48 -0
  6. package/dist/runtime/adapters/base/store-validator.js +147 -0
  7. package/dist/runtime/adapters/builtin/file-queue.d.ts +15 -1
  8. package/dist/runtime/adapters/builtin/file-queue.js +70 -6
  9. package/dist/runtime/adapters/builtin/file-store.d.ts +4 -18
  10. package/dist/runtime/adapters/builtin/file-store.js +90 -109
  11. package/dist/runtime/adapters/builtin/memory-queue.js +4 -0
  12. package/dist/runtime/adapters/builtin/memory-store.d.ts +42 -31
  13. package/dist/runtime/adapters/builtin/memory-store.js +253 -183
  14. package/dist/runtime/adapters/factory.d.ts +2 -2
  15. package/dist/runtime/adapters/factory.js +54 -20
  16. package/dist/runtime/adapters/interfaces/store.d.ts +177 -113
  17. package/dist/runtime/config/index.d.ts +2 -2
  18. package/dist/runtime/config/index.js +14 -6
  19. package/dist/runtime/config/types.d.ts +32 -2
  20. package/dist/runtime/events/eventBus.d.ts +1 -1
  21. package/dist/runtime/events/types.d.ts +31 -2
  22. package/dist/runtime/events/utils/scheduleTrigger.d.ts +8 -0
  23. package/dist/runtime/events/utils/scheduleTrigger.js +69 -0
  24. package/dist/runtime/events/utils/stallDetector.d.ts +44 -3
  25. package/dist/runtime/events/utils/stallDetector.js +288 -89
  26. package/dist/runtime/events/utils/triggerRuntime.d.ts +58 -0
  27. package/dist/runtime/events/utils/triggerRuntime.js +212 -0
  28. package/dist/runtime/events/wiring/flowWiring.d.ts +11 -5
  29. package/dist/runtime/events/wiring/flowWiring.js +620 -92
  30. package/dist/runtime/events/wiring/registry.d.ts +2 -2
  31. package/dist/runtime/events/wiring/registry.js +8 -6
  32. package/dist/runtime/events/wiring/streamWiring.d.ts +15 -11
  33. package/dist/runtime/events/wiring/streamWiring.js +88 -11
  34. package/dist/runtime/events/wiring/triggerWiring.d.ts +21 -0
  35. package/dist/runtime/events/wiring/triggerWiring.js +412 -0
  36. package/dist/runtime/{server → nitro}/plugins/00.adapters.js +8 -4
  37. package/dist/runtime/{server → nitro}/plugins/02.workers.js +21 -3
  38. package/dist/runtime/nitro/plugins/03.triggers.d.ts +12 -0
  39. package/dist/runtime/nitro/plugins/03.triggers.js +55 -0
  40. package/dist/runtime/nitro/routes/webhook.await.d.ts +23 -0
  41. package/dist/runtime/nitro/routes/webhook.await.js +90 -0
  42. package/dist/runtime/nitro/routes/webhook.trigger.d.ts +69 -0
  43. package/dist/runtime/nitro/routes/webhook.trigger.js +64 -0
  44. package/dist/runtime/{utils → nitro/utils}/adapters.d.ts +6 -6
  45. package/dist/runtime/nitro/utils/awaitPatterns/event.d.ts +15 -0
  46. package/dist/runtime/nitro/utils/awaitPatterns/event.js +120 -0
  47. package/dist/runtime/nitro/utils/awaitPatterns/index.d.ts +28 -0
  48. package/dist/runtime/nitro/utils/awaitPatterns/index.js +55 -0
  49. package/dist/runtime/nitro/utils/awaitPatterns/schedule.d.ts +16 -0
  50. package/dist/runtime/nitro/utils/awaitPatterns/schedule.js +78 -0
  51. package/dist/runtime/nitro/utils/awaitPatterns/time.d.ts +15 -0
  52. package/dist/runtime/nitro/utils/awaitPatterns/time.js +67 -0
  53. package/dist/runtime/nitro/utils/awaitPatterns/webhook.d.ts +15 -0
  54. package/dist/runtime/nitro/utils/awaitPatterns/webhook.js +120 -0
  55. package/dist/runtime/{utils → nitro/utils}/defineFunction.d.ts +2 -2
  56. package/dist/runtime/{utils → nitro/utils}/defineFunction.js +3 -3
  57. package/dist/runtime/{utils → nitro/utils}/defineFunctionConfig.d.ts +156 -0
  58. package/dist/runtime/{utils → nitro/utils}/defineFunctionConfig.js +1 -0
  59. package/dist/runtime/nitro/utils/defineHooks.d.ts +41 -0
  60. package/dist/runtime/nitro/utils/defineHooks.js +6 -0
  61. package/dist/runtime/{utils → nitro/utils}/registerAdapter.d.ts +3 -3
  62. package/dist/runtime/{utils → nitro/utils}/registerAdapter.js +1 -1
  63. package/dist/runtime/nitro/utils/useAwait.d.ts +71 -0
  64. package/dist/runtime/nitro/utils/useAwait.js +139 -0
  65. package/dist/runtime/{utils → nitro/utils}/useEventManager.d.ts +2 -2
  66. package/dist/runtime/{utils → nitro/utils}/useEventManager.js +1 -1
  67. package/dist/runtime/nitro/utils/useFlow.d.ts +68 -0
  68. package/dist/runtime/nitro/utils/useFlow.js +226 -0
  69. package/dist/runtime/nitro/utils/useHookRegistry.d.ts +34 -0
  70. package/dist/runtime/nitro/utils/useHookRegistry.js +25 -0
  71. package/dist/runtime/nitro/utils/useRunContext.d.ts +6 -0
  72. package/dist/runtime/nitro/utils/useRunContext.js +102 -0
  73. package/dist/runtime/nitro/utils/useStreamTopics.d.ts +83 -0
  74. package/dist/runtime/nitro/utils/useStreamTopics.js +94 -0
  75. package/dist/runtime/nitro/utils/useTrigger.d.ts +150 -0
  76. package/dist/runtime/nitro/utils/useTrigger.js +320 -0
  77. package/dist/runtime/scheduler/index.d.ts +33 -0
  78. package/dist/runtime/scheduler/index.js +38 -0
  79. package/dist/runtime/scheduler/scheduler.d.ts +113 -0
  80. package/dist/runtime/scheduler/scheduler.js +623 -0
  81. package/dist/runtime/scheduler/types.d.ts +116 -0
  82. package/dist/runtime/scheduler/types.js +0 -0
  83. package/dist/runtime/worker/node/runner.d.ts +12 -2
  84. package/dist/runtime/worker/node/runner.js +141 -37
  85. package/package.json +6 -6
  86. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.d.ts +0 -10
  87. package/dist/runtime/server/api/_flows/[name]/clear-history.delete.js +0 -55
  88. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.d.ts +0 -2
  89. package/dist/runtime/server/api/_flows/[name]/runs/[runId]/cancel.post.js +0 -21
  90. package/dist/runtime/server/api/_flows/[name]/runs.get.d.ts +0 -17
  91. package/dist/runtime/server/api/_flows/[name]/runs.get.js +0 -64
  92. package/dist/runtime/server/api/_flows/[name]/schedule.post.d.ts +0 -2
  93. package/dist/runtime/server/api/_flows/[name]/schedule.post.js +0 -66
  94. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.d.ts +0 -2
  95. package/dist/runtime/server/api/_flows/[name]/schedules/[id].delete.js +0 -47
  96. package/dist/runtime/server/api/_flows/[name]/schedules.get.d.ts +0 -2
  97. package/dist/runtime/server/api/_flows/[name]/schedules.get.js +0 -50
  98. package/dist/runtime/server/api/_flows/[name]/start.post.d.ts +0 -2
  99. package/dist/runtime/server/api/_flows/[name]/start.post.js +0 -9
  100. package/dist/runtime/server/api/_flows/index.get.d.ts +0 -6
  101. package/dist/runtime/server/api/_flows/index.get.js +0 -5
  102. package/dist/runtime/server/api/_flows/ws.d.ts +0 -60
  103. package/dist/runtime/server/api/_flows/ws.js +0 -209
  104. package/dist/runtime/server/api/_queues/[name]/job/[id].get.d.ts +0 -2
  105. package/dist/runtime/server/api/_queues/[name]/job/[id].get.js +0 -14
  106. package/dist/runtime/server/api/_queues/[name]/job/index.get.d.ts +0 -2
  107. package/dist/runtime/server/api/_queues/[name]/job/index.get.js +0 -27
  108. package/dist/runtime/server/api/_queues/index.get.d.ts +0 -2
  109. package/dist/runtime/server/api/_queues/index.get.js +0 -106
  110. package/dist/runtime/server/api/_queues/ws.d.ts +0 -48
  111. package/dist/runtime/server/api/_queues/ws.js +0 -215
  112. package/dist/runtime/utils/useFlowEngine.d.ts +0 -19
  113. package/dist/runtime/utils/useFlowEngine.js +0 -108
  114. package/dist/runtime/utils/useStreamTopics.d.ts +0 -72
  115. package/dist/runtime/utils/useStreamTopics.js +0 -47
  116. /package/dist/runtime/{server → nitro}/plugins/00.adapters.d.ts +0 -0
  117. /package/dist/runtime/{server → nitro}/plugins/01.ws-lifecycle.d.ts +0 -0
  118. /package/dist/runtime/{server → nitro}/plugins/01.ws-lifecycle.js +0 -0
  119. /package/dist/runtime/{server → nitro}/plugins/02.workers.d.ts +0 -0
  120. /package/dist/runtime/{utils → nitro/utils}/adapters.js +0 -0
  121. /package/dist/runtime/{utils → nitro/utils}/useNventLogger.d.ts +0 -0
  122. /package/dist/runtime/{utils → nitro/utils}/useNventLogger.js +0 -0
  123. /package/dist/runtime/{utils → nitro/utils}/wsPeerManager.d.ts +0 -0
  124. /package/dist/runtime/{utils → nitro/utils}/wsPeerManager.js +0 -0
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Scheduler Types
3
+ *
4
+ * Unified scheduling system for all time-based operations in nvent:
5
+ * - Stall detection
6
+ * - Await timeouts
7
+ * - Trigger schedules
8
+ * - Cleanup jobs
9
+ */
10
+ export interface ScheduledJob {
11
+ /**
12
+ * Unique job identifier
13
+ */
14
+ id: string;
15
+ /**
16
+ * Human-readable job name
17
+ */
18
+ name: string;
19
+ /**
20
+ * Job type
21
+ */
22
+ type: 'cron' | 'interval' | 'one-time';
23
+ /**
24
+ * Cron expression (for type: 'cron')
25
+ * @example '0 2 * * *' - Daily at 2 AM
26
+ * @example '* /5 * * * *' - Every 5 minutes
27
+ */
28
+ cron?: string;
29
+ /**
30
+ * Interval in milliseconds (for type: 'interval')
31
+ */
32
+ interval?: number;
33
+ /**
34
+ * Execution timestamp (for type: 'one-time')
35
+ */
36
+ executeAt?: number;
37
+ /**
38
+ * Job handler function
39
+ */
40
+ handler: () => Promise<void>;
41
+ /**
42
+ * Timezone for cron jobs
43
+ * @default 'UTC'
44
+ */
45
+ timezone?: string;
46
+ /**
47
+ * Whether the job is enabled
48
+ * @default true
49
+ */
50
+ enabled?: boolean;
51
+ /**
52
+ * Additional metadata
53
+ */
54
+ metadata?: Record<string, any>;
55
+ /**
56
+ * Last execution timestamp
57
+ */
58
+ lastRun?: number;
59
+ /**
60
+ * Next scheduled execution timestamp
61
+ */
62
+ nextRun?: number;
63
+ /**
64
+ * Total execution count
65
+ */
66
+ runCount?: number;
67
+ /**
68
+ * Failure count
69
+ */
70
+ failCount?: number;
71
+ }
72
+ export interface SchedulerAdapter {
73
+ /**
74
+ * Schedule a job with distributed locking support
75
+ */
76
+ schedule(job: ScheduledJob): Promise<string>;
77
+ /**
78
+ * Unschedule a job
79
+ */
80
+ unschedule(jobId: string): Promise<boolean>;
81
+ /**
82
+ * Start the scheduler (begins processing scheduled jobs)
83
+ */
84
+ start(): Promise<void>;
85
+ /**
86
+ * Stop the scheduler and release all locks
87
+ */
88
+ stop(): Promise<void>;
89
+ /**
90
+ * Get all scheduled jobs (in-memory, for this instance)
91
+ */
92
+ getScheduledJobs(): Promise<ScheduledJob[]>;
93
+ /**
94
+ * Get all persisted jobs from store (across all instances)
95
+ * Useful for debugging and monitoring in horizontal setups
96
+ */
97
+ getAllPersistedJobs(): Promise<ScheduledJob[]>;
98
+ /**
99
+ * Check if scheduler is healthy
100
+ */
101
+ isHealthy(): Promise<boolean>;
102
+ }
103
+ export interface SchedulerLock {
104
+ jobId: string;
105
+ instanceId: string;
106
+ acquiredAt: number;
107
+ expiresAt: number;
108
+ }
109
+ export interface SchedulerStats {
110
+ jobId: string;
111
+ lastRun: number;
112
+ nextRun?: number;
113
+ runCount: number;
114
+ failCount: number;
115
+ lastError?: string;
116
+ }
File without changes
@@ -1,4 +1,4 @@
1
- import { useFlowEngine } from '#imports';
1
+ import { useFlow } from '#imports';
2
2
  /**
3
3
  * Generic job interface that works with any queue adapter
4
4
  * Adapters should provide jobs in this format
@@ -32,7 +32,17 @@ export interface RunContext {
32
32
  attempt?: number;
33
33
  logger: RunLogger;
34
34
  state: RunState;
35
- flow: ReturnType<typeof useFlowEngine>;
35
+ flow: ReturnType<typeof useFlow>;
36
+ /**
37
+ * Resolved data from await pattern (awaitBefore only)
38
+ * Available when step resumes after await resolution
39
+ */
40
+ trigger?: any;
41
+ /**
42
+ * Current step's await configuration
43
+ * Useful for conditional logic based on await settings
44
+ */
45
+ awaitConfig?: any;
36
46
  }
37
47
  export declare function buildContext(partial?: Partial<RunContext>): RunContext;
38
48
  export type NodeHandler = (input: any, ctx: RunContext) => Promise<any>;
@@ -1,6 +1,17 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { useStateAdapter } from "../../utils/adapters.js";
3
- import { useRuntimeConfig, useFlowEngine, useEventManager, useNventLogger } from "#imports";
2
+ import {
3
+ useRuntimeConfig,
4
+ useFlow,
5
+ useEventManager,
6
+ useNventLogger,
7
+ $useFunctionRegistry,
8
+ useAwait,
9
+ useHookRegistry,
10
+ useStreamTopics,
11
+ useStateAdapter,
12
+ useStoreAdapter,
13
+ useRunContext
14
+ } from "#imports";
4
15
  const logger = useNventLogger("node-runner");
5
16
  const defaultState = {
6
17
  async get() {
@@ -55,14 +66,15 @@ export function buildContext(partial) {
55
66
  }
56
67
  };
57
68
  })();
58
- const baseFlowEngine = useFlowEngine();
69
+ const baseFlowEngine = useFlow();
59
70
  const flow = {
60
71
  ...baseFlowEngine,
61
72
  emit: async (trigger, payload = {}) => {
62
73
  const enrichedPayload = {
63
74
  ...payload,
64
75
  flowId: payload.flowId || partial?.flowId,
65
- flowName: payload.flowName || partial?.flowName
76
+ flowName: payload.flowName || partial?.flowName,
77
+ stepName: payload.stepName || partial?.stepName
66
78
  };
67
79
  return baseFlowEngine.emit(trigger, enrichedPayload);
68
80
  },
@@ -97,26 +109,13 @@ export function buildContext(partial) {
97
109
  attempt: partial?.attempt,
98
110
  logger: logger2,
99
111
  state,
100
- flow
112
+ flow,
113
+ trigger: partial?.trigger,
114
+ awaitConfig: partial?.awaitConfig
101
115
  };
102
116
  }
103
117
  export function createJobProcessor(handler, queueName) {
104
118
  return async function processor(job) {
105
- if (job.data?.__scheduledFlowStart) {
106
- const { __flowName, __flowInput } = job.data;
107
- try {
108
- const { startFlow } = useFlowEngine();
109
- const result2 = await startFlow(__flowName, __flowInput || {});
110
- return {
111
- scheduled: true,
112
- flowId: result2.flowId,
113
- flowName: __flowName
114
- };
115
- } catch (err) {
116
- logger.error("[scheduled-flow] Failed to start flow:", err);
117
- throw err;
118
- }
119
- }
120
119
  const eventMgr = useEventManager();
121
120
  const rc = useRuntimeConfig();
122
121
  const autoScope = rc?.nvent?.store?.state?.autoScope || "always";
@@ -127,6 +126,59 @@ export function createJobProcessor(handler, queueName) {
127
126
  const isFinalAttempt = attempt >= maxAttempts;
128
127
  const stepRunId = `${String(flowId || job.id)}__${job.name}__attempt-${attempt}`;
129
128
  const flowName = job.data?.flowName || "unknown";
129
+ const registry = $useFunctionRegistry();
130
+ const flowRegistry = (registry?.flows || {})[flowName];
131
+ let stepMeta = flowRegistry?.steps?.[job.name];
132
+ if (!stepMeta && flowRegistry?.entry?.step === job.name) {
133
+ stepMeta = flowRegistry?.entry;
134
+ }
135
+ const awaitBefore = stepMeta?.awaitBefore;
136
+ const awaitAfter = stepMeta?.awaitAfter;
137
+ const isAwaitResume = job.data?.awaitResolved === true;
138
+ const awaitData = job.data?.awaitData;
139
+ if (awaitBefore && !isAwaitResume) {
140
+ const awaitLogger = useNventLogger("await-before");
141
+ awaitLogger.info("Step has awaitBefore, registering await pattern", {
142
+ flowName,
143
+ runId: flowId,
144
+ stepName: job.name,
145
+ awaitType: awaitBefore.type
146
+ });
147
+ try {
148
+ const { register } = useAwait();
149
+ const awaitResult = await register(
150
+ flowId || "unknown",
151
+ job.name,
152
+ flowName,
153
+ awaitBefore,
154
+ "before"
155
+ // Position: awaitBefore means wait before execution
156
+ );
157
+ const hookRegistry = useHookRegistry();
158
+ const hooks = hookRegistry.load(flowName, job.name);
159
+ if (hooks?.onAwaitRegister) {
160
+ try {
161
+ await hooks.onAwaitRegister(
162
+ awaitResult.webhookUrl || awaitResult.eventName || "",
163
+ job.data,
164
+ useRunContext({ flowId, flowName, stepName: job.name })
165
+ );
166
+ } catch (err) {
167
+ awaitLogger.error("onAwaitRegister hook failed", { error: err.message });
168
+ }
169
+ }
170
+ return {
171
+ awaiting: true,
172
+ awaitType: awaitBefore.type,
173
+ awaitConfig: awaitBefore
174
+ };
175
+ } catch (err) {
176
+ awaitLogger.error("Failed to register await pattern", {
177
+ error: err.message,
178
+ stack: err.stack
179
+ });
180
+ }
181
+ }
130
182
  const ctx = buildContext({
131
183
  jobId: job.id,
132
184
  queue: queueName,
@@ -134,7 +186,9 @@ export function createJobProcessor(handler, queueName) {
134
186
  flowName,
135
187
  stepName: job.name,
136
188
  stepId: stepRunId,
137
- attempt
189
+ attempt,
190
+ trigger: isAwaitResume ? awaitData : void 0,
191
+ awaitConfig: awaitBefore || awaitAfter || void 0
138
192
  });
139
193
  const attemptLogger = {
140
194
  log: (level, msg, meta) => {
@@ -168,21 +222,6 @@ export function createJobProcessor(handler, queueName) {
168
222
  stack: err?.stack
169
223
  });
170
224
  const willRetry = !isFinalAttempt;
171
- try {
172
- await eventMgr.publishBus({
173
- type: "step.failed",
174
- runId: flowId || "unknown",
175
- flowName,
176
- stepName: job.name,
177
- stepId: stepRunId,
178
- attempt,
179
- data: {
180
- error: String(err?.message || err),
181
- stack: err?.stack
182
- }
183
- });
184
- } catch {
185
- }
186
225
  if (willRetry) {
187
226
  try {
188
227
  await eventMgr.publishBus({
@@ -197,7 +236,25 @@ export function createJobProcessor(handler, queueName) {
197
236
  queue: queueName,
198
237
  attempt,
199
238
  maxAttempts,
200
- nextAttempt: attempt + 1
239
+ nextAttempt: attempt + 1,
240
+ error: String(err?.message || err),
241
+ stack: err?.stack
242
+ }
243
+ });
244
+ } catch {
245
+ }
246
+ } else {
247
+ try {
248
+ await eventMgr.publishBus({
249
+ type: "step.failed",
250
+ runId: flowId || "unknown",
251
+ flowName,
252
+ stepName: job.name,
253
+ stepId: stepRunId,
254
+ attempt,
255
+ data: {
256
+ error: String(err?.message || err),
257
+ stack: err?.stack
201
258
  }
202
259
  });
203
260
  } catch {
@@ -218,6 +275,53 @@ export function createJobProcessor(handler, queueName) {
218
275
  });
219
276
  } catch {
220
277
  }
278
+ if (awaitAfter && !isAwaitResume) {
279
+ const awaitLogger = useNventLogger("await-after");
280
+ awaitLogger.info("Step has awaitAfter, registering await pattern", {
281
+ flowName,
282
+ runId: flowId,
283
+ stepName: job.name,
284
+ awaitType: awaitAfter.type
285
+ });
286
+ try {
287
+ const store = useStoreAdapter();
288
+ const { StoreSubjects } = useStreamTopics();
289
+ const streamName = StoreSubjects.flowRun(flowId || "unknown");
290
+ let _emitEvents = [];
291
+ if (store.stream.read) {
292
+ const recentEvents = await store.stream.read(streamName, { limit: 100 });
293
+ _emitEvents = recentEvents.filter(
294
+ (evt) => evt.type === "emit" && evt.stepName === job.name && evt.stepId === stepRunId
295
+ );
296
+ }
297
+ const { register } = useAwait();
298
+ const awaitResult = await register(
299
+ flowId || "unknown",
300
+ job.name,
301
+ flowName,
302
+ awaitAfter,
303
+ "after"
304
+ );
305
+ const hookRegistry = useHookRegistry();
306
+ const hooks = hookRegistry.load(flowName, job.name);
307
+ if (hooks?.onAwaitRegister) {
308
+ try {
309
+ await hooks.onAwaitRegister(
310
+ awaitResult.webhookUrl || awaitResult.eventName || "",
311
+ { ...job.data, result },
312
+ ctx
313
+ );
314
+ } catch (err) {
315
+ awaitLogger.error("onAwaitRegister hook failed", { error: err.message });
316
+ }
317
+ }
318
+ } catch (err) {
319
+ awaitLogger.error("Failed to register awaitAfter pattern", {
320
+ error: err.message,
321
+ stack: err.stack
322
+ });
323
+ }
324
+ }
221
325
  return result;
222
326
  };
223
327
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nvent",
3
- "version": "0.4.5",
3
+ "version": "0.5.1",
4
4
  "description": "Event-driven workflows for Nuxt",
5
5
  "repository": "DevJoghurt/nvent",
6
6
  "license": "MIT",
@@ -19,12 +19,12 @@
19
19
  "scripts": {
20
20
  "build": "nuxt-module-build build",
21
21
  "dev": "nuxt-module-build build --stub",
22
- "prepack": "pnpm build",
23
- "test": "vitest"
22
+ "prepack": "pnpm build"
24
23
  },
25
24
  "dependencies": {
26
25
  "@nuxt/kit": "4.2.1",
27
- "chokidar": "^4.0.3",
26
+ "chokidar": "^5.0.0",
27
+ "cron": "^4.3.5",
28
28
  "cron-parser": "^5.4.0",
29
29
  "defu": "^6.1.4",
30
30
  "fastq": "^1.19.1",
@@ -33,13 +33,13 @@
33
33
  "nuxt": "4.2.1",
34
34
  "pathe": "^2.0.3",
35
35
  "perfect-debounce": "^2.0.0",
36
- "zod": "^4.1.12"
36
+ "zod": "^4.1.13"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@nuxt/module-builder": "^1.0.2",
40
40
  "@nuxt/schema": "4.2.1",
41
41
  "@types/node": "^24.10.1",
42
42
  "typescript": "latest",
43
- "vitest": "^4.0.10"
43
+ "vitest": "^4.0.15"
44
44
  }
45
45
  }
@@ -1,10 +0,0 @@
1
- /**
2
- * DELETE /api/_flows/:flowName/clear-history
3
- *
4
- * Clears all event history for a specific flow.
5
- * This deletes:
6
- * - All flow run streams (nq:flow:run-*)
7
- * - The flow runs index (nq:flows:<flowName>)
8
- */
9
- declare const _default: any;
10
- export default _default;
@@ -1,55 +0,0 @@
1
- import { defineEventHandler, createError, useStoreAdapter, useStreamTopics } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const flowName = event.context.params?.name;
4
- if (!flowName) {
5
- throw createError({ statusCode: 400, statusMessage: "Flow name required" });
6
- }
7
- let store;
8
- let SubjectPatterns;
9
- try {
10
- store = useStoreAdapter();
11
- const topics = useStreamTopics();
12
- SubjectPatterns = topics.SubjectPatterns;
13
- } catch {
14
- throw createError({
15
- statusCode: 503,
16
- statusMessage: "Server initializing",
17
- data: "Adapters not ready yet, please retry"
18
- });
19
- }
20
- try {
21
- let deletedStreams = 0;
22
- let deletedIndex = false;
23
- const indexKey = SubjectPatterns.flowRunIndex(flowName);
24
- if (store.indexRead) {
25
- const runs = await store.indexRead(indexKey, { limit: 1e4 });
26
- if (store.deleteStream) {
27
- for (const run of runs) {
28
- const streamName = SubjectPatterns.flowRun(run.id);
29
- await store.deleteStream(streamName);
30
- if (store.deleteIndex) {
31
- const metaKey = `${indexKey}:meta:${run.id}`;
32
- await store.deleteIndex(metaKey);
33
- }
34
- deletedStreams++;
35
- }
36
- }
37
- }
38
- if (store.deleteIndex) {
39
- await store.deleteIndex(indexKey);
40
- deletedIndex = true;
41
- }
42
- return {
43
- success: true,
44
- flowName,
45
- deletedStreams,
46
- deletedIndex
47
- };
48
- } catch (error) {
49
- throw createError({
50
- statusCode: 500,
51
- statusMessage: "Failed to clear flow history",
52
- data: error instanceof Error ? error.message : String(error)
53
- });
54
- }
55
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;
@@ -1,21 +0,0 @@
1
- import { defineEventHandler, getRouterParam, createError, useFlowEngine } 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 = useFlowEngine();
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,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 SubjectPatterns;
16
- try {
17
- store = useStoreAdapter();
18
- const topics = useStreamTopics();
19
- SubjectPatterns = topics.SubjectPatterns;
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 = SubjectPatterns.flowRunIndex(flowName);
29
- let totalCount = 0;
30
- try {
31
- const allEntries = await store.indexRead(runIndexKey, { limit: 1e4 });
32
- totalCount = allEntries.length;
33
- } catch {
34
- totalCount = 0;
35
- }
36
- const entries = await store.indexRead(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,66 +0,0 @@
1
- import { defineEventHandler, readBody, getRouterParam, createError, useQueueAdapter, $useQueueRegistry } from "#imports";
2
- export default defineEventHandler(async (event) => {
3
- const flowName = getRouterParam(event, "name");
4
- if (!flowName) {
5
- throw createError({ statusCode: 400, statusMessage: "Flow name is required" });
6
- }
7
- const body = await readBody(event);
8
- const { input, cron, delay, jobId, metadata } = body;
9
- if (cron && delay) {
10
- throw createError({
11
- statusCode: 400,
12
- statusMessage: "Cannot specify both cron and delay"
13
- });
14
- }
15
- if (!cron && !delay) {
16
- throw createError({
17
- statusCode: 400,
18
- statusMessage: "Must specify either cron or delay"
19
- });
20
- }
21
- const registry = $useQueueRegistry();
22
- const flow = registry?.flows?.[flowName];
23
- if (!flow || !flow.entry) {
24
- throw createError({ statusCode: 404, statusMessage: `Flow '${flowName}' not found` });
25
- }
26
- const queueName = typeof flow.entry.queue === "string" ? flow.entry.queue : flow.entry.queue?.name || flow.entry.queue;
27
- let queue;
28
- try {
29
- queue = useQueueAdapter();
30
- } catch {
31
- throw createError({
32
- statusCode: 503,
33
- statusMessage: "Server initializing",
34
- data: "Queue adapter not ready yet, please retry"
35
- });
36
- }
37
- const scheduleOpts = {};
38
- if (cron) scheduleOpts.cron = cron;
39
- if (delay) scheduleOpts.delay = delay;
40
- const jobData = {
41
- __scheduledFlowStart: true,
42
- __flowName: flowName,
43
- __flowInput: input || {},
44
- __schedule: {
45
- metadata,
46
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
47
- }
48
- };
49
- const id = await queue.schedule(
50
- queueName,
51
- {
52
- name: flow.entry.step,
53
- data: jobData,
54
- opts: jobId ? { jobId } : void 0
55
- },
56
- scheduleOpts
57
- );
58
- return {
59
- id,
60
- flowName,
61
- queue: queueName,
62
- step: flow.entry.step,
63
- schedule: scheduleOpts,
64
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
65
- };
66
- });
@@ -1,2 +0,0 @@
1
- declare const _default: any;
2
- export default _default;