nvent 0.5.4 → 0.5.6

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 (46) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +127 -23
  3. package/dist/runtime/adapters/builtin/memory-store.d.ts +2 -1
  4. package/dist/runtime/adapters/builtin/memory-store.js +28 -4
  5. package/dist/runtime/adapters/factory.js +8 -7
  6. package/dist/runtime/adapters/interfaces/queue.d.ts +5 -0
  7. package/dist/runtime/adapters/interfaces/store.d.ts +3 -1
  8. package/dist/runtime/config/index.js +14 -1
  9. package/dist/runtime/config/types.d.ts +42 -0
  10. package/dist/runtime/events/types.d.ts +0 -1
  11. package/dist/runtime/events/utils/stallDetector.d.ts +13 -77
  12. package/dist/runtime/events/utils/stallDetector.js +8 -192
  13. package/dist/runtime/events/wiring/flowWiring.js +347 -109
  14. package/dist/runtime/events/wiring/registry.js +9 -1
  15. package/dist/runtime/events/wiring/triggerWiring.js +11 -1
  16. package/dist/runtime/nitro/plugins/02.workers.js +31 -2
  17. package/dist/runtime/nitro/routes/webhook.await.js +28 -6
  18. package/dist/runtime/nitro/routes/webhook.trigger.d.ts +17 -0
  19. package/dist/runtime/nitro/routes/webhook.trigger.js +9 -0
  20. package/dist/runtime/nitro/utils/awaitPatterns/event.js +58 -50
  21. package/dist/runtime/nitro/utils/awaitPatterns/schedule.js +6 -1
  22. package/dist/runtime/nitro/utils/awaitPatterns/time.d.ts +1 -1
  23. package/dist/runtime/nitro/utils/awaitPatterns/time.js +6 -2
  24. package/dist/runtime/nitro/utils/awaitPatterns/webhook.js +53 -45
  25. package/dist/runtime/nitro/utils/defineFunction.d.ts +2 -9
  26. package/dist/runtime/nitro/utils/defineFunction.js +1 -14
  27. package/dist/runtime/nitro/utils/defineFunctionConfig.d.ts +84 -16
  28. package/dist/runtime/nitro/utils/defineHooks.d.ts +64 -10
  29. package/dist/runtime/nitro/utils/defineHooks.js +3 -0
  30. package/dist/runtime/nitro/utils/useAwait.d.ts +12 -0
  31. package/dist/runtime/nitro/utils/useAwait.js +34 -4
  32. package/dist/runtime/nitro/utils/useFlow.d.ts +39 -48
  33. package/dist/runtime/nitro/utils/useFlow.js +53 -14
  34. package/dist/runtime/nitro/utils/useHookRegistry.d.ts +10 -4
  35. package/dist/runtime/nitro/utils/useTrigger.js +7 -16
  36. package/dist/runtime/scheduler/index.js +5 -1
  37. package/dist/runtime/scheduler/scheduler.d.ts +19 -0
  38. package/dist/runtime/scheduler/scheduler.js +184 -8
  39. package/dist/runtime/scheduler/types.d.ts +6 -0
  40. package/dist/runtime/worker/node/runner.d.ts +44 -2
  41. package/dist/runtime/worker/node/runner.js +45 -100
  42. package/dist/runtime/worker/system/awaitHandlers.d.ts +27 -0
  43. package/dist/runtime/worker/system/awaitHandlers.js +230 -0
  44. package/dist/runtime/worker/system/index.d.ts +24 -0
  45. package/dist/runtime/worker/system/index.js +39 -0
  46. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { defineNitroPlugin, $useWorkerHandlers, $useFunctionRegistry, useQueueAdapter, useHookRegistry } from "#imports";
2
2
  import { createJobProcessor } from "../../worker/node/runner.js";
