@gravito/flux 3.0.1 → 3.0.2

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 (48) hide show
  1. package/README.md +298 -0
  2. package/bin/flux.js +25 -1
  3. package/dev/viewer/app.js +4 -4
  4. package/dist/bun.cjs +2 -2
  5. package/dist/bun.cjs.map +1 -1
  6. package/dist/bun.d.cts +65 -26
  7. package/dist/bun.d.ts +65 -26
  8. package/dist/bun.js +1 -1
  9. package/dist/chunk-4DXCQ6CL.js +3486 -0
  10. package/dist/chunk-4DXCQ6CL.js.map +1 -0
  11. package/dist/chunk-6AZNHVEO.cjs +316 -0
  12. package/dist/chunk-6AZNHVEO.cjs.map +1 -0
  13. package/dist/{chunk-ZAMVC732.js → chunk-NAIVO7RR.js} +64 -15
  14. package/dist/chunk-NAIVO7RR.js.map +1 -0
  15. package/dist/chunk-WAPZDXSX.cjs +3486 -0
  16. package/dist/chunk-WAPZDXSX.cjs.map +1 -0
  17. package/dist/chunk-WGDTB6OC.js +316 -0
  18. package/dist/chunk-WGDTB6OC.js.map +1 -0
  19. package/dist/{chunk-SJSPR4ZU.cjs → chunk-YXBEYVGY.cjs} +66 -17
  20. package/dist/chunk-YXBEYVGY.cjs.map +1 -0
  21. package/dist/cli/flux-visualize.cjs +108 -0
  22. package/dist/cli/flux-visualize.cjs.map +1 -0
  23. package/dist/cli/flux-visualize.d.cts +1 -0
  24. package/dist/cli/flux-visualize.d.ts +1 -0
  25. package/dist/cli/flux-visualize.js +108 -0
  26. package/dist/cli/flux-visualize.js.map +1 -0
  27. package/dist/index.cjs +97 -9
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +369 -13
  30. package/dist/index.d.ts +369 -13
  31. package/dist/index.js +96 -8
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.node.cjs +11 -3
  34. package/dist/index.node.cjs.map +1 -1
  35. package/dist/index.node.d.cts +1110 -247
  36. package/dist/index.node.d.ts +1110 -247
  37. package/dist/index.node.js +10 -2
  38. package/dist/types-CRz5XdLd.d.cts +433 -0
  39. package/dist/types-CRz5XdLd.d.ts +433 -0
  40. package/package.json +17 -6
  41. package/dist/chunk-3JGQYHUN.js +0 -1006
  42. package/dist/chunk-3JGQYHUN.js.map +0 -1
  43. package/dist/chunk-5OXXH442.cjs +0 -1006
  44. package/dist/chunk-5OXXH442.cjs.map +0 -1
  45. package/dist/chunk-SJSPR4ZU.cjs.map +0 -1
  46. package/dist/chunk-ZAMVC732.js.map +0 -1
  47. package/dist/types-CZwYGpou.d.cts +0 -353
  48. package/dist/types-CZwYGpou.d.ts +0 -353
package/dist/index.d.ts CHANGED
@@ -1,16 +1,255 @@
1
- import { W as WorkflowDefinition, F as FluxWaitResult } from './types-CZwYGpou.js';
2
- export { a as FluxConfig, b as FluxLogger, c as FluxResult, d as FluxTraceEvent, e as FluxTraceEventType, f as FluxTraceSink, S as StepDefinition, g as StepDescriptor, h as StepExecution, i as StepResult, j as WorkflowContext, k as WorkflowDescriptor, l as WorkflowFilter, m as WorkflowState, n as WorkflowStatus, o as WorkflowStorage } from './types-CZwYGpou.js';
1
+ import { C as CronScheduleOptions, W as WorkflowDefinition, a as WorkflowState, F as FluxWaitResult } from './types-CRz5XdLd.js';
2
+ export { b as FluxConfig, c as FluxLogger, d as FluxResult, e as FluxTraceEvent, f as FluxTraceEventType, g as FluxTraceSink, L as Lock, h as LockProvider, M as MemoryLockProvider, S as StepDefinition, i as StepDescriptor, j as StepExecution, k as StepResult, l as WorkflowContext, m as WorkflowDescriptor, n as WorkflowFilter, o as WorkflowStatus, p as WorkflowStorage } from './types-CRz5XdLd.js';
3
3
  import { FluxEngine } from './index.node.js';
4
- export { ContextManager, FluxConsoleLogger, FluxSilentLogger, JsonFileTraceSink, MemoryStorage, OrbitFlux, OrbitFluxOptions, StateMachine, StepExecutor, WorkflowBuilder, createWorkflow } from './index.node.js';
4
+ export { BatchExecutionOptions, BatchExecutor, BatchItemResult, BatchResult, ContextManager, FluxConsoleLogger, FluxSilentLogger, JsonFileTraceSink, MemoryStorage, OrbitFlux, OrbitFluxOptions, PostgreSQLStorage, PostgreSQLStorageOptions, RedisClient, RedisLockProvider, RedisLockProviderOptions, StateMachine, StepExecutor, WorkflowBuilder, createWorkflow } from './index.node.js';
5
5
  export { BunSQLiteStorage, BunSQLiteStorageOptions } from './bun.js';
6
6
  import '@gravito/core';
7
7
  import 'bun:sqlite';
8
8
 
9
+ /**
10
+ * Standard error codes for FluxEngine operations.
11
+ *
12
+ * Used to programmatically identify the cause of a `FluxError`.
13
+ */
14
+ declare enum FluxErrorCode {
15
+ /** The requested workflow instance could not be found in storage. */
16
+ WORKFLOW_NOT_FOUND = "WORKFLOW_NOT_FOUND",
17
+ /** The input data provided to the workflow failed validation. */
18
+ WORKFLOW_INVALID_INPUT = "WORKFLOW_INVALID_INPUT",
19
+ /** The workflow definition has changed since the instance was created, making it unsafe to resume. */
20
+ WORKFLOW_DEFINITION_CHANGED = "WORKFLOW_DEFINITION_CHANGED",
21
+ /** The workflow name in the definition does not match the stored state. */
22
+ WORKFLOW_NAME_MISMATCH = "WORKFLOW_NAME_MISMATCH",
23
+ /** An attempt was made to transition the workflow to an incompatible state. */
24
+ INVALID_STATE_TRANSITION = "INVALID_STATE_TRANSITION",
25
+ /** An operation requiring a suspended state was attempted on a workflow that is not suspended. */
26
+ WORKFLOW_NOT_SUSPENDED = "WORKFLOW_NOT_SUSPENDED",
27
+ /** The requested step index is out of bounds for the current workflow definition. */
28
+ INVALID_STEP_INDEX = "INVALID_STEP_INDEX",
29
+ /** A workflow step exceeded its configured execution time limit. */
30
+ STEP_TIMEOUT = "STEP_TIMEOUT",
31
+ /** The requested step could not be found in the workflow definition. */
32
+ STEP_NOT_FOUND = "STEP_NOT_FOUND",
33
+ /** Multiple concurrent attempts to modify the same workflow instance were detected. */
34
+ CONCURRENT_MODIFICATION = "CONCURRENT_MODIFICATION",
35
+ /** A workflow definition must contain at least one step to be executable. */
36
+ EMPTY_WORKFLOW = "EMPTY_WORKFLOW",
37
+ /** No recovery action is registered for a step that requires recovery. */
38
+ NO_RECOVERY_ACTION = "NO_RECOVERY_ACTION",
39
+ /** An invalid JSON Pointer was provided for state manipulation. */
40
+ INVALID_JSON_POINTER = "INVALID_JSON_POINTER",
41
+ /** Cannot access a property on a non-object value in the state tree. */
42
+ INVALID_PATH_TRAVERSAL = "INVALID_PATH_TRAVERSAL",
43
+ /** Cannot replace the root object of the workflow state. */
44
+ CANNOT_REPLACE_ROOT = "CANNOT_REPLACE_ROOT",
45
+ /** Cannot remove the root object of the workflow state. */
46
+ CANNOT_REMOVE_ROOT = "CANNOT_REMOVE_ROOT"
47
+ }
48
+ /**
49
+ * Base class for all errors thrown by the FluxEngine.
50
+ *
51
+ * Includes a machine-readable error code and optional context for debugging.
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * try {
56
+ * await engine.execute(flow, input);
57
+ * } catch (err) {
58
+ * if (err instanceof FluxError && err.code === FluxErrorCode.STEP_TIMEOUT) {
59
+ * console.error('Workflow timed out');
60
+ * }
61
+ * }
62
+ * ```
63
+ */
64
+ declare class FluxError extends Error {
65
+ readonly code: FluxErrorCode;
66
+ readonly context?: Record<string, unknown> | undefined;
67
+ /**
68
+ * Creates a new FluxError.
69
+ *
70
+ * @param message - Human-readable error description.
71
+ * @param code - Machine-readable error code.
72
+ * @param context - Additional metadata related to the error.
73
+ */
74
+ constructor(message: string, code: FluxErrorCode, context?: Record<string, unknown> | undefined);
75
+ }
76
+ /**
77
+ * Creates a FluxError for a missing workflow instance.
78
+ *
79
+ * @param id - The unique identifier of the missing workflow.
80
+ * @returns A FluxError with the WORKFLOW_NOT_FOUND code.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * throw workflowNotFound('wf-123');
85
+ * ```
86
+ */
87
+ declare function workflowNotFound(id: string): FluxError;
88
+ /**
89
+ * Creates a FluxError for an illegal state transition.
90
+ *
91
+ * @param from - The current state of the workflow.
92
+ * @param to - The attempted target state.
93
+ * @returns A FluxError with the INVALID_STATE_TRANSITION code.
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * throw invalidStateTransition('completed', 'running');
98
+ * ```
99
+ */
100
+ declare function invalidStateTransition(from: string, to: string): FluxError;
101
+ /**
102
+ * Creates a FluxError for invalid workflow input.
103
+ *
104
+ * @param workflowName - The name of the workflow definition.
105
+ * @returns A FluxError with the WORKFLOW_INVALID_INPUT code.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * throw invalidInput('order-process');
110
+ * ```
111
+ */
112
+ declare function invalidInput(workflowName: string): FluxError;
113
+ /**
114
+ * Creates a FluxError for a workflow name mismatch.
115
+ *
116
+ * @param expected - The name expected by the definition.
117
+ * @param received - The name found in the stored state.
118
+ * @returns A FluxError with the WORKFLOW_NAME_MISMATCH code.
119
+ */
120
+ declare function workflowNameMismatch(expected: string, received: string): FluxError;
121
+ /**
122
+ * Creates a FluxError when a workflow definition has changed incompatibly.
123
+ *
124
+ * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.
125
+ */
126
+ declare function workflowDefinitionChanged(): FluxError;
127
+ /**
128
+ * Creates a FluxError when an operation requires a suspended workflow.
129
+ *
130
+ * @param status - The current status of the workflow.
131
+ * @returns A FluxError with the WORKFLOW_NOT_SUSPENDED code.
132
+ */
133
+ declare function workflowNotSuspended(status: string): FluxError;
134
+ /**
135
+ * Creates a FluxError when a specific step cannot be found.
136
+ *
137
+ * @param step - The name or index of the missing step.
138
+ * @returns A FluxError with the STEP_NOT_FOUND code.
139
+ */
140
+ declare function stepNotFound(step: string | number): FluxError;
141
+ /**
142
+ * Creates a FluxError for an out-of-bounds step index.
143
+ *
144
+ * @param index - The invalid step index.
145
+ * @returns A FluxError with the INVALID_STEP_INDEX code.
146
+ */
147
+ declare function invalidStepIndex(index: number): FluxError;
148
+ /**
149
+ * Creates a FluxError for an empty workflow (no steps defined).
150
+ *
151
+ * @param workflowName - The name of the workflow.
152
+ * @returns A FluxError with the EMPTY_WORKFLOW code.
153
+ */
154
+ declare function emptyWorkflow(workflowName: string): FluxError;
155
+ /**
156
+ * Creates a FluxError when no recovery action is registered for a step.
157
+ *
158
+ * @param stepName - The name of the step requiring recovery.
159
+ * @returns A FluxError with the NO_RECOVERY_ACTION code.
160
+ */
161
+ declare function noRecoveryAction(stepName: string): FluxError;
162
+ /**
163
+ * Creates a FluxError for invalid JSON Pointer syntax.
164
+ *
165
+ * @param path - The invalid JSON Pointer.
166
+ * @returns A FluxError with the INVALID_JSON_POINTER code.
167
+ */
168
+ declare function invalidJsonPointer(path: string): FluxError;
169
+ /**
170
+ * Creates a FluxError when attempting to traverse a non-object value.
171
+ *
172
+ * @param segment - The property being accessed.
173
+ * @param current - The current value type.
174
+ * @returns A FluxError with the INVALID_PATH_TRAVERSAL code.
175
+ */
176
+ declare function invalidPathTraversal(segment: string, current: unknown): FluxError;
177
+ /**
178
+ * Creates a FluxError when attempting to replace the root object.
179
+ *
180
+ * @returns A FluxError with the CANNOT_REPLACE_ROOT code.
181
+ */
182
+ declare function cannotReplaceRoot(): FluxError;
183
+ /**
184
+ * Creates a FluxError when attempting to remove the root object.
185
+ *
186
+ * @returns A FluxError with the CANNOT_REMOVE_ROOT code.
187
+ */
188
+ declare function cannotRemoveRoot(): FluxError;
189
+
190
+ /**
191
+ * Built-in scheduler for Flux workflows.
192
+ *
193
+ * Manages multiple cron-based schedules and triggers workflow execution
194
+ * at the specified intervals.
195
+ */
196
+ declare class CronTrigger {
197
+ private engine;
198
+ private schedules;
199
+ private timers;
200
+ private running;
201
+ /**
202
+ * Creates a new CronTrigger instance.
203
+ *
204
+ * @param engine - The Flux engine to use for executing scheduled workflows.
205
+ */
206
+ constructor(engine: FluxEngine);
207
+ /**
208
+ * Starts the scheduler.
209
+ */
210
+ start(): void;
211
+ /**
212
+ * Stops the scheduler and clears all timers.
213
+ */
214
+ stop(): void;
215
+ /**
216
+ * Adds a new schedule or updates an existing one.
217
+ *
218
+ * @param options - The schedule configuration.
219
+ */
220
+ addSchedule(options: CronScheduleOptions): void;
221
+ /**
222
+ * Removes a schedule.
223
+ *
224
+ * @param id - The ID of the schedule to remove.
225
+ */
226
+ removeSchedule(id: string): void;
227
+ /**
228
+ * Refreshes all active schedules.
229
+ * @private
230
+ */
231
+ private refreshAll;
232
+ /**
233
+ * Calculates the next execution time and sets a timer for a specific schedule.
234
+ *
235
+ * @param id - The ID of the schedule to refresh.
236
+ * @private
237
+ */
238
+ private refreshSchedule;
239
+ /**
240
+ * Lists all registered schedules.
241
+ * @returns An array of schedule configurations.
242
+ */
243
+ listSchedules(): CronScheduleOptions[];
244
+ }
245
+
9
246
  /**
10
247
  * Performance metrics captured during a workflow profiling session.
11
248
  *
249
+ * Used to quantify the resource footprint of a workflow execution, enabling
250
+ * data-driven decisions for infrastructure scaling and concurrency tuning.
251
+ *
12
252
  * @public
13
- * @since 3.0.0
14
253
  */
15
254
  interface ProfileMetrics {
16
255
  /** Total wall-clock duration of the workflow execution in milliseconds. */
@@ -27,8 +266,10 @@ interface ProfileMetrics {
27
266
  /**
28
267
  * Concurrency recommendations generated by the profiler.
29
268
  *
269
+ * Provides actionable insights into how many instances of a workflow can safely
270
+ * and efficiently run in parallel on the current hardware.
271
+ *
30
272
  * @public
31
- * @since 3.0.0
32
273
  */
33
274
  interface ProfileRecommendation {
34
275
  /** The identified primary bottleneck type. */
@@ -53,21 +294,51 @@ interface ProfileRecommendation {
53
294
  * const profiler = new WorkflowProfiler();
54
295
  * const metrics = await profiler.profile(myWorkflow, { input: 'data' });
55
296
  * const advice = profiler.recommend(metrics);
56
- * console.log(advice.suggestedConcurrency);
297
+ * console.log(`Suggested concurrency: ${advice.suggestedConcurrency}`);
57
298
  * ```
58
299
  *
59
300
  * @public
60
- * @since 3.0.0
61
301
  */
62
302
  declare class WorkflowProfiler {
63
303
  private engine?;
304
+ /**
305
+ * Initializes the profiler with an optional engine.
306
+ *
307
+ * @param engine - The FluxEngine instance to use for execution. If omitted, a silent engine is created.
308
+ */
64
309
  constructor(engine?: FluxEngine | undefined);
65
310
  /**
66
- * Run a profile session for a specific workflow
311
+ * Executes a workflow and captures its resource consumption metrics.
312
+ *
313
+ * Performs a warmup run to ensure JIT optimization before measurement.
314
+ *
315
+ * @param workflow - The workflow definition to profile.
316
+ * @param input - The input data for the workflow execution.
317
+ * @returns A promise resolving to the captured performance metrics.
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * const metrics = await profiler.profile(orderWorkflow, { id: '123' });
322
+ * console.log(`Duration: ${metrics.durationMs}ms`);
323
+ * ```
67
324
  */
68
325
  profile<TInput>(workflow: WorkflowDefinition<TInput, any>, input: TInput): Promise<ProfileMetrics>;
69
326
  /**
70
- * Generate recommendations based on metrics and current environment
327
+ * Analyzes metrics to generate concurrency recommendations.
328
+ *
329
+ * Considers system CPU cores and total memory to calculate safe and efficient limits.
330
+ *
331
+ * @param metrics - The metrics captured during a profiling session.
332
+ * @param config - Optional current configuration to check against recommendations.
333
+ * @returns A recommendation object containing bottleneck analysis and concurrency limits.
334
+ *
335
+ * @example
336
+ * ```typescript
337
+ * const advice = profiler.recommend(metrics, { configuredConcurrency: 10 });
338
+ * if (advice.type === 'CPU_BOUND') {
339
+ * console.warn('Workflow is CPU bound, consider reducing concurrency');
340
+ * }
341
+ * ```
71
342
  */
72
343
  recommend(metrics: ProfileMetrics, config?: {
73
344
  configuredConcurrency?: number;
@@ -75,15 +346,100 @@ declare class WorkflowProfiler {
75
346
  }
76
347
 
77
348
  /**
78
- * Flux helper utilities
349
+ * Options for customizing Mermaid diagram generation.
350
+ */
351
+ interface MermaidOptions {
352
+ /** Include detailed step information (retries, timeout, conditions). */
353
+ showDetails?: boolean;
354
+ /** Include execution history with status colors. */
355
+ showStatus?: boolean;
356
+ /** Render parallel groups visually. */
357
+ showParallelGroups?: boolean;
358
+ /** Theme: 'default' | 'dark' | 'forest' | 'neutral'. */
359
+ theme?: 'default' | 'dark' | 'forest' | 'neutral';
360
+ }
361
+ /**
362
+ * Generates Mermaid flowchart diagrams from workflow definitions and execution states.
363
+ *
364
+ * **Features**:
365
+ * - Workflow structure visualization (steps, parallel groups, conditions)
366
+ * - Execution status overlay (completed, failed, compensated)
367
+ * - Detailed metadata (retries, timeout, commit markers)
368
+ *
369
+ * **Use Cases**:
370
+ * - Documentation generation
371
+ * - Debugging workflow execution
372
+ * - Visual workflow design validation
373
+ */
374
+ declare class MermaidGenerator {
375
+ /**
376
+ * Generates a Mermaid flowchart from a workflow definition.
377
+ *
378
+ * @param definition - The workflow definition to visualize
379
+ * @param options - Customization options
380
+ * @returns Mermaid diagram syntax as a string
381
+ *
382
+ * @example
383
+ * ```typescript
384
+ * const generator = new MermaidGenerator()
385
+ * const diagram = generator.generateFromDefinition(workflow, {
386
+ * showDetails: true,
387
+ * showParallelGroups: true
388
+ * })
389
+ * console.log(diagram)
390
+ * ```
391
+ */
392
+ generateFromDefinition<TInput, TData>(definition: WorkflowDefinition<TInput, TData>, options?: MermaidOptions): string;
393
+ /**
394
+ * Generates a Mermaid flowchart from a workflow execution state.
395
+ * Overlays execution status (completed, failed, compensated) on top of the structure.
396
+ *
397
+ * @param definition - The workflow definition
398
+ * @param state - The current execution state
399
+ * @param options - Customization options
400
+ * @returns Mermaid diagram syntax with status overlay
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * const diagram = generator.generateFromState(workflow, executionState, {
405
+ * showStatus: true,
406
+ * showDetails: true
407
+ * })
408
+ * ```
409
+ */
410
+ generateFromState<TInput, TData>(definition: WorkflowDefinition<TInput, TData>, state: WorkflowState<TInput, TData>, options?: MermaidOptions): string;
411
+ private sanitizeNodeId;
412
+ private buildStepLabel;
413
+ private buildStepLabelWithStatus;
414
+ private getStatusClass;
415
+ private getWorkflowFinalStatus;
416
+ private getNextNodeId;
417
+ }
418
+
419
+ /**
420
+ * Flux helper utilities for workflow control flow.
421
+ *
422
+ * Provides methods to interact with the workflow engine's special behaviors,
423
+ * such as suspending execution to wait for external signals.
79
424
  */
80
425
  declare const Flux: {
81
426
  /**
82
- * Suspend workflow execution and wait for a signal
427
+ * Suspends workflow execution until a specific signal is received.
428
+ *
429
+ * When a handler returns this result, the engine saves the current state
430
+ * and stops execution. The workflow can be resumed later using `engine.signal()`.
431
+ *
432
+ * @param signal - The unique identifier for the signal to wait for.
433
+ * @returns A special result object that instructs the engine to suspend.
83
434
  *
84
- * @param signal - Signal name to wait for
435
+ * @example
436
+ * ```typescript
437
+ * .step('wait-for-approval', async (ctx) => {
438
+ * return Flux.wait('manager-approval');
439
+ * })
440
+ * ```
85
441
  */
86
442
  wait: (signal: string) => FluxWaitResult;
87
443
  };
88
444
 
89
- export { Flux, FluxEngine, FluxWaitResult, type ProfileMetrics, type ProfileRecommendation, WorkflowDefinition, WorkflowProfiler };
445
+ export { CronScheduleOptions, CronTrigger, Flux, FluxEngine, FluxError, FluxErrorCode, FluxWaitResult, MermaidGenerator, type MermaidOptions, type ProfileMetrics, type ProfileRecommendation, WorkflowDefinition, WorkflowProfiler, WorkflowState, cannotRemoveRoot, cannotReplaceRoot, emptyWorkflow, invalidInput, invalidJsonPointer, invalidPathTraversal, invalidStateTransition, invalidStepIndex, noRecoveryAction, stepNotFound, workflowDefinitionChanged, workflowNameMismatch, workflowNotFound, workflowNotSuspended };
package/dist/index.js CHANGED
@@ -1,23 +1,52 @@
1
1
  import {
2
+ BatchExecutor,
2
3
  ContextManager,
4
+ CronTrigger,
3
5
  FluxConsoleLogger,
4
6
  FluxEngine,
7
+ FluxError,
8
+ FluxErrorCode,
5
9
  FluxSilentLogger,
6
10
  JsonFileTraceSink,
11
+ MemoryLockProvider,
7
12
  MemoryStorage,
8
13
  OrbitFlux,
14
+ PostgreSQLStorage,
15
+ RedisLockProvider,
9
16
  StateMachine,
10
17
  StepExecutor,
11
18
  WorkflowBuilder,
12
- createWorkflow
13
- } from "./chunk-3JGQYHUN.js";
19
+ cannotRemoveRoot,
20
+ cannotReplaceRoot,
21
+ createWorkflow,
22
+ emptyWorkflow,
23
+ invalidInput,
24
+ invalidJsonPointer,
25
+ invalidPathTraversal,
26
+ invalidStateTransition,
27
+ invalidStepIndex,
28
+ noRecoveryAction,
29
+ stepNotFound,
30
+ workflowDefinitionChanged,
31
+ workflowNameMismatch,
32
+ workflowNotFound,
33
+ workflowNotSuspended
34
+ } from "./chunk-4DXCQ6CL.js";
14
35
  import {
15
36
  BunSQLiteStorage
16
- } from "./chunk-ZAMVC732.js";
37
+ } from "./chunk-NAIVO7RR.js";
38
+ import {
39
+ MermaidGenerator
40
+ } from "./chunk-WGDTB6OC.js";
17
41
 
18
42
  // src/profiler/WorkflowProfiler.ts
19
43
  import * as os from "os";
20
44
  var WorkflowProfiler = class {
45
+ /**
46
+ * Initializes the profiler with an optional engine.
47
+ *
48
+ * @param engine - The FluxEngine instance to use for execution. If omitted, a silent engine is created.
49
+ */
21
50
  constructor(engine) {
22
51
  this.engine = engine;
23
52
  if (!this.engine) {
@@ -27,7 +56,19 @@ var WorkflowProfiler = class {
27
56
  }
28
57
  }
29
58
  /**
30
- * Run a profile session for a specific workflow
59
+ * Executes a workflow and captures its resource consumption metrics.
60
+ *
61
+ * Performs a warmup run to ensure JIT optimization before measurement.
62
+ *
63
+ * @param workflow - The workflow definition to profile.
64
+ * @param input - The input data for the workflow execution.
65
+ * @returns A promise resolving to the captured performance metrics.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const metrics = await profiler.profile(orderWorkflow, { id: '123' });
70
+ * console.log(`Duration: ${metrics.durationMs}ms`);
71
+ * ```
31
72
  */
32
73
  async profile(workflow, input) {
33
74
  try {
@@ -60,7 +101,21 @@ var WorkflowProfiler = class {
60
101
  };
61
102
  }
62
103
  /**
63
- * Generate recommendations based on metrics and current environment
104
+ * Analyzes metrics to generate concurrency recommendations.
105
+ *
106
+ * Considers system CPU cores and total memory to calculate safe and efficient limits.
107
+ *
108
+ * @param metrics - The metrics captured during a profiling session.
109
+ * @param config - Optional current configuration to check against recommendations.
110
+ * @returns A recommendation object containing bottleneck analysis and concurrency limits.
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * const advice = profiler.recommend(metrics, { configuredConcurrency: 10 });
115
+ * if (advice.type === 'CPU_BOUND') {
116
+ * console.warn('Workflow is CPU bound, consider reducing concurrency');
117
+ * }
118
+ * ```
64
119
  */
65
120
  recommend(metrics, config) {
66
121
  const totalMem = os.totalmem();
@@ -107,9 +162,20 @@ var WorkflowProfiler = class {
107
162
  // src/index.ts
108
163
  var Flux = {
109
164
  /**
110
- * Suspend workflow execution and wait for a signal
165
+ * Suspends workflow execution until a specific signal is received.
166
+ *
167
+ * When a handler returns this result, the engine saves the current state
168
+ * and stops execution. The workflow can be resumed later using `engine.signal()`.
169
+ *
170
+ * @param signal - The unique identifier for the signal to wait for.
171
+ * @returns A special result object that instructs the engine to suspend.
111
172
  *
112
- * @param signal - Signal name to wait for
173
+ * @example
174
+ * ```typescript
175
+ * .step('wait-for-approval', async (ctx) => {
176
+ * return Flux.wait('manager-approval');
177
+ * })
178
+ * ```
113
179
  */
114
180
  wait: (signal) => ({
115
181
  __kind: "flux_wait",
@@ -117,19 +183,41 @@ var Flux = {
117
183
  })
118
184
  };
119
185
  export {
186
+ BatchExecutor,
120
187
  BunSQLiteStorage,
121
188
  ContextManager,
189
+ CronTrigger,
122
190
  Flux,
123
191
  FluxConsoleLogger,
124
192
  FluxEngine,
193
+ FluxError,
194
+ FluxErrorCode,
125
195
  FluxSilentLogger,
126
196
  JsonFileTraceSink,
197
+ MemoryLockProvider,
127
198
  MemoryStorage,
199
+ MermaidGenerator,
128
200
  OrbitFlux,
201
+ PostgreSQLStorage,
202
+ RedisLockProvider,
129
203
  StateMachine,
130
204
  StepExecutor,
131
205
  WorkflowBuilder,
132
206
  WorkflowProfiler,
133
- createWorkflow
207
+ cannotRemoveRoot,
208
+ cannotReplaceRoot,
209
+ createWorkflow,
210
+ emptyWorkflow,
211
+ invalidInput,
212
+ invalidJsonPointer,
213
+ invalidPathTraversal,
214
+ invalidStateTransition,
215
+ invalidStepIndex,
216
+ noRecoveryAction,
217
+ stepNotFound,
218
+ workflowDefinitionChanged,
219
+ workflowNameMismatch,
220
+ workflowNotFound,
221
+ workflowNotSuspended
134
222
  };
135
223
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/profiler/WorkflowProfiler.ts","../src/index.ts"],"sourcesContent":["import * as os from 'node:os'\nimport { FluxEngine } from '../engine/FluxEngine'\nimport { FluxSilentLogger } from '../logger/FluxLogger'\nimport type { WorkflowDefinition } from '../types'\n\n/**\n * Performance metrics captured during a workflow profiling session.\n *\n * @public\n * @since 3.0.0\n */\nexport interface ProfileMetrics {\n /** Total wall-clock duration of the workflow execution in milliseconds. */\n durationMs: number\n /** Amount of time spent in user-space CPU operations in milliseconds. */\n cpuUserMs: number\n /** Amount of time spent in system-space CPU operations in milliseconds. */\n cpuSysMs: number\n /** Estimated heap memory increase during execution in bytes. */\n memDeltaBytes: number\n /** Ratio of CPU time to wall-clock time (0.0 to 1.0+). Higher values indicate CPU-bound tasks. */\n cpuRatio: number\n}\n\n/**\n * Concurrency recommendations generated by the profiler.\n *\n * @public\n * @since 3.0.0\n */\nexport interface ProfileRecommendation {\n /** The identified primary bottleneck type. */\n type: 'IO_BOUND' | 'CPU_BOUND' | 'MEMORY_BOUND'\n /** Maximum safe concurrency considering memory and system stability. */\n safeConcurrency: number\n /** Most efficient concurrency level considering CPU utilization. */\n efficientConcurrency: number\n /** A suggested range for worker concurrency configuration. */\n suggestedConcurrency: string\n /** Detailed explanation for the recommendation. */\n reason: string\n}\n\n/**\n * WorkflowProfiler analyzes workflow performance characteristics.\n *\n * It measures CPU usage, memory consumption, and execution duration to recommend\n * optimal concurrency settings for Gravito Quasar workers or high-throughput consumers.\n *\n * @example\n * ```typescript\n * const profiler = new WorkflowProfiler();\n * const metrics = await profiler.profile(myWorkflow, { input: 'data' });\n * const advice = profiler.recommend(metrics);\n * console.log(advice.suggestedConcurrency);\n * ```\n *\n * @public\n * @since 3.0.0\n */\nexport class WorkflowProfiler {\n constructor(private engine?: FluxEngine) {\n if (!this.engine) {\n // Default minimal engine for profiling (Silent)\n this.engine = new FluxEngine({\n logger: new FluxSilentLogger(),\n })\n }\n }\n\n /**\n * Run a profile session for a specific workflow\n */\n async profile<TInput>(\n workflow: WorkflowDefinition<TInput, any>,\n input: TInput\n ): Promise<ProfileMetrics> {\n // 1. Warmup (JIT)\n try {\n await this.engine?.execute(workflow, input)\n } catch {}\n\n // 2. Measure\n if (global.gc) {\n global.gc()\n }\n\n const startCpu = process.cpuUsage()\n const startMem = process.memoryUsage().heapUsed\n const startTime = process.hrtime.bigint()\n\n await this.engine?.execute(workflow, input)\n\n const endTime = process.hrtime.bigint()\n const endCpu = process.cpuUsage(startCpu)\n const endMem = process.memoryUsage().heapUsed\n\n // 3. Calculate\n const durationNs = Number(endTime - startTime)\n const durationMs = durationNs / 1_000_000\n const cpuUserMs = endCpu.user / 1000\n const cpuSysMs = endCpu.system / 1000\n const totalCpuMs = cpuUserMs + cpuSysMs\n const memDeltaBytes = Math.max(0, endMem - startMem) // Clamp to 0\n\n // CPU Ratio: How much % of the time was spent on CPU vs Waiting\n const cpuRatio = totalCpuMs / durationMs\n\n return {\n durationMs,\n cpuUserMs,\n cpuSysMs,\n memDeltaBytes,\n cpuRatio,\n }\n }\n\n /**\n * Generate recommendations based on metrics and current environment\n */\n recommend(\n metrics: ProfileMetrics,\n config?: { configuredConcurrency?: number }\n ): ProfileRecommendation {\n const totalMem = os.totalmem()\n const cpus = os.cpus().length\n\n // 1. Analyze Bottleneck Type\n let type: ProfileRecommendation['type'] = 'IO_BOUND'\n if (metrics.cpuRatio > 0.5) {\n type = 'CPU_BOUND'\n } else if (metrics.memDeltaBytes > 50 * 1024 * 1024) {\n // > 50MB per run\n type = 'MEMORY_BOUND'\n }\n\n // 2. Calculate Limits\n\n // Memory Limit: Keep 30% buffer for system, divide rest by per-workflow memory\n const safeMem = totalMem * 0.7\n // Use at least 1MB as baseline to avoid division by zero or huge numbers\n const perInstanceMem = Math.max(metrics.memDeltaBytes, 1024 * 1024)\n const maxMemConcurrency = Math.floor(safeMem / perInstanceMem)\n\n // CPU Limit:\n // If IO Bound (0.2% cpu), we can run many. 100% / 0.2% = 500 tasks per core.\n // We cap efficiency at a reasonable number to avoid Event Loop Lag density.\n const cpuEfficiencyFactor = 1 / Math.max(metrics.cpuRatio, 0.001) // Avoid div by 0\n const maxCpuConcurrency = Math.floor(cpus * cpuEfficiencyFactor)\n\n // 3. Synthesize Recommendation\n const safe = Math.min(maxMemConcurrency, 200) // Hard cap at 200 for sanity\n let efficient = Math.min(maxCpuConcurrency, 200)\n\n // If CPU bound, strict limit based on cores\n if (type === 'CPU_BOUND') {\n efficient = cpus // 1:1 mapping is best for CPU bound\n }\n\n const recommended = Math.min(safe, efficient)\n\n let reason = ''\n if (type === 'IO_BOUND') {\n reason = `Workflow is I/O intensive (CPU usage ${(metrics.cpuRatio * 100).toFixed(1)}%). It is safe to run high concurrency up to ${recommended}.`\n } else if (type === 'CPU_BOUND') {\n reason = `Workflow is CPU intensive. Limiting concurrency to match CPU cores (${cpus}) is recommended to prevent blocking.`\n } else {\n reason = `Workflow consumes significant memory (${(metrics.memDeltaBytes / 1024 / 1024).toFixed(1)}MB). Concurrency limited by available RAM.`\n }\n\n if (config?.configuredConcurrency && config.configuredConcurrency > recommended) {\n reason += ` \\n⚠️ Warning: Your current setting (${config.configuredConcurrency}) exceeds the recommended limit (${recommended}).`\n }\n\n return {\n type,\n safeConcurrency: safe,\n efficientConcurrency: efficient,\n suggestedConcurrency: `${Math.max(1, Math.floor(recommended * 0.5))} - ${recommended}`,\n reason,\n }\n }\n}\n","/**\n * @fileoverview @gravito/flux - Platform-agnostic Workflow Engine\n *\n * High-performance, type-safe workflow engine with Bun optimizations.\n *\n * @example Basic Usage\n * ```typescript\n * import { FluxEngine, createWorkflow } from '@gravito/flux'\n *\n * const workflow = createWorkflow('order-process')\n * .input<{ orderId: string }>()\n * .step('validate', async (ctx) => {\n * ctx.data.order = await fetchOrder(ctx.input.orderId)\n * })\n * .step('process', async (ctx) => {\n * await processPayment(ctx.data.order)\n * })\n * .commit('notify', async (ctx) => {\n * await sendEmail(ctx.data.order.email)\n * })\n *\n * const engine = new FluxEngine()\n * const result = await engine.execute(workflow, { orderId: '123' })\n * ```\n *\n * @module @gravito/flux\n */\n\n// Builder\nexport { createWorkflow, WorkflowBuilder } from './builder/WorkflowBuilder'\nexport { ContextManager } from './core/ContextManager'\n// Core (for advanced usage)\nexport { StateMachine } from './core/StateMachine'\nexport { StepExecutor } from './core/StepExecutor'\n// Core\nexport { FluxEngine } from './engine/FluxEngine'\n// Logger\nexport { FluxConsoleLogger, FluxSilentLogger } from './logger/FluxLogger'\n// Gravito Integration\nexport { OrbitFlux, type OrbitFluxOptions } from './orbit/OrbitFlux'\n// Profiler\nexport {\n type ProfileMetrics,\n type ProfileRecommendation,\n WorkflowProfiler,\n} from './profiler/WorkflowProfiler'\nexport { BunSQLiteStorage, type BunSQLiteStorageOptions } from './storage/BunSQLiteStorage'\n// Storage\nexport { MemoryStorage } from './storage/MemoryStorage'\n// Trace\nexport { JsonFileTraceSink } from './trace/JsonFileTraceSink'\n\n// Types\nexport type {\n // Config\n FluxConfig,\n // Logger\n FluxLogger,\n FluxResult,\n // Trace\n FluxTraceEvent,\n FluxTraceEventType,\n FluxTraceSink,\n // Helper\n FluxWaitResult,\n // Step types\n StepDefinition,\n StepDescriptor,\n StepExecution,\n StepResult,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowDescriptor,\n WorkflowFilter,\n WorkflowState,\n // Core types\n WorkflowStatus,\n // Storage\n WorkflowStorage,\n} from './types'\n\n/**\n * Flux helper utilities\n */\nexport const Flux = {\n /**\n * Suspend workflow execution and wait for a signal\n *\n * @param signal - Signal name to wait for\n */\n wait: (signal: string): import('./types').FluxWaitResult => ({\n __kind: 'flux_wait',\n signal,\n }),\n}\n"],"mappings":"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","names":["cpus"]}
1
+ {"version":3,"sources":["../src/profiler/WorkflowProfiler.ts","../src/index.ts"],"sourcesContent":["import * as os from 'node:os'\nimport { FluxEngine } from '../engine/FluxEngine'\nimport { FluxSilentLogger } from '../logger/FluxLogger'\nimport type { WorkflowDefinition } from '../types'\n\n/**\n * Performance metrics captured during a workflow profiling session.\n *\n * Used to quantify the resource footprint of a workflow execution, enabling\n * data-driven decisions for infrastructure scaling and concurrency tuning.\n *\n * @public\n */\nexport interface ProfileMetrics {\n /** Total wall-clock duration of the workflow execution in milliseconds. */\n durationMs: number\n /** Amount of time spent in user-space CPU operations in milliseconds. */\n cpuUserMs: number\n /** Amount of time spent in system-space CPU operations in milliseconds. */\n cpuSysMs: number\n /** Estimated heap memory increase during execution in bytes. */\n memDeltaBytes: number\n /** Ratio of CPU time to wall-clock time (0.0 to 1.0+). Higher values indicate CPU-bound tasks. */\n cpuRatio: number\n}\n\n/**\n * Concurrency recommendations generated by the profiler.\n *\n * Provides actionable insights into how many instances of a workflow can safely\n * and efficiently run in parallel on the current hardware.\n *\n * @public\n */\nexport interface ProfileRecommendation {\n /** The identified primary bottleneck type. */\n type: 'IO_BOUND' | 'CPU_BOUND' | 'MEMORY_BOUND'\n /** Maximum safe concurrency considering memory and system stability. */\n safeConcurrency: number\n /** Most efficient concurrency level considering CPU utilization. */\n efficientConcurrency: number\n /** A suggested range for worker concurrency configuration. */\n suggestedConcurrency: string\n /** Detailed explanation for the recommendation. */\n reason: string\n}\n\n/**\n * WorkflowProfiler analyzes workflow performance characteristics.\n *\n * It measures CPU usage, memory consumption, and execution duration to recommend\n * optimal concurrency settings for Gravito Quasar workers or high-throughput consumers.\n *\n * @example\n * ```typescript\n * const profiler = new WorkflowProfiler();\n * const metrics = await profiler.profile(myWorkflow, { input: 'data' });\n * const advice = profiler.recommend(metrics);\n * console.log(`Suggested concurrency: ${advice.suggestedConcurrency}`);\n * ```\n *\n * @public\n */\nexport class WorkflowProfiler {\n /**\n * Initializes the profiler with an optional engine.\n *\n * @param engine - The FluxEngine instance to use for execution. If omitted, a silent engine is created.\n */\n constructor(private engine?: FluxEngine) {\n if (!this.engine) {\n // Default minimal engine for profiling (Silent)\n this.engine = new FluxEngine({\n logger: new FluxSilentLogger(),\n })\n }\n }\n\n /**\n * Executes a workflow and captures its resource consumption metrics.\n *\n * Performs a warmup run to ensure JIT optimization before measurement.\n *\n * @param workflow - The workflow definition to profile.\n * @param input - The input data for the workflow execution.\n * @returns A promise resolving to the captured performance metrics.\n *\n * @example\n * ```typescript\n * const metrics = await profiler.profile(orderWorkflow, { id: '123' });\n * console.log(`Duration: ${metrics.durationMs}ms`);\n * ```\n */\n async profile<TInput>(\n workflow: WorkflowDefinition<TInput, any>,\n input: TInput\n ): Promise<ProfileMetrics> {\n // 1. Warmup (JIT)\n try {\n await this.engine?.execute(workflow, input)\n } catch {}\n\n // 2. Measure\n if (global.gc) {\n global.gc()\n }\n\n const startCpu = process.cpuUsage()\n const startMem = process.memoryUsage().heapUsed\n const startTime = process.hrtime.bigint()\n\n await this.engine?.execute(workflow, input)\n\n const endTime = process.hrtime.bigint()\n const endCpu = process.cpuUsage(startCpu)\n const endMem = process.memoryUsage().heapUsed\n\n // 3. Calculate\n const durationNs = Number(endTime - startTime)\n const durationMs = durationNs / 1_000_000\n const cpuUserMs = endCpu.user / 1000\n const cpuSysMs = endCpu.system / 1000\n const totalCpuMs = cpuUserMs + cpuSysMs\n const memDeltaBytes = Math.max(0, endMem - startMem) // Clamp to 0\n\n // CPU Ratio: How much % of the time was spent on CPU vs Waiting\n const cpuRatio = totalCpuMs / durationMs\n\n return {\n durationMs,\n cpuUserMs,\n cpuSysMs,\n memDeltaBytes,\n cpuRatio,\n }\n }\n\n /**\n * Analyzes metrics to generate concurrency recommendations.\n *\n * Considers system CPU cores and total memory to calculate safe and efficient limits.\n *\n * @param metrics - The metrics captured during a profiling session.\n * @param config - Optional current configuration to check against recommendations.\n * @returns A recommendation object containing bottleneck analysis and concurrency limits.\n *\n * @example\n * ```typescript\n * const advice = profiler.recommend(metrics, { configuredConcurrency: 10 });\n * if (advice.type === 'CPU_BOUND') {\n * console.warn('Workflow is CPU bound, consider reducing concurrency');\n * }\n * ```\n */\n recommend(\n metrics: ProfileMetrics,\n config?: { configuredConcurrency?: number }\n ): ProfileRecommendation {\n const totalMem = os.totalmem()\n const cpus = os.cpus().length\n\n // 1. Analyze Bottleneck Type\n let type: ProfileRecommendation['type'] = 'IO_BOUND'\n if (metrics.cpuRatio > 0.5) {\n type = 'CPU_BOUND'\n } else if (metrics.memDeltaBytes > 50 * 1024 * 1024) {\n // > 50MB per run\n type = 'MEMORY_BOUND'\n }\n\n // 2. Calculate Limits\n\n // Memory Limit: Keep 30% buffer for system, divide rest by per-workflow memory\n const safeMem = totalMem * 0.7\n // Use at least 1MB as baseline to avoid division by zero or huge numbers\n const perInstanceMem = Math.max(metrics.memDeltaBytes, 1024 * 1024)\n const maxMemConcurrency = Math.floor(safeMem / perInstanceMem)\n\n // CPU Limit:\n // If IO Bound (0.2% cpu), we can run many. 100% / 0.2% = 500 tasks per core.\n // We cap efficiency at a reasonable number to avoid Event Loop Lag density.\n const cpuEfficiencyFactor = 1 / Math.max(metrics.cpuRatio, 0.001) // Avoid div by 0\n const maxCpuConcurrency = Math.floor(cpus * cpuEfficiencyFactor)\n\n // 3. Synthesize Recommendation\n const safe = Math.min(maxMemConcurrency, 200) // Hard cap at 200 for sanity\n let efficient = Math.min(maxCpuConcurrency, 200)\n\n // If CPU bound, strict limit based on cores\n if (type === 'CPU_BOUND') {\n efficient = cpus // 1:1 mapping is best for CPU bound\n }\n\n const recommended = Math.min(safe, efficient)\n\n let reason = ''\n if (type === 'IO_BOUND') {\n reason = `Workflow is I/O intensive (CPU usage ${(metrics.cpuRatio * 100).toFixed(1)}%). It is safe to run high concurrency up to ${recommended}.`\n } else if (type === 'CPU_BOUND') {\n reason = `Workflow is CPU intensive. Limiting concurrency to match CPU cores (${cpus}) is recommended to prevent blocking.`\n } else {\n reason = `Workflow consumes significant memory (${(metrics.memDeltaBytes / 1024 / 1024).toFixed(1)}MB). Concurrency limited by available RAM.`\n }\n\n if (config?.configuredConcurrency && config.configuredConcurrency > recommended) {\n reason += ` \\n⚠️ Warning: Your current setting (${config.configuredConcurrency}) exceeds the recommended limit (${recommended}).`\n }\n\n return {\n type,\n safeConcurrency: safe,\n efficientConcurrency: efficient,\n suggestedConcurrency: `${Math.max(1, Math.floor(recommended * 0.5))} - ${recommended}`,\n reason,\n }\n }\n}\n","/**\n * @fileoverview @gravito/flux - Platform-agnostic Workflow Engine\n *\n * High-performance, type-safe workflow engine with Bun optimizations.\n *\n * @example Basic Usage\n * ```typescript\n * import { FluxEngine, createWorkflow } from '@gravito/flux'\n *\n * const workflow = createWorkflow('order-process')\n * .input<{ orderId: string }>()\n * .step('validate', async (ctx) => {\n * ctx.data.order = await fetchOrder(ctx.input.orderId)\n * })\n * .step('process', async (ctx) => {\n * await processPayment(ctx.data.order)\n * })\n * .commit('notify', async (ctx) => {\n * await sendEmail(ctx.data.order.email)\n * })\n *\n * const engine = new FluxEngine()\n * const result = await engine.execute(workflow, { orderId: '123' })\n * ```\n *\n * @module @gravito/flux\n */\n\n// Builder\nexport { createWorkflow, WorkflowBuilder } from './builder/WorkflowBuilder'\nexport { ContextManager } from './core/ContextManager'\nexport { type Lock, type LockProvider, MemoryLockProvider } from './core/LockProvider'\nexport {\n type RedisClient,\n RedisLockProvider,\n type RedisLockProviderOptions,\n} from './core/RedisLockProvider'\n// Core (for advanced usage)\nexport { StateMachine } from './core/StateMachine'\nexport { StepExecutor } from './core/StepExecutor'\nexport {\n type BatchExecutionOptions,\n BatchExecutor,\n type BatchItemResult,\n type BatchResult,\n} from './engine/BatchExecutor'\n// Core\nexport { FluxEngine } from './engine/FluxEngine'\n// Errors\nexport {\n cannotRemoveRoot,\n cannotReplaceRoot,\n emptyWorkflow,\n FluxError,\n FluxErrorCode,\n invalidInput,\n invalidJsonPointer,\n invalidPathTraversal,\n invalidStateTransition,\n invalidStepIndex,\n noRecoveryAction,\n stepNotFound,\n workflowDefinitionChanged,\n workflowNameMismatch,\n workflowNotFound,\n workflowNotSuspended,\n} from './errors'\n// Logger\nexport { FluxConsoleLogger, FluxSilentLogger } from './logger/FluxLogger'\nexport { CronTrigger } from './orbit/CronTrigger'\n// Gravito Integration\nexport { OrbitFlux, type OrbitFluxOptions } from './orbit/OrbitFlux'\n// Profiler\nexport {\n type ProfileMetrics,\n type ProfileRecommendation,\n WorkflowProfiler,\n} from './profiler/WorkflowProfiler'\nexport { BunSQLiteStorage, type BunSQLiteStorageOptions } from './storage/BunSQLiteStorage'\n// Storage\nexport { MemoryStorage } from './storage/MemoryStorage'\nexport { PostgreSQLStorage, type PostgreSQLStorageOptions } from './storage/PostgreSQLStorage'\n// Trace\nexport { JsonFileTraceSink } from './trace/JsonFileTraceSink'\n// Types\nexport type {\n CronScheduleOptions,\n // Config\n FluxConfig,\n // Logger\n FluxLogger,\n FluxResult,\n // Trace\n FluxTraceEvent,\n FluxTraceEventType,\n FluxTraceSink,\n // Helper\n FluxWaitResult,\n // Step types\n StepDefinition,\n StepDescriptor,\n StepExecution,\n StepResult,\n WorkflowContext,\n WorkflowDefinition,\n WorkflowDescriptor,\n WorkflowFilter,\n WorkflowState,\n // Core types\n WorkflowStatus,\n // Storage\n WorkflowStorage,\n} from './types'\n// Visualization\nexport { MermaidGenerator, type MermaidOptions } from './visualization/MermaidGenerator'\n\n/**\n * Flux helper utilities for workflow control flow.\n *\n * Provides methods to interact with the workflow engine's special behaviors,\n * such as suspending execution to wait for external signals.\n */\nexport const Flux = {\n /**\n * Suspends workflow execution until a specific signal is received.\n *\n * When a handler returns this result, the engine saves the current state\n * and stops execution. The workflow can be resumed later using `engine.signal()`.\n *\n * @param signal - The unique identifier for the signal to wait for.\n * @returns A special result object that instructs the engine to suspend.\n *\n * @example\n * ```typescript\n * .step('wait-for-approval', async (ctx) => {\n * return Flux.wait('manager-approval');\n * })\n * ```\n */\n wait: (signal: string): import('./types').FluxWaitResult => ({\n __kind: 'flux_wait',\n signal,\n }),\n}\n"],"mappings":"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","names":["cpus"]}