ai-workflows 2.1.1 → 2.3.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -1
- package/README.md +305 -184
- package/dist/barrier.d.ts +159 -0
- package/dist/barrier.d.ts.map +1 -0
- package/dist/barrier.js +377 -0
- package/dist/barrier.js.map +1 -0
- package/dist/cascade-context.d.ts +149 -0
- package/dist/cascade-context.d.ts.map +1 -0
- package/dist/cascade-context.js +324 -0
- package/dist/cascade-context.js.map +1 -0
- package/dist/cascade-executor.d.ts +196 -0
- package/dist/cascade-executor.d.ts.map +1 -0
- package/dist/cascade-executor.js +384 -0
- package/dist/cascade-executor.js.map +1 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +27 -8
- package/dist/context.js.map +1 -1
- package/dist/cron-parser.d.ts +65 -0
- package/dist/cron-parser.d.ts.map +1 -0
- package/dist/cron-parser.js +294 -0
- package/dist/cron-parser.js.map +1 -0
- package/dist/cron-scheduler.d.ts +117 -0
- package/dist/cron-scheduler.d.ts.map +1 -0
- package/dist/cron-scheduler.js +176 -0
- package/dist/cron-scheduler.js.map +1 -0
- package/dist/database-context.d.ts +184 -0
- package/dist/database-context.d.ts.map +1 -0
- package/dist/database-context.js +428 -0
- package/dist/database-context.js.map +1 -0
- package/dist/dependency-graph.d.ts +157 -0
- package/dist/dependency-graph.d.ts.map +1 -0
- package/dist/dependency-graph.js +382 -0
- package/dist/dependency-graph.js.map +1 -0
- package/dist/digital-objects-adapter.d.ts +159 -0
- package/dist/digital-objects-adapter.d.ts.map +1 -0
- package/dist/digital-objects-adapter.js +229 -0
- package/dist/digital-objects-adapter.js.map +1 -0
- package/dist/durable-execution-cloudflare.d.ts +427 -0
- package/dist/durable-execution-cloudflare.d.ts.map +1 -0
- package/dist/durable-execution-cloudflare.js +510 -0
- package/dist/durable-execution-cloudflare.js.map +1 -0
- package/dist/durable-execution.d.ts +482 -0
- package/dist/durable-execution.d.ts.map +1 -0
- package/dist/durable-execution.js +594 -0
- package/dist/durable-execution.js.map +1 -0
- package/dist/durable-workflow.d.ts +176 -0
- package/dist/durable-workflow.d.ts.map +1 -0
- package/dist/durable-workflow.js +552 -0
- package/dist/durable-workflow.js.map +1 -0
- package/dist/every.d.ts +31 -2
- package/dist/every.d.ts.map +1 -1
- package/dist/every.js +63 -32
- package/dist/every.js.map +1 -1
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +8 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/topological-sort.d.ts +121 -0
- package/dist/graph/topological-sort.d.ts.map +1 -0
- package/dist/graph/topological-sort.js +292 -0
- package/dist/graph/topological-sort.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +101 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +115 -0
- package/dist/logger.js.map +1 -0
- package/dist/on.d.ts +35 -10
- package/dist/on.d.ts.map +1 -1
- package/dist/on.js +53 -19
- package/dist/on.js.map +1 -1
- package/dist/runtime.d.ts +169 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +275 -0
- package/dist/runtime.js.map +1 -0
- package/dist/send.d.ts.map +1 -1
- package/dist/send.js +4 -3
- package/dist/send.js.map +1 -1
- package/dist/telemetry.d.ts +150 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +388 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/timer-registry.d.ts +77 -0
- package/dist/timer-registry.d.ts.map +1 -0
- package/dist/timer-registry.js +154 -0
- package/dist/timer-registry.js.map +1 -0
- package/dist/types.d.ts +105 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -1
- package/dist/types.js.map +1 -1
- package/dist/worker/durable-step.d.ts +481 -0
- package/dist/worker/durable-step.d.ts.map +1 -0
- package/dist/worker/durable-step.js +606 -0
- package/dist/worker/durable-step.js.map +1 -0
- package/dist/worker/index.d.ts +106 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +124 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/state-adapter.d.ts +230 -0
- package/dist/worker/state-adapter.d.ts.map +1 -0
- package/dist/worker/state-adapter.js +409 -0
- package/dist/worker/state-adapter.js.map +1 -0
- package/dist/worker/topological-executor.d.ts +282 -0
- package/dist/worker/topological-executor.d.ts.map +1 -0
- package/dist/worker/topological-executor.js +396 -0
- package/dist/worker/topological-executor.js.map +1 -0
- package/dist/worker/workflow-builder.d.ts +286 -0
- package/dist/worker/workflow-builder.d.ts.map +1 -0
- package/dist/worker/workflow-builder.js +565 -0
- package/dist/worker/workflow-builder.js.map +1 -0
- package/dist/worker.d.ts +800 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +2428 -0
- package/dist/worker.js.map +1 -0
- package/dist/workflow-builder.d.ts +287 -0
- package/dist/workflow-builder.d.ts.map +1 -0
- package/dist/workflow-builder.js +762 -0
- package/dist/workflow-builder.js.map +1 -0
- package/dist/workflow.d.ts +14 -30
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +136 -292
- package/dist/workflow.js.map +1 -1
- package/examples/01-ecommerce-order-pipeline.ts +358 -0
- package/examples/02-content-moderation-cascade.ts +454 -0
- package/examples/03-scheduled-reporting-dependencies.ts +479 -0
- package/examples/04-database-persistence.ts +518 -0
- package/examples/README.md +173 -0
- package/package.json +21 -4
- package/src/__tests__/digital-objects-adapter.test.ts +274 -0
- package/src/__tests__/durable-workflow.test.ts +297 -0
- package/src/barrier.ts +507 -0
- package/src/cascade-context.ts +495 -0
- package/src/cascade-executor.ts +588 -0
- package/src/context.ts +51 -17
- package/src/cron-parser.ts +347 -0
- package/src/cron-scheduler.ts +239 -0
- package/src/database-context.ts +658 -0
- package/src/dependency-graph.ts +518 -0
- package/src/digital-objects-adapter.ts +351 -0
- package/src/durable-execution-cloudflare.ts +855 -0
- package/src/durable-execution.ts +1042 -0
- package/src/durable-workflow.ts +717 -0
- package/src/every.ts +104 -35
- package/src/graph/index.ts +19 -0
- package/src/graph/topological-sort.ts +412 -0
- package/src/index.ts +147 -0
- package/src/logger.ts +148 -0
- package/src/on.ts +81 -26
- package/src/runtime.ts +436 -0
- package/src/send.ts +4 -5
- package/src/telemetry.ts +577 -0
- package/src/timer-registry.ts +179 -0
- package/src/types.ts +146 -10
- package/src/worker/durable-step.ts +976 -0
- package/src/worker/index.ts +216 -0
- package/src/worker/state-adapter.ts +589 -0
- package/src/worker/topological-executor.ts +625 -0
- package/src/worker/workflow-builder.ts +871 -0
- package/src/worker.ts +2906 -0
- package/src/workflow-builder.ts +1068 -0
- package/src/workflow.ts +199 -355
- package/test/barrier-join.test.ts +442 -0
- package/test/barrier-unhandled-rejections.test.ts +359 -0
- package/test/cascade-context.test.ts +390 -0
- package/test/cascade-executor.test.ts +852 -0
- package/test/cron-parser.test.ts +314 -0
- package/test/cron-scheduler.test.ts +291 -0
- package/test/database-context.test.ts +770 -0
- package/test/db-provider-adapter.test.ts +862 -0
- package/test/dependency-graph.test.ts +512 -0
- package/test/durable-execution-cloudflare.test.ts +606 -0
- package/test/durable-execution-in-process.test.ts +286 -0
- package/test/durable-execution.test.ts +247 -0
- package/test/e2e/workflow-scenarios.e2e.test.ts +1039 -0
- package/test/graph/topological-sort.test.ts +586 -0
- package/test/integration.test.ts +442 -0
- package/test/rpc-surface.test.ts +946 -0
- package/test/runtime.test.ts +262 -0
- package/test/schedule-timer-cleanup.test.ts +353 -0
- package/test/send-race-conditions.test.ts +400 -0
- package/test/type-safety-every.test.ts +303 -0
- package/test/worker/durable-cascade.test.ts +1117 -0
- package/test/worker/durable-step.test.ts +723 -0
- package/test/worker/topological-executor.test.ts +1240 -0
- package/test/worker/workflow-builder.test.ts +1067 -0
- package/test/worker.test.ts +608 -0
- package/test/workflow-builder.test.ts +1670 -0
- package/test/workflow-cron.test.ts +256 -0
- package/test/workflow-state-adapter.test.ts +923 -0
- package/test/workflow.test.ts +25 -22
- package/tsconfig.json +3 -1
- package/vitest.config.ts +38 -1
- package/vitest.workers.config.ts +44 -0
- package/wrangler.jsonc +22 -0
- package/.turbo/turbo-test.log +0 -7
- package/src/context.js +0 -83
- package/src/every.js +0 -267
- package/src/index.js +0 -71
- package/src/on.js +0 -79
- package/src/send.js +0 -111
- package/src/types.js +0 -4
- package/src/workflow.js +0 -455
- package/test/context.test.js +0 -116
- package/test/every.test.js +0 -282
- package/test/on.test.js +0 -80
- package/test/send.test.js +0 -89
- package/test/workflow.test.js +0 -224
- package/vitest.config.js +0 -7
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global timer registry for workflow timers
|
|
3
|
+
*
|
|
4
|
+
* This module tracks all active timers across workflows to enable:
|
|
5
|
+
* - Timer cleanup when workflows are destroyed
|
|
6
|
+
* - Global timer count for debugging
|
|
7
|
+
* - Process exit cleanup
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface TimerEntry {
|
|
11
|
+
timerId: NodeJS.Timeout
|
|
12
|
+
workflowId: string
|
|
13
|
+
registeredAt: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Global registry of active timers
|
|
18
|
+
*/
|
|
19
|
+
const activeTimers: Map<string, TimerEntry> = new Map()
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Counter for generating unique timer IDs
|
|
23
|
+
*/
|
|
24
|
+
let timerCounter = 0
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generate a unique timer ID
|
|
28
|
+
*/
|
|
29
|
+
function generateTimerId(workflowId: string): string {
|
|
30
|
+
return `${workflowId}-timer-${++timerCounter}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Register a timer in the global registry
|
|
35
|
+
*/
|
|
36
|
+
export function registerTimer(workflowId: string, timerId: NodeJS.Timeout): string {
|
|
37
|
+
const id = generateTimerId(workflowId)
|
|
38
|
+
activeTimers.set(id, {
|
|
39
|
+
timerId,
|
|
40
|
+
workflowId,
|
|
41
|
+
registeredAt: Date.now(),
|
|
42
|
+
})
|
|
43
|
+
return id
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Unregister a timer from the global registry
|
|
48
|
+
*/
|
|
49
|
+
export function unregisterTimer(id: string): boolean {
|
|
50
|
+
const entry = activeTimers.get(id)
|
|
51
|
+
if (entry) {
|
|
52
|
+
clearInterval(entry.timerId)
|
|
53
|
+
activeTimers.delete(id)
|
|
54
|
+
return true
|
|
55
|
+
}
|
|
56
|
+
return false
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get all timer IDs for a specific workflow
|
|
61
|
+
*/
|
|
62
|
+
export function getTimerIdsForWorkflow(workflowId: string): string[] {
|
|
63
|
+
const ids: string[] = []
|
|
64
|
+
for (const [id, entry] of activeTimers) {
|
|
65
|
+
if (entry.workflowId === workflowId) {
|
|
66
|
+
ids.push(id)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return ids
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Clear all timers for a specific workflow
|
|
74
|
+
*/
|
|
75
|
+
export function clearTimersForWorkflow(workflowId: string): number {
|
|
76
|
+
const ids = getTimerIdsForWorkflow(workflowId)
|
|
77
|
+
for (const id of ids) {
|
|
78
|
+
unregisterTimer(id)
|
|
79
|
+
}
|
|
80
|
+
return ids.length
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the count of all active timers
|
|
85
|
+
*/
|
|
86
|
+
export function getActiveTimerCount(): number {
|
|
87
|
+
return activeTimers.size
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Clear all timers from all workflows
|
|
92
|
+
*/
|
|
93
|
+
export function clearAllTimers(): void {
|
|
94
|
+
for (const [id, entry] of activeTimers) {
|
|
95
|
+
clearInterval(entry.timerId)
|
|
96
|
+
activeTimers.delete(id)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Timer registry object for external access
|
|
102
|
+
*/
|
|
103
|
+
export const timerRegistry = {
|
|
104
|
+
register: registerTimer,
|
|
105
|
+
unregister: unregisterTimer,
|
|
106
|
+
getTimerIdsForWorkflow,
|
|
107
|
+
clearForWorkflow: clearTimersForWorkflow,
|
|
108
|
+
getActiveCount: getActiveTimerCount,
|
|
109
|
+
clearAll: clearAllTimers,
|
|
110
|
+
getAll: () => Array.from(activeTimers.entries()),
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Global registration is opt-in to avoid namespace pollution
|
|
114
|
+
declare const global: typeof globalThis
|
|
115
|
+
|
|
116
|
+
let globalRegistrationEnabled = false
|
|
117
|
+
|
|
118
|
+
function registerGlobalFunctions(target: typeof globalThis) {
|
|
119
|
+
;(target as unknown as Record<string, unknown>)['getActiveWorkflowTimerCount'] =
|
|
120
|
+
getActiveTimerCount
|
|
121
|
+
;(target as unknown as Record<string, unknown>)['clearAllWorkflowTimers'] = clearAllTimers
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Enable global timer registry functions.
|
|
126
|
+
*
|
|
127
|
+
* This opt-in function registers `getActiveWorkflowTimerCount` and `clearAllWorkflowTimers`
|
|
128
|
+
* on the global scope for debugging and cleanup purposes.
|
|
129
|
+
*
|
|
130
|
+
* Call this function explicitly if you need global access to timer management:
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* import { enableGlobalTimerRegistry } from 'ai-workflows'
|
|
135
|
+
*
|
|
136
|
+
* // Enable global registration
|
|
137
|
+
* enableGlobalTimerRegistry()
|
|
138
|
+
*
|
|
139
|
+
* // Now these are available globally:
|
|
140
|
+
* // globalThis.getActiveWorkflowTimerCount()
|
|
141
|
+
* // globalThis.clearAllWorkflowTimers()
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export function enableGlobalTimerRegistry(): void {
|
|
145
|
+
if (globalRegistrationEnabled) return
|
|
146
|
+
globalRegistrationEnabled = true
|
|
147
|
+
|
|
148
|
+
// Register on globalThis (standard)
|
|
149
|
+
if (typeof globalThis !== 'undefined') {
|
|
150
|
+
registerGlobalFunctions(globalThis)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Also register on global (Node.js specific, used in some test environments)
|
|
154
|
+
if (typeof global !== 'undefined' && global !== globalThis) {
|
|
155
|
+
registerGlobalFunctions(global)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Check if global timer registry is enabled
|
|
161
|
+
*/
|
|
162
|
+
export function isGlobalTimerRegistryEnabled(): boolean {
|
|
163
|
+
return globalRegistrationEnabled
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Register process exit handlers for cleanup
|
|
167
|
+
let cleanupRegistered = false
|
|
168
|
+
|
|
169
|
+
export function registerProcessCleanup(): void {
|
|
170
|
+
if (cleanupRegistered) return
|
|
171
|
+
cleanupRegistered = true
|
|
172
|
+
|
|
173
|
+
const cleanup = () => {
|
|
174
|
+
clearAllTimers()
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
process.on('exit', cleanup)
|
|
178
|
+
process.on('beforeExit', cleanup)
|
|
179
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Types for ai-workflows
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { WorkflowContextType } from '@org.ai/types'
|
|
6
|
+
|
|
5
7
|
/**
|
|
6
8
|
* Handler function with source code for remote execution
|
|
7
9
|
*/
|
|
8
10
|
export interface HandlerFunction<T = unknown> {
|
|
9
11
|
/** The actual function */
|
|
10
|
-
fn: (...args:
|
|
12
|
+
fn: (...args: unknown[]) => void | Promise<void>
|
|
11
13
|
/** Source code string for remote execution */
|
|
12
14
|
source: string
|
|
13
15
|
/** Handler name (for debugging) */
|
|
@@ -21,6 +23,9 @@ export interface HandlerFunction<T = unknown> {
|
|
|
21
23
|
* Generic order follows Promise<T> convention:
|
|
22
24
|
* - TOutput (first) is what the handler returns
|
|
23
25
|
* - TInput (second) is what the handler receives
|
|
26
|
+
*
|
|
27
|
+
* Note: Uses WorkflowContext (extends WorkflowContextType from @org.ai/types)
|
|
28
|
+
* for workflow-specific features like OnProxy, EveryProxy, getState, log.
|
|
24
29
|
*/
|
|
25
30
|
export type EventHandler<TOutput = unknown, TInput = unknown> = (
|
|
26
31
|
data: TInput,
|
|
@@ -30,19 +35,25 @@ export type EventHandler<TOutput = unknown, TInput = unknown> = (
|
|
|
30
35
|
/**
|
|
31
36
|
* Schedule handler function type
|
|
32
37
|
*/
|
|
33
|
-
export type ScheduleHandler = (
|
|
34
|
-
$: WorkflowContext
|
|
35
|
-
) => void | Promise<void>
|
|
38
|
+
export type ScheduleHandler = ($: WorkflowContext) => void | Promise<void>
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
|
-
* Workflow context ($) passed to handlers
|
|
41
|
+
* Workflow context ($) passed to handlers.
|
|
42
|
+
* Extends WorkflowContextType from @org.ai/types with workflow-specific features.
|
|
39
43
|
*/
|
|
40
|
-
export interface WorkflowContext {
|
|
44
|
+
export interface WorkflowContext extends WorkflowContextType {
|
|
41
45
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
46
|
+
* Track an event (fire and forget)
|
|
47
|
+
* Best effort, no confirmation, swallows errors
|
|
48
|
+
* Use for telemetry and non-critical events
|
|
44
49
|
*/
|
|
45
|
-
|
|
50
|
+
track: (event: string, data: unknown) => void
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Send an event (durable)
|
|
54
|
+
* Guaranteed delivery, returns trackable EventId
|
|
55
|
+
*/
|
|
56
|
+
send: <T = unknown>(event: string, data: T) => string
|
|
46
57
|
|
|
47
58
|
/**
|
|
48
59
|
* Do an action (durable, waits for result)
|
|
@@ -245,7 +256,62 @@ export type EveryProxy = {
|
|
|
245
256
|
weeks: (value: number) => (handler: ScheduleHandler) => void
|
|
246
257
|
|
|
247
258
|
// Index signature for dynamic patterns
|
|
248
|
-
[key: string]:
|
|
259
|
+
[key: string]:
|
|
260
|
+
| ((handler: ScheduleHandler) => void)
|
|
261
|
+
| ((value: number) => (handler: ScheduleHandler) => void)
|
|
262
|
+
| DayScheduleProxy
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Callable target type for EveryProxy
|
|
267
|
+
* Used as a properly-typed Proxy target that supports both call and property access
|
|
268
|
+
*/
|
|
269
|
+
export type EveryProxyTarget = {
|
|
270
|
+
(description: string, handler: ScheduleHandler): void
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* ProxyHandler type for OnProxy
|
|
275
|
+
* Provides proper typing for the two-level noun.event proxy pattern
|
|
276
|
+
*/
|
|
277
|
+
export interface OnProxyHandler extends ProxyHandler<Record<string, NounEventProxy>> {
|
|
278
|
+
get(target: Record<string, NounEventProxy>, noun: string, receiver: unknown): NounEventProxy
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* ProxyHandler type for the inner noun level (event accessors)
|
|
283
|
+
*/
|
|
284
|
+
export interface NounEventProxyHandler
|
|
285
|
+
extends ProxyHandler<
|
|
286
|
+
Record<string, (handler: EventHandler, dependencies?: DependencyConfig) => void>
|
|
287
|
+
> {
|
|
288
|
+
get(
|
|
289
|
+
target: Record<string, (handler: EventHandler, dependencies?: DependencyConfig) => void>,
|
|
290
|
+
event: string,
|
|
291
|
+
receiver: unknown
|
|
292
|
+
): (handler: EventHandler, dependencies?: DependencyConfig) => void
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* ProxyHandler type for EveryProxy
|
|
297
|
+
* Handles both function calls and property access for schedule patterns
|
|
298
|
+
*/
|
|
299
|
+
export interface EveryProxyHandler extends ProxyHandler<EveryProxyTarget> {
|
|
300
|
+
get(target: EveryProxyTarget, prop: string, receiver: unknown): unknown
|
|
301
|
+
apply(target: EveryProxyTarget, thisArg: unknown, args: [string, ScheduleHandler]): void
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* ProxyHandler type for day schedule patterns with time modifiers
|
|
306
|
+
* Handles $.every.Monday.at9am pattern
|
|
307
|
+
*/
|
|
308
|
+
export interface DayScheduleProxyHandler extends ProxyHandler<(handler: ScheduleHandler) => void> {
|
|
309
|
+
get(
|
|
310
|
+
target: (handler: ScheduleHandler) => void,
|
|
311
|
+
timeKey: string,
|
|
312
|
+
receiver: unknown
|
|
313
|
+
): ((handler: ScheduleHandler) => void) | undefined
|
|
314
|
+
apply(target: (handler: ScheduleHandler) => void, thisArg: unknown, args: [ScheduleHandler]): void
|
|
249
315
|
}
|
|
250
316
|
|
|
251
317
|
/**
|
|
@@ -270,6 +336,30 @@ export interface WorkflowHistoryEntry {
|
|
|
270
336
|
data?: unknown
|
|
271
337
|
}
|
|
272
338
|
|
|
339
|
+
/**
|
|
340
|
+
* Dependency type: hard (must succeed) or soft (can proceed on failure)
|
|
341
|
+
*/
|
|
342
|
+
export type DependencyType = 'hard' | 'soft'
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Configuration for step dependencies
|
|
346
|
+
*/
|
|
347
|
+
export interface DependencyConfig {
|
|
348
|
+
/**
|
|
349
|
+
* Step(s) that must complete before this step runs
|
|
350
|
+
* Can be a single step ID or array of step IDs
|
|
351
|
+
* Format: 'Noun.event' (e.g., 'Step1.complete')
|
|
352
|
+
*/
|
|
353
|
+
dependsOn: string | string[]
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Type of dependency (default: 'hard')
|
|
357
|
+
* - 'hard': Dependency must complete successfully
|
|
358
|
+
* - 'soft': Step can proceed even if dependency fails
|
|
359
|
+
*/
|
|
360
|
+
type?: DependencyType
|
|
361
|
+
}
|
|
362
|
+
|
|
273
363
|
/**
|
|
274
364
|
* Event registration with source
|
|
275
365
|
*/
|
|
@@ -278,6 +368,8 @@ export interface EventRegistration {
|
|
|
278
368
|
event: string
|
|
279
369
|
handler: EventHandler
|
|
280
370
|
source: string
|
|
371
|
+
/** Optional dependency configuration for workflow step ordering */
|
|
372
|
+
dependencies?: DependencyConfig
|
|
281
373
|
}
|
|
282
374
|
|
|
283
375
|
/**
|
|
@@ -289,6 +381,50 @@ export interface ScheduleRegistration {
|
|
|
289
381
|
source: string
|
|
290
382
|
}
|
|
291
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Time-based interval types (singular form)
|
|
386
|
+
* Used as discriminant values in ScheduleInterval
|
|
387
|
+
*/
|
|
388
|
+
export type TimeIntervalType = 'second' | 'minute' | 'hour' | 'day' | 'week'
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Mapping from plural unit names to their singular interval types
|
|
392
|
+
* Used for type-safe conversion in every.units(value) patterns
|
|
393
|
+
*/
|
|
394
|
+
export type PluralUnitMapping = {
|
|
395
|
+
seconds: 'second'
|
|
396
|
+
minutes: 'minute'
|
|
397
|
+
hours: 'hour'
|
|
398
|
+
days: 'day'
|
|
399
|
+
weeks: 'week'
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Plural unit keys
|
|
404
|
+
*/
|
|
405
|
+
export type PluralUnitKey = keyof PluralUnitMapping
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Type guard to check if a string is a valid plural unit key
|
|
409
|
+
*/
|
|
410
|
+
export function isPluralUnitKey(key: string): key is PluralUnitKey {
|
|
411
|
+
return (
|
|
412
|
+
key === 'seconds' || key === 'minutes' || key === 'hours' || key === 'days' || key === 'weeks'
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Constant mapping object with strict typing
|
|
418
|
+
* Maps plural forms to their singular interval type values
|
|
419
|
+
*/
|
|
420
|
+
export const PLURAL_UNITS: Readonly<PluralUnitMapping> = {
|
|
421
|
+
seconds: 'second',
|
|
422
|
+
minutes: 'minute',
|
|
423
|
+
hours: 'hour',
|
|
424
|
+
days: 'day',
|
|
425
|
+
weeks: 'week',
|
|
426
|
+
} as const
|
|
427
|
+
|
|
292
428
|
/**
|
|
293
429
|
* Schedule intervals
|
|
294
430
|
*/
|