3
+ import { registerSystemHandlersOnQueue } from "../../worker/system/index.js";
3
4
  export default defineNitroPlugin(async (nitroApp) => {
4
5
  nitroApp.hooks.hook("close", async () => {
5
6
  const queueAdapter = useQueueAdapter();
@@ -11,6 +12,7 @@ export default defineNitroPlugin(async (nitroApp) => {
11
12
  const handlers = $useWorkerHandlers();
12
13
  const registry = $useFunctionRegistry() || { workers: [] };
13
14
  const registeredQueues = /* @__PURE__ */ new Set();
15
+ const queuesWithHooks = /* @__PURE__ */ new Set();
14
16
  for (const entry of handlers) {
15
17
  const { queue, id, handler, module } = entry;
16
18
  const w = registry.workers.find((rw) => rw?.id === id || rw?.queue?.name === queue && rw?.absPath === entry.absPath);
@@ -20,7 +22,7 @@ export default defineNitroPlugin(async (nitroApp) => {
20
22
  } else {
21
23
  jobName = id.includes("/") ? id.split("/").pop() : id;
22
24
  }
23
- if (module && w?.flow) {
25
+ if (module) {
24
26
  const hooks = {};
25
27
  if (typeof module.onAwaitRegister === "function") {
26
28
  hooks.onAwaitRegister = module.onAwaitRegister;
@@ -28,7 +30,10 @@ export default defineNitroPlugin(async (nitroApp) => {
28
30
  if (typeof module.onAwaitResolve === "function") {
29
31
  hooks.onAwaitResolve = module.onAwaitResolve;
30
32
  }
31
- if (Object.keys(hooks).length > 0) {
33
+ if (typeof module.onAwaitTimeout === "function") {
34
+ hooks.onAwaitTimeout = module.onAwaitTimeout;
35
+ }
36
+ if (Object.keys(hooks).length > 0 && w?.flow) {
32
37
  const hookRegistry = useHookRegistry();
33
38
  const flowNames = w.flow.names ? Array.isArray(w.flow.names) ? w.flow.names : [w.flow.names] : w.flow.name ? Array.isArray(w.flow.name) ? w.flow.name : [w.flow.name] : [];
34
39
  for (const flowName of flowNames) {
@@ -36,6 +41,20 @@ export default defineNitroPlugin(async (nitroApp) => {
36
41
  hookRegistry.register(flowName, jobName, hooks);
37
42
  }
38
43
  }
44
+ queuesWithHooks.add(queue);
45
+ }
46
+ if (w?.flow?.awaitBefore || w?.flow?.awaitAfter) {
47
+ queuesWithHooks.add(queue);
48
+ }
49
+ if (w?.flow?.role === "entry") {
50
+ const flowNames = w.flow.names ? Array.isArray(w.flow.names) ? w.flow.names : [w.flow.names] : w.flow.name ? Array.isArray(w.flow.name) ? w.flow.name : [w.flow.name] : [];
51
+ for (const flowName of flowNames) {
52
+ const flowRegistry = (registry?.flows || {})[flowName];
53
+ if (flowRegistry?.entry?.awaitBefore || flowRegistry?.entry?.awaitAfter) {
54
+ queuesWithHooks.add(queue);
55
+ break;
56
+ }
57
+ }
39
58
  }
40
59
  }
41
60
  if (typeof handler === "function") {
@@ -52,6 +71,16 @@ export default defineNitroPlugin(async (nitroApp) => {
52
71
  registeredQueues.add(queue);
53
72
  }
54
73
  }
74
+ for (const queueName of queuesWithHooks) {
75
+ try {
76
+ const queueWorker = registry.workers.find((w) => w?.queue?.name === queueName);
77
+ const concurrency = queueWorker?.worker?.concurrency;
78
+ registerSystemHandlersOnQueue(queueName, concurrency);
79
+ registeredQueues.add(queueName);
80
+ } catch (err) {
81
+ console.error(`[nvent] Failed to register system handlers on queue ${queueName}:`, err);
82
+ }
83
+ }
55
84
  if (queueAdapter.startProcessingQueue) {
56
85
  for (const queueName of Array.from(registeredQueues)) {
57
86
  queueAdapter.startProcessingQueue(queueName);
@@ -30,8 +30,8 @@ export default defineEventHandler(async (event) => {
30
30
  });
31
31
  }
32
32
  const status = flowEntry.metadata?.status;
33
- if (status && status !== "running") {
34
- logger.warn(`Flow is not running`, { flowName, runId, stepName, status });
33
+ if (status && status !== "running" && status !== "awaiting") {
34
+ logger.warn(`Flow is not running or awaiting`, { flowName, runId, stepName, status });
35
35
  setResponseStatus(event, 410);
36
36
  throw createError({
37
37
  statusCode: 410,
@@ -39,9 +39,32 @@ export default defineEventHandler(async (event) => {
39
39
  message: `This webhook is no longer valid because the flow is ${status}.`
40
40
  });
41
41
  }
42
- const awaitState = flowEntry.metadata?.awaitingSteps?.[stepName];
43
- if (!awaitState || awaitState.status !== "awaiting") {
44
- logger.warn(`Step is not awaiting`, { flowName, runId, stepName, awaitState });
42
+ const awaitingSteps = flowEntry.metadata?.awaitingSteps || {};
43
+ const awaitKeyBefore = `${stepName}:before`;
44
+ const awaitKeyAfter = `${stepName}:after`;
45
+ let awaitState = null;
46
+ let position = "before";
47
+ const awaitStateBefore = awaitingSteps[awaitKeyBefore];
48
+ if (awaitStateBefore && awaitStateBefore.status === "awaiting") {
49
+ awaitState = awaitStateBefore;
50
+ position = "before";
51
+ }
52
+ if (!awaitState) {
53
+ const awaitStateAfter = awaitingSteps[awaitKeyAfter];
54
+ if (awaitStateAfter && awaitStateAfter.status === "awaiting") {
55
+ awaitState = awaitStateAfter;
56
+ position = "after";
57
+ }
58
+ }
59
+ if (!awaitState) {
60
+ const legacyAwaitState = awaitingSteps[stepName];
61
+ if (legacyAwaitState && legacyAwaitState.status === "awaiting") {
62
+ awaitState = legacyAwaitState;
63
+ position = "after";
64
+ }
65
+ }
66
+ if (!awaitState) {
67
+ logger.warn(`Step is not awaiting`, { flowName, runId, stepName, awaitingSteps });
45
68
  setResponseStatus(event, 410);
46
69
  throw createError({
47
70
  statusCode: 410,
@@ -66,7 +89,6 @@ export default defineEventHandler(async (event) => {
66
89
  message: `This webhook expects ${expectedMethod} requests.`
67
90
  });
68
91
  }
69
- const position = awaitState.position || "after";
70
92
  let webhookData;
71
93
  if (event.method === "GET") {
72
94
  webhookData = getRouterParams(event, { decode: true });
@@ -16,6 +16,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
16
16
  triggerName?: undefined;
17
17
  expectedType?: undefined;
18
18
  actualType?: undefined;
19
+ status?: undefined;
19
20
  expectedMethod?: undefined;
20
21
  actualMethod?: undefined;
21
22
  success?: undefined;
@@ -27,6 +28,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
27
28
  message: string;
28
29
  expectedType?: undefined;
29
30
  actualType?: undefined;
31
+ status?: undefined;
30
32
  expectedMethod?: undefined;
31
33
  actualMethod?: undefined;
32
34
  success?: undefined;
@@ -38,6 +40,19 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
38
40
  expectedType: string;
39
41
  actualType: any;
40
42
  message?: undefined;
43
+ status?: undefined;
44
+ expectedMethod?: undefined;
45
+ actualMethod?: undefined;
46
+ success?: undefined;
47
+ subscribedFlows?: undefined;
48
+ timestamp?: undefined;
49
+ } | {
50
+ error: string;
51
+ triggerName: string;
52
+ status: any;
53
+ message: string;
54
+ expectedType?: undefined;
55
+ actualType?: undefined;
41
56
  expectedMethod?: undefined;
42
57
  actualMethod?: undefined;
43
58
  success?: undefined;
@@ -51,6 +66,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
51
66
  triggerName?: undefined;
52
67
  expectedType?: undefined;
53
68
  actualType?: undefined;
69
+ status?: undefined;
54
70
  success?: undefined;
55
71
  subscribedFlows?: undefined;
56
72
  timestamp?: undefined;
@@ -63,6 +79,7 @@ declare const _default: import("h3").EventHandler<import("h3").EventHandlerReque
63
79
  error?: undefined;
64
80
  expectedType?: undefined;
65
81
  actualType?: undefined;
82
+ status?: undefined;
66
83
  expectedMethod?: undefined;
67
84
  actualMethod?: undefined;
68
85
  }>>;
@@ -30,6 +30,15 @@ export default defineEventHandler(async (event) => {
30
30
  actualType: triggerEntry.type
31
31
  };
32
32
  }
33
+ if (triggerEntry.status !== "active") {
34
+ logger.info(`Trigger '${triggerName}' is ${triggerEntry.status}, rejecting webhook`);
35
+ return {
36
+ error: "Trigger not active",
37
+ triggerName,
38
+ status: triggerEntry.status,
39
+ message: `Trigger '${triggerName}' is ${triggerEntry.status}. Update status to 'active' to enable.`
40
+ };
41
+ }
33
42
  const expectedMethod = triggerEntry.webhook?.method || "POST";
34
43
  if (event.method !== expectedMethod) {
35
44
  logger.warn(`Method mismatch: expected ${expectedMethod}, got ${event.method}`);
@@ -18,6 +18,9 @@ export async function registerEventAwait(runId, stepName, flowName, config, posi
18
18
  await resolveEventAwait(runId, stepName, flowName, position, event.data);
19
19
  unsubscribe();
20
20
  });
21
+ const { useAwaitDefaults } = await import("../useAwait.js");
22
+ const { eventTimeout: defaultTimeout, timeoutAction: defaultTimeoutAction } = useAwaitDefaults();
23
+ const timeoutMs = config.timeout && config.timeout > 0 ? config.timeout : defaultTimeout;
21
24
  eventBus.publish({
22
25
  type: "await.registered",
23
26
  flowName,
@@ -27,66 +30,69 @@ export async function registerEventAwait(runId, stepName, flowName, config, posi
27
30
  position,
28
31
  config,
29
32
  data: {
33
+ position,
34
+ // Store position in data for database persistence
30
35
  eventName: config.event,
31
36
  filterKey: config.filterKey,
32
- timeout: config.timeout,
33
- registeredAt: Date.now()
37
+ timeout: timeoutMs,
38
+ // Store resolved timeout (with default)
39
+ registeredAt: Date.now(),
40
+ timeoutAction: config.timeoutAction || defaultTimeoutAction
34
41
  }
35
42
  });
36
- if (config.timeout && config.timeout > 0) {
37
- const scheduler = useScheduler();
38
- const timeoutAt = Date.now() + config.timeout;
39
- const jobId = `await-event-timeout-${runId}-${stepName}-${position}`;
40
- await scheduler.schedule({
41
- id: jobId,
42
- name: `Event Await Timeout: ${flowName} - ${stepName}`,
43
- type: "one-time",
44
- executeAt: timeoutAt,
45
- handler: async () => {
46
- logger.warn("Event await timeout", {
47
- runId,
48
- stepName,
49
- flowName,
50
- eventName: config.event,
51
- timeout: config.timeout,
52
- timeoutAction: config.timeoutAction || "fail"
53
- });
54
- eventBus.publish({
55
- type: "await.timeout",
56
- flowName,
57
- runId,
58
- stepName,
59
- position,
60
- awaitType: "event",
61
- timeoutAction: config.timeoutAction || "fail",
62
- data: {
63
- eventName: config.event,
64
- timeout: config.timeout,
65
- registeredAt: Date.now() - (config.timeout || 0),
66
- timedOutAt: Date.now()
67
- }
68
- });
69
- unsubscribe();
70
- },
71
- metadata: {
72
- component: "await-pattern",
73
- awaitType: "event",
43
+ const scheduler = useScheduler();
44
+ const timeoutAt = Date.now() + timeoutMs;
45
+ const jobId = `await-event-timeout-${runId}-${stepName}-${position}`;
46
+ await scheduler.schedule({
47
+ id: jobId,
48
+ name: `Event Await Timeout: ${flowName} - ${stepName}`,
49
+ type: "one-time",
50
+ executeAt: timeoutAt,
51
+ handler: async () => {
52
+ logger.warn("Event await timeout", {
74
53
  runId,
75
54
  stepName,
76
55
  flowName,
56
+ eventName: config.event,
57
+ timeout: timeoutMs,
58
+ timeoutAction: config.timeoutAction || "fail"
59
+ });
60
+ eventBus.publish({
61
+ type: "await.timeout",
62
+ flowName,
63
+ runId,
64
+ stepName,
77
65
  position,
78
- timeout: config.timeout,
79
- eventName: config.event
80
- }
81
- });
82
- logger.debug(`Event timeout scheduled`, {
66
+ awaitType: "event",
67
+ timeoutAction: config.timeoutAction || "fail",
68
+ data: {
69
+ eventName: config.event,
70
+ timeout: timeoutMs,
71
+ registeredAt: Date.now() - timeoutMs,
72
+ timedOutAt: Date.now()
73
+ }
74
+ });
75
+ unsubscribe();
76
+ },
77
+ metadata: {
78
+ component: "await-pattern",
79
+ awaitType: "event",
83
80
  runId,
84
81
  stepName,
85
- eventName: config.event,
86
- timeout: config.timeout,
87
- timeoutAction: config.timeoutAction
88
- });
89
- }
82
+ flowName,
83
+ position,
84
+ timeout: timeoutMs,
85
+ eventName: config.event
86
+ }
87
+ });
88
+ logger.debug(`Event timeout scheduled`, {
89
+ runId,
90
+ stepName,
91
+ eventName: config.event,
92
+ timeout: timeoutMs,
93
+ timeoutAction: config.timeoutAction,
94
+ isDefault: !config.timeout || config.timeout <= 0
95
+ });
90
96
  logger.debug(`Event await registered: ${config.event}`, { runId, stepName });
91
97
  return {
92
98
  eventName: config.event,
@@ -113,6 +119,8 @@ export async function resolveEventAwait(runId, stepName, flowName, position, eve
113
119
  position,
114
120
  triggerData: eventData,
115
121
  data: {
122
+ position,
123
+ // Store position in data for database persistence
116
124
  resolvedAt: Date.now()
117
125
  }
118
126
  });
@@ -43,6 +43,8 @@ export async function registerScheduleAwait(runId, stepName, flowName, config, p
43
43
  position,
44
44
  config,
45
45
  data: {
46
+ position,
47
+ // Store position in data for database persistence
46
48
  cron: config.cron,
47
49
  nextOccurrence,
48
50
  timeUntilNext,
@@ -63,14 +65,17 @@ export async function resolveScheduleAwait(runId, stepName, flowName, position,
63
65
  const logger = useNventLogger("await-schedule");
64
66
  const eventBus = getEventBus();
65
67
  logger.info(`Resolving schedule await`, { runId, stepName });
68
+ const scheduledAt = scheduleData?.scheduledAt || Date.now();
66
69
  eventBus.publish({
67
70
  type: "await.resolved",
68
71
  flowName,
69
72
  runId,
70
73
  stepName,
71
74
  position,
72
- triggerData: scheduleData,
75
+ triggerData: { scheduledAt },
73
76
  data: {
77
+ position,
78
+ // Store position in data for database persistence
74
79
  resolvedAt: Date.now()
75
80
  }
76
81
  });
@@ -12,4 +12,4 @@ export declare function registerTimeAwait(runId: string, stepName: string, flowN
12
12
  /**
13
13
  * Resolve time await when delay completes
14
14
  */
15
- export declare function resolveTimeAwait(runId: string, stepName: string, flowName: string, position: 'before' | 'after', timeData: any): Promise<void>;
15
+ export declare function resolveTimeAwait(runId: string, stepName: string, flowName: string, position: 'before' | 'after', _timeData: any): Promise<void>;
@@ -37,6 +37,8 @@ export async function registerTimeAwait(runId, stepName, flowName, config, posit
37
37
  position,
38
38
  config,
39
39
  data: {
40
+ position,
41
+ // Store position in data for database persistence
40
42
  delay: config.delay,
41
43
  resolveAt,
42
44
  registeredAt: Date.now()
@@ -48,7 +50,7 @@ export async function registerTimeAwait(runId, stepName, flowName, config, posit
48
50
  resolveAt
49
51
  };
50
52
  }
51
- export async function resolveTimeAwait(runId, stepName, flowName, position, timeData) {
53
+ export async function resolveTimeAwait(runId, stepName, flowName, position, _timeData) {
52
54
  const logger = useNventLogger("await-time");
53
55
  const eventBus = getEventBus();
54
56
  logger.info(`Resolving time await`, { runId, stepName });
@@ -58,8 +60,10 @@ export async function resolveTimeAwait(runId, stepName, flowName, position, time
58
60
  runId,
59
61
  stepName,
60
62
  position,
61
- triggerData: timeData,
63
+ triggerData: {},
62
64
  data: {
65
+ position,
66
+ // Store position in data for database persistence
63
67
  resolvedAt: Date.now()
64
68
  }
65
69
  });
@@ -22,6 +22,9 @@ export async function registerWebhookAwait(runId, stepName, flowName, config, po
22
22
  const webhookPath = `/api/_webhook/await${path}`;
23
23
  const fullWebhookUrl = `${baseUrl.replace(/\/$/, "")}${webhookPath}`;
24
24
  logger.info(`Registering webhook await: ${fullWebhookUrl}`, { runId, stepName });
25
+ const { useAwaitDefaults } = await import("../useAwait.js");
26
+ const { webhookTimeout: defaultTimeout, timeoutAction: defaultTimeoutAction } = useAwaitDefaults();
27
+ const timeoutMs = config.timeout && config.timeout > 0 ? config.timeout : defaultTimeout;
25
28
  eventBus.publish({
26
29
  type: "await.registered",
27
30
  flowName,
@@ -31,62 +34,65 @@ export async function registerWebhookAwait(runId, stepName, flowName, config, po
31
34
  position,
32
35
  config,
33
36
  data: {
37
+ position,
38
+ // Store position in data for database persistence
34
39
  path,
35
40
  method: config.method || "POST",
36
- timeout: config.timeout,
41
+ timeout: timeoutMs,
42
+ // Store resolved timeout (with default)
37
43
  registeredAt: Date.now(),
38
- webhookUrl: fullWebhookUrl
44
+ webhookUrl: fullWebhookUrl,
45
+ timeoutAction: config.timeoutAction || defaultTimeoutAction
39
46
  }
40
47
  });
41
- if (config.timeout && config.timeout > 0) {
42
- const scheduler = useScheduler();
43
- const timeoutAt = Date.now() + config.timeout;
44
- const jobId = `await-webhook-timeout-${runId}-${stepName}-${position}`;
45
- await scheduler.schedule({
46
- id: jobId,
47
- name: `Webhook Timeout: ${flowName} - ${stepName}`,
48
- type: "one-time",
49
- executeAt: timeoutAt,
50
- handler: async () => {
51
- logger.warn("Webhook await timeout", {
52
- runId,
53
- stepName,
54
- flowName,
55
- timeout: config.timeout,
56
- timeoutAction: config.timeoutAction || "fail"
57
- });
58
- eventBus.publish({
59
- type: "await.timeout",
60
- flowName,
61
- runId,
62
- stepName,
63
- position,
64
- awaitType: "webhook",
65
- timeoutAction: config.timeoutAction || "fail",
66
- data: {
67
- timeout: config.timeout,
68
- registeredAt: Date.now() - (config.timeout || 0),
69
- timedOutAt: Date.now()
70
- }
71
- });
72
- },
73
- metadata: {
74
- component: "await-pattern",
75
- awaitType: "webhook",
48
+ const scheduler = useScheduler();
49
+ const timeoutAt = Date.now() + timeoutMs;
50
+ const jobId = `await-webhook-timeout-${runId}-${stepName}-${position}`;
51
+ await scheduler.schedule({
52
+ id: jobId,
53
+ name: `Webhook Timeout: ${flowName} - ${stepName}`,
54
+ type: "one-time",
55
+ executeAt: timeoutAt,
56
+ handler: async () => {
57
+ logger.warn("Webhook await timeout", {
76
58
  runId,
77
59
  stepName,
78
60
  flowName,
61
+ timeout: timeoutMs,
62
+ timeoutAction: config.timeoutAction || "fail"
63
+ });
64
+ eventBus.publish({
65
+ type: "await.timeout",
66
+ flowName,
67
+ runId,
68
+ stepName,
79
69
  position,
80
- timeout: config.timeout
81
- }
82
- });
83
- logger.debug(`Webhook timeout scheduled`, {
70
+ awaitType: "webhook",
71
+ timeoutAction: config.timeoutAction || "fail",
72
+ data: {
73
+ timeout: timeoutMs,
74
+ registeredAt: Date.now() - timeoutMs,
75
+ timedOutAt: Date.now()
76
+ }
77
+ });
78
+ },
79
+ metadata: {
80
+ component: "await-pattern",
81
+ awaitType: "webhook",
84
82
  runId,
85
83
  stepName,
86
- timeout: config.timeout,
87
- timeoutAction: config.timeoutAction
88
- });
89
- }
84
+ flowName,
85
+ position,
86
+ timeout: timeoutMs
87
+ }
88
+ });
89
+ logger.debug(`Webhook timeout scheduled`, {
90
+ runId,
91
+ stepName,
92
+ timeout: timeoutMs,
93
+ timeoutAction: config.timeoutAction,
94
+ isDefault: !config.timeout || config.timeout <= 0
95
+ });
90
96
  logger.debug(`Webhook await registered: ${fullWebhookUrl}`, { runId, stepName });
91
97
  return {
92
98
  webhookUrl: fullWebhookUrl,
@@ -113,6 +119,8 @@ export async function resolveWebhookAwait(runId, stepName, flowName, position, w
113
119
  position,
114
120
  triggerData: webhookData,
115
121
  data: {
122
+ position,
123
+ // Store position in data for database persistence
116
124
  resolvedAt: Date.now()
117
125
  }
118
126
  });
@@ -1,10 +1,3 @@
1
- import { useFlow, useQueueAdapter } from '#imports';
2
- import type { RunContext, NodeHandler } from '../worker/node/runner.js';
3
- export type ExtendedRunContext = RunContext & {
4
- provider: ReturnType<typeof useQueueAdapter>;
5
- flow: ReturnType<typeof useFlow>;
6
- registry: any;
7
- };
8
- export type DefineFunction = (handler: (input: any, ctx: ExtendedRunContext) => Promise<any>) => NodeHandler;
9
- export declare const defineFunction: DefineFunction;
1
+ import type { RunContext, NodeHandler } from '../../worker/node/runner.js';
2
+ export declare const defineFunction: <TInput = any, TOutput = any>(handler: (input: TInput, ctx: RunContext) => Promise<TOutput>) => NodeHandler;
10
3
  export default defineFunction;
@@ -1,17 +1,4 @@
1
- import { $useFunctionRegistry, useFlow, useQueueAdapter } from "#imports";
2
1
  export const defineFunction = (handler) => {
3
- const wrapped = async (input, ctx) => {
4
- const provider = useQueueAdapter();
5
- const flow = ctx.flow || useFlow();
6
- const registry = $useFunctionRegistry();
7
- const extended = {
8
- ...ctx,
9
- provider,
10
- flow,
11
- registry
12
- };
13
- return handler(input, extended);
14
- };
15
- return wrapped;
2
+ return handler;
16
3
  };
17
4
  export default defineFunction;