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
package/src/index.ts
CHANGED
|
@@ -63,6 +63,18 @@
|
|
|
63
63
|
// Main Workflow API
|
|
64
64
|
export { Workflow, createTestContext, parseEvent, type WorkflowInstance } from './workflow.js'
|
|
65
65
|
|
|
66
|
+
// WorkflowRuntime - single owner of the `$` runtime contract
|
|
67
|
+
// (composes cascade-context, database-context, on/send/every internally).
|
|
68
|
+
// New callers should reach for createWorkflowRuntime() to understand exactly
|
|
69
|
+
// what `$` contains end-to-end. The Workflow() function wraps a runtime with
|
|
70
|
+
// schedule/timer lifecycle; for tests, runtime.dispatch() is the canonical
|
|
71
|
+
// surface.
|
|
72
|
+
export {
|
|
73
|
+
createWorkflowRuntime,
|
|
74
|
+
type WorkflowRuntime,
|
|
75
|
+
type WorkflowRuntimeOptions,
|
|
76
|
+
} from './runtime.js'
|
|
77
|
+
|
|
66
78
|
// Standalone event handling (for global registration)
|
|
67
79
|
export { on, registerEventHandler, getEventHandlers, clearEventHandlers } from './on.js'
|
|
68
80
|
|
|
@@ -84,6 +96,139 @@ export { send, getEventBus } from './send.js'
|
|
|
84
96
|
// Context
|
|
85
97
|
export { createWorkflowContext, createIsolatedContext } from './context.js'
|
|
86
98
|
|
|
99
|
+
// Cascade Context - Correlation IDs and step metadata
|
|
100
|
+
export {
|
|
101
|
+
createCascadeContext,
|
|
102
|
+
recordStep,
|
|
103
|
+
withCascadeContext,
|
|
104
|
+
type CascadeContext,
|
|
105
|
+
type CascadeStep,
|
|
106
|
+
type CascadeContextOptions,
|
|
107
|
+
type SerializedCascadeContext,
|
|
108
|
+
type SerializedCascadeStep,
|
|
109
|
+
type TraceContext,
|
|
110
|
+
type FiveWHEvent,
|
|
111
|
+
type StepStatus,
|
|
112
|
+
} from './cascade-context.js'
|
|
113
|
+
|
|
114
|
+
// Dependency Graph
|
|
115
|
+
export {
|
|
116
|
+
DependencyGraph,
|
|
117
|
+
CircularDependencyError,
|
|
118
|
+
MissingDependencyError,
|
|
119
|
+
type GraphNode,
|
|
120
|
+
type ParallelGroup,
|
|
121
|
+
type GraphJSON,
|
|
122
|
+
type EventRegistrationWithDeps,
|
|
123
|
+
} from './dependency-graph.js'
|
|
124
|
+
|
|
125
|
+
// Topological Sort - Execution ordering algorithms
|
|
126
|
+
export {
|
|
127
|
+
topologicalSort,
|
|
128
|
+
topologicalSortKahn,
|
|
129
|
+
topologicalSortDFS,
|
|
130
|
+
getExecutionLevels,
|
|
131
|
+
CycleDetectedError,
|
|
132
|
+
MissingNodeError,
|
|
133
|
+
type SortableNode,
|
|
134
|
+
type ExecutionLevel,
|
|
135
|
+
type TopologicalSortOptions,
|
|
136
|
+
type TopologicalSortResult,
|
|
137
|
+
} from './graph/topological-sort.js'
|
|
138
|
+
|
|
139
|
+
// Barrier/Join Semantics - Parallel step coordination
|
|
140
|
+
export {
|
|
141
|
+
Barrier,
|
|
142
|
+
BarrierTimeoutError,
|
|
143
|
+
createBarrier,
|
|
144
|
+
waitForAll,
|
|
145
|
+
waitForAny,
|
|
146
|
+
withConcurrencyLimit,
|
|
147
|
+
type BarrierOptions,
|
|
148
|
+
type BarrierProgress,
|
|
149
|
+
type BarrierResult,
|
|
150
|
+
type WaitForAllOptions,
|
|
151
|
+
type WaitForAnyOptions,
|
|
152
|
+
type WaitForAnyResult,
|
|
153
|
+
type ConcurrencyOptions,
|
|
154
|
+
} from './barrier.js'
|
|
155
|
+
|
|
156
|
+
// Cascade Executor - code -> generative -> agentic -> human pattern
|
|
157
|
+
export {
|
|
158
|
+
CascadeExecutor,
|
|
159
|
+
CascadeTimeoutError,
|
|
160
|
+
TierSkippedError,
|
|
161
|
+
AllTiersFailedError,
|
|
162
|
+
TIER_ORDER,
|
|
163
|
+
DEFAULT_TIER_TIMEOUTS,
|
|
164
|
+
type CapabilityTier,
|
|
165
|
+
type TierHandler,
|
|
166
|
+
type TierContext,
|
|
167
|
+
type TierResult,
|
|
168
|
+
type TierRetryConfig,
|
|
169
|
+
type CascadeConfig,
|
|
170
|
+
type CascadeResult,
|
|
171
|
+
type CascadeMetrics,
|
|
172
|
+
type SkipCondition,
|
|
173
|
+
} from './cascade-executor.js'
|
|
174
|
+
|
|
175
|
+
// DurableStep - Cloudflare Workflows step wrapper
|
|
176
|
+
export {
|
|
177
|
+
DurableStep,
|
|
178
|
+
StepContext as DurableStepContext,
|
|
179
|
+
type StepConfig,
|
|
180
|
+
type StepMetadata,
|
|
181
|
+
type RetryConfig as DurableRetryConfig,
|
|
182
|
+
type WorkflowStep,
|
|
183
|
+
type StepFunction as DurableStepFunction,
|
|
184
|
+
// Cascade types
|
|
185
|
+
DurableCascadeStep,
|
|
186
|
+
AllTiersFailed,
|
|
187
|
+
CascadeTimeout,
|
|
188
|
+
DEFAULT_CASCADE_TIMEOUTS,
|
|
189
|
+
CASCADE_TIER_ORDER,
|
|
190
|
+
type CascadeTier,
|
|
191
|
+
type CascadeConfig as DurableCascadeConfig,
|
|
192
|
+
type CascadeTierConfig,
|
|
193
|
+
type CascadeTierResult,
|
|
194
|
+
type CascadeResult as DurableCascadeResult,
|
|
195
|
+
type CascadeContext as DurableCascadeContext,
|
|
196
|
+
type CascadeTierContext,
|
|
197
|
+
type AiBinding,
|
|
198
|
+
type HumanReviewRequest,
|
|
199
|
+
type CodeTierHandler,
|
|
200
|
+
type AiTierHandler,
|
|
201
|
+
type HumanTierHandler,
|
|
202
|
+
} from './worker/durable-step.js'
|
|
203
|
+
|
|
204
|
+
// WorkflowBuilder DSL - Fluent API for building durable workflows
|
|
205
|
+
export {
|
|
206
|
+
workflow,
|
|
207
|
+
WorkflowBuilder,
|
|
208
|
+
type StepDefinition,
|
|
209
|
+
type StepChain,
|
|
210
|
+
type ConditionalChain,
|
|
211
|
+
type LoopChain,
|
|
212
|
+
type BuiltWorkflow,
|
|
213
|
+
type StepContext,
|
|
214
|
+
type RetryConfig,
|
|
215
|
+
type StepFunction,
|
|
216
|
+
type ConditionFunction,
|
|
217
|
+
type ErrorHandler,
|
|
218
|
+
type LoopOptions,
|
|
219
|
+
type ForEachOptions,
|
|
220
|
+
} from './workflow-builder.js'
|
|
221
|
+
|
|
222
|
+
// WorkflowStateAdapter - Persistent state storage
|
|
223
|
+
export {
|
|
224
|
+
WorkflowStateAdapter,
|
|
225
|
+
type PersistedWorkflowState,
|
|
226
|
+
type StepCheckpoint,
|
|
227
|
+
type WorkflowHistoryEntry as StateHistoryEntry,
|
|
228
|
+
type SnapshotInfo,
|
|
229
|
+
type DatabaseConnection,
|
|
230
|
+
} from './worker/state-adapter.js'
|
|
231
|
+
|
|
87
232
|
// Types
|
|
88
233
|
export type {
|
|
89
234
|
EventHandler,
|
|
@@ -103,4 +248,6 @@ export type {
|
|
|
103
248
|
DatabaseContext,
|
|
104
249
|
ActionData,
|
|
105
250
|
ArtifactData,
|
|
251
|
+
DependencyConfig,
|
|
252
|
+
DependencyType,
|
|
106
253
|
} from './types.js'
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configurable Logger Interface
|
|
3
|
+
*
|
|
4
|
+
* Provides a pluggable logging abstraction for ai-workflows.
|
|
5
|
+
* By default uses console.log/warn/error, but can be replaced
|
|
6
|
+
* with any logging implementation.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { setLogger, getLogger } from 'ai-workflows'
|
|
11
|
+
*
|
|
12
|
+
* // Use default console logger
|
|
13
|
+
* const logger = getLogger()
|
|
14
|
+
* logger.log('[workflow] Starting', { workflowId: '123' })
|
|
15
|
+
*
|
|
16
|
+
* // Set a custom logger
|
|
17
|
+
* setLogger({
|
|
18
|
+
* log: (msg, data) => winston.info(msg, data),
|
|
19
|
+
* warn: (msg, data) => winston.warn(msg, data),
|
|
20
|
+
* error: (msg, error) => winston.error(msg, { error }),
|
|
21
|
+
* })
|
|
22
|
+
*
|
|
23
|
+
* // Disable logging
|
|
24
|
+
* setLogger({
|
|
25
|
+
* log: () => {},
|
|
26
|
+
* warn: () => {},
|
|
27
|
+
* error: () => {},
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Logger interface for ai-workflows
|
|
34
|
+
*
|
|
35
|
+
* Implementations must provide log, warn, and error methods.
|
|
36
|
+
* Data parameter is optional and can be any value for context.
|
|
37
|
+
*/
|
|
38
|
+
export interface Logger {
|
|
39
|
+
/**
|
|
40
|
+
* Log informational messages
|
|
41
|
+
* @param msg - The log message
|
|
42
|
+
* @param data - Optional data for context
|
|
43
|
+
*/
|
|
44
|
+
log(msg: string, data?: unknown): void
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Log warning messages
|
|
48
|
+
* @param msg - The warning message
|
|
49
|
+
* @param data - Optional data for context
|
|
50
|
+
*/
|
|
51
|
+
warn(msg: string, data?: unknown): void
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Log error messages
|
|
55
|
+
* @param msg - The error message
|
|
56
|
+
* @param error - Optional error object or data
|
|
57
|
+
*/
|
|
58
|
+
error(msg: string, error?: unknown): void
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Default console logger implementation
|
|
63
|
+
*
|
|
64
|
+
* Uses console.log, console.warn, and console.error.
|
|
65
|
+
*/
|
|
66
|
+
export const consoleLogger: Logger = {
|
|
67
|
+
log(msg: string, data?: unknown): void {
|
|
68
|
+
if (data !== undefined) {
|
|
69
|
+
console.log(msg, data)
|
|
70
|
+
} else {
|
|
71
|
+
console.log(msg)
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
warn(msg: string, data?: unknown): void {
|
|
76
|
+
if (data !== undefined) {
|
|
77
|
+
console.warn(msg, data)
|
|
78
|
+
} else {
|
|
79
|
+
console.warn(msg)
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
error(msg: string, error?: unknown): void {
|
|
84
|
+
if (error !== undefined) {
|
|
85
|
+
console.error(msg, error)
|
|
86
|
+
} else {
|
|
87
|
+
console.error(msg)
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* No-op logger that discards all messages
|
|
94
|
+
*
|
|
95
|
+
* Useful for silencing logs in tests or production.
|
|
96
|
+
*/
|
|
97
|
+
export const noopLogger: Logger = {
|
|
98
|
+
log(): void {},
|
|
99
|
+
warn(): void {},
|
|
100
|
+
error(): void {},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Current logger instance
|
|
105
|
+
* Defaults to consoleLogger
|
|
106
|
+
*/
|
|
107
|
+
let currentLogger: Logger = consoleLogger
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get the current logger instance
|
|
111
|
+
*
|
|
112
|
+
* @returns The current Logger implementation
|
|
113
|
+
*/
|
|
114
|
+
export function getLogger(): Logger {
|
|
115
|
+
return currentLogger
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Set the logger implementation
|
|
120
|
+
*
|
|
121
|
+
* @param logger - The Logger implementation to use
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* // Use a custom logger
|
|
126
|
+
* setLogger({
|
|
127
|
+
* log: (msg, data) => myLogger.info(msg, data),
|
|
128
|
+
* warn: (msg, data) => myLogger.warn(msg, data),
|
|
129
|
+
* error: (msg, error) => myLogger.error(msg, { error }),
|
|
130
|
+
* })
|
|
131
|
+
*
|
|
132
|
+
* // Disable logging
|
|
133
|
+
* setLogger(noopLogger)
|
|
134
|
+
*
|
|
135
|
+
* // Reset to console
|
|
136
|
+
* setLogger(consoleLogger)
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export function setLogger(logger: Logger): void {
|
|
140
|
+
currentLogger = logger
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Reset the logger to the default console logger
|
|
145
|
+
*/
|
|
146
|
+
export function resetLogger(): void {
|
|
147
|
+
currentLogger = consoleLogger
|
|
148
|
+
}
|
package/src/on.ts
CHANGED
|
@@ -5,9 +5,21 @@
|
|
|
5
5
|
* on.Customer.created(customer => { ... })
|
|
6
6
|
* on.Order.completed(order => { ... })
|
|
7
7
|
* on.Payment.failed(payment => { ... })
|
|
8
|
+
*
|
|
9
|
+
* With dependencies:
|
|
10
|
+
* on.Step2.complete(handler, { dependsOn: 'Step1.complete' })
|
|
11
|
+
* on.Step3.complete(handler, { dependsOn: ['Step1.complete', 'Step2.complete'] })
|
|
8
12
|
*/
|
|
9
13
|
|
|
10
|
-
import type {
|
|
14
|
+
import type {
|
|
15
|
+
EventHandler,
|
|
16
|
+
EventRegistration,
|
|
17
|
+
DependencyConfig,
|
|
18
|
+
OnProxy,
|
|
19
|
+
NounEventProxy,
|
|
20
|
+
OnProxyHandler,
|
|
21
|
+
NounEventProxyHandler,
|
|
22
|
+
} from './types.js'
|
|
11
23
|
|
|
12
24
|
/**
|
|
13
25
|
* Registry of event handlers
|
|
@@ -34,50 +46,93 @@ export function clearEventHandlers(): void {
|
|
|
34
46
|
export function registerEventHandler(
|
|
35
47
|
noun: string,
|
|
36
48
|
event: string,
|
|
37
|
-
handler: EventHandler
|
|
49
|
+
handler: EventHandler,
|
|
50
|
+
dependencies?: DependencyConfig
|
|
38
51
|
): void {
|
|
39
52
|
eventRegistry.push({
|
|
40
53
|
noun,
|
|
41
54
|
event,
|
|
42
55
|
handler,
|
|
43
56
|
source: handler.toString(),
|
|
57
|
+
...(dependencies !== undefined && { dependencies }),
|
|
44
58
|
})
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
/**
|
|
48
|
-
*
|
|
62
|
+
* Handler registration callback type
|
|
63
|
+
* Used by createTypedOnProxy to customize handler registration
|
|
49
64
|
*/
|
|
50
|
-
type
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
65
|
+
export type OnProxyRegistrationCallback = (
|
|
66
|
+
noun: string,
|
|
67
|
+
event: string,
|
|
68
|
+
handler: EventHandler,
|
|
69
|
+
dependencies?: DependencyConfig
|
|
70
|
+
) => void
|
|
55
71
|
|
|
56
72
|
/**
|
|
57
|
-
* Create
|
|
73
|
+
* Create a typed OnProxy with proper TypeScript generics
|
|
58
74
|
*
|
|
59
|
-
* This creates a proxy that allows:
|
|
60
|
-
*
|
|
61
|
-
*
|
|
75
|
+
* This factory function creates a two-level proxy that allows:
|
|
76
|
+
* proxy.Customer.created(handler)
|
|
77
|
+
* proxy.Order.shipped(handler)
|
|
62
78
|
*
|
|
63
79
|
* The first property access captures the noun (Customer, Order)
|
|
64
80
|
* The second property access captures the event (created, shipped)
|
|
65
|
-
* The function call
|
|
81
|
+
* The function call invokes the registration callback
|
|
82
|
+
*
|
|
83
|
+
* @param registerCallback - Function called when a handler is registered
|
|
84
|
+
* @returns A properly typed OnProxy
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* // Create proxy with custom registration
|
|
89
|
+
* const myOn = createTypedOnProxy((noun, event, handler, deps) => {
|
|
90
|
+
* myRegistry.push({ noun, event, handler, deps })
|
|
91
|
+
* })
|
|
92
|
+
*
|
|
93
|
+
* myOn.Customer.created(handler) // Properly typed!
|
|
94
|
+
* ```
|
|
66
95
|
*/
|
|
67
|
-
function
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
}
|
|
96
|
+
export function createTypedOnProxy(registerCallback: OnProxyRegistrationCallback): OnProxy {
|
|
97
|
+
// Create typed handler for the noun level (event accessors)
|
|
98
|
+
const createNounHandler = (noun: string): NounEventProxyHandler => ({
|
|
99
|
+
get(
|
|
100
|
+
_target: Record<string, (handler: EventHandler, dependencies?: DependencyConfig) => void>,
|
|
101
|
+
event: string,
|
|
102
|
+
_receiver: unknown
|
|
103
|
+
): (handler: EventHandler, dependencies?: DependencyConfig) => void {
|
|
104
|
+
// Return a function that registers the handler with optional dependencies
|
|
105
|
+
return (handler: EventHandler, dependencies?: DependencyConfig) => {
|
|
106
|
+
registerCallback(noun, event, handler, dependencies)
|
|
107
|
+
}
|
|
108
|
+
},
|
|
80
109
|
})
|
|
110
|
+
|
|
111
|
+
// Create typed handler for the top-level proxy (noun accessors)
|
|
112
|
+
const onHandler: OnProxyHandler = {
|
|
113
|
+
get(_target: Record<string, NounEventProxy>, noun: string, _receiver: unknown): NounEventProxy {
|
|
114
|
+
// Return a proxy for the event level with typed handler
|
|
115
|
+
const eventTarget: Record<
|
|
116
|
+
string,
|
|
117
|
+
(handler: EventHandler, dependencies?: DependencyConfig) => void
|
|
118
|
+
> = {}
|
|
119
|
+
return new Proxy(eventTarget, createNounHandler(noun)) as NounEventProxy
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Create and return the typed OnProxy
|
|
124
|
+
const target: Record<string, NounEventProxy> = {}
|
|
125
|
+
return new Proxy(target, onHandler) as OnProxy
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Create the `on` proxy using the global event registry
|
|
130
|
+
*
|
|
131
|
+
* This is the default implementation that uses registerEventHandler
|
|
132
|
+
* for backward compatibility with the standalone `on` export.
|
|
133
|
+
*/
|
|
134
|
+
function createOnProxy(): OnProxy {
|
|
135
|
+
return createTypedOnProxy(registerEventHandler)
|
|
81
136
|
}
|
|
82
137
|
|
|
83
138
|
/**
|