@gravito/flux 3.0.3 → 4.0.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.
@@ -1,4 +1,121 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/storage/BunSQLiteStorage.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/errors.ts
2
+ var _core = require('@gravito/core');
3
+ var FluxErrorCode = /* @__PURE__ */ ((FluxErrorCode2) => {
4
+ FluxErrorCode2["WORKFLOW_NOT_FOUND"] = "WORKFLOW_NOT_FOUND";
5
+ FluxErrorCode2["WORKFLOW_INVALID_INPUT"] = "WORKFLOW_INVALID_INPUT";
6
+ FluxErrorCode2["WORKFLOW_DEFINITION_CHANGED"] = "WORKFLOW_DEFINITION_CHANGED";
7
+ FluxErrorCode2["WORKFLOW_NAME_MISMATCH"] = "WORKFLOW_NAME_MISMATCH";
8
+ FluxErrorCode2["INVALID_STATE_TRANSITION"] = "INVALID_STATE_TRANSITION";
9
+ FluxErrorCode2["WORKFLOW_NOT_SUSPENDED"] = "WORKFLOW_NOT_SUSPENDED";
10
+ FluxErrorCode2["INVALID_STEP_INDEX"] = "INVALID_STEP_INDEX";
11
+ FluxErrorCode2["STEP_TIMEOUT"] = "STEP_TIMEOUT";
12
+ FluxErrorCode2["STEP_NOT_FOUND"] = "STEP_NOT_FOUND";
13
+ FluxErrorCode2["CONCURRENT_MODIFICATION"] = "CONCURRENT_MODIFICATION";
14
+ FluxErrorCode2["EMPTY_WORKFLOW"] = "EMPTY_WORKFLOW";
15
+ FluxErrorCode2["NO_RECOVERY_ACTION"] = "NO_RECOVERY_ACTION";
16
+ FluxErrorCode2["INVALID_JSON_POINTER"] = "INVALID_JSON_POINTER";
17
+ FluxErrorCode2["INVALID_PATH_TRAVERSAL"] = "INVALID_PATH_TRAVERSAL";
18
+ FluxErrorCode2["CANNOT_REPLACE_ROOT"] = "CANNOT_REPLACE_ROOT";
19
+ FluxErrorCode2["CANNOT_REMOVE_ROOT"] = "CANNOT_REMOVE_ROOT";
20
+ return FluxErrorCode2;
21
+ })(FluxErrorCode || {});
22
+ var FluxError = class extends _core.QueueException {
23
+ /**
24
+ * Additional metadata related to the error.
25
+ */
26
+
27
+ /**
28
+ * Creates a new FluxError.
29
+ *
30
+ * @param message - Human-readable error description.
31
+ * @param code - Machine-readable error code (FluxErrorCode enum value).
32
+ * @param context - Additional metadata related to the error.
33
+ */
34
+ constructor(message, code, context) {
35
+ const options = { message };
36
+ super(422, code, options);
37
+ this.name = "FluxError";
38
+ this.context = context;
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ }
41
+ };
42
+ function workflowNotFound(id) {
43
+ return new FluxError(`Workflow not found: ${id}`, "WORKFLOW_NOT_FOUND" /* WORKFLOW_NOT_FOUND */, {
44
+ workflowId: id
45
+ });
46
+ }
47
+ function invalidStateTransition(from, to) {
48
+ return new FluxError(
49
+ `Invalid state transition: ${from} \u2192 ${to}`,
50
+ "INVALID_STATE_TRANSITION" /* INVALID_STATE_TRANSITION */,
51
+ { from, to }
52
+ );
53
+ }
54
+ function invalidInput(workflowName) {
55
+ return new FluxError(
56
+ `Invalid input for workflow "${workflowName}"`,
57
+ "WORKFLOW_INVALID_INPUT" /* WORKFLOW_INVALID_INPUT */,
58
+ { workflowName }
59
+ );
60
+ }
61
+ function workflowNameMismatch(expected, received) {
62
+ return new FluxError(
63
+ `Workflow name mismatch: ${received} !== ${expected}`,
64
+ "WORKFLOW_NAME_MISMATCH" /* WORKFLOW_NAME_MISMATCH */,
65
+ { expected, received }
66
+ );
67
+ }
68
+ function workflowDefinitionChanged() {
69
+ return new FluxError(
70
+ "Workflow definition changed; operation is not safe",
71
+ "WORKFLOW_DEFINITION_CHANGED" /* WORKFLOW_DEFINITION_CHANGED */
72
+ );
73
+ }
74
+ function workflowNotSuspended(status) {
75
+ return new FluxError(
76
+ `Workflow is not suspended (status: ${status})`,
77
+ "WORKFLOW_NOT_SUSPENDED" /* WORKFLOW_NOT_SUSPENDED */,
78
+ { status }
79
+ );
80
+ }
81
+ function stepNotFound(step) {
82
+ return new FluxError(`Step not found: ${step}`, "STEP_NOT_FOUND" /* STEP_NOT_FOUND */, { step });
83
+ }
84
+ function invalidStepIndex(index) {
85
+ return new FluxError(`Invalid step index: ${index}`, "INVALID_STEP_INDEX" /* INVALID_STEP_INDEX */, { index });
86
+ }
87
+ function emptyWorkflow(workflowName) {
88
+ return new FluxError(`Workflow "${workflowName}" has no steps`, "EMPTY_WORKFLOW" /* EMPTY_WORKFLOW */, {
89
+ workflowName
90
+ });
91
+ }
92
+ function noRecoveryAction(stepName) {
93
+ return new FluxError(
94
+ `No recovery action registered for step: ${stepName}`,
95
+ "NO_RECOVERY_ACTION" /* NO_RECOVERY_ACTION */,
96
+ { stepName }
97
+ );
98
+ }
99
+ function invalidJsonPointer(path) {
100
+ return new FluxError(`Invalid JSON Pointer: ${path}`, "INVALID_JSON_POINTER" /* INVALID_JSON_POINTER */, {
101
+ path
102
+ });
103
+ }
104
+ function invalidPathTraversal(segment, current) {
105
+ return new FluxError(
106
+ `Cannot access property '${segment}' on ${current}`,
107
+ "INVALID_PATH_TRAVERSAL" /* INVALID_PATH_TRAVERSAL */,
108
+ { segment, currentType: typeof current }
109
+ );
110
+ }
111
+ function cannotReplaceRoot() {
112
+ return new FluxError("Cannot replace root object", "CANNOT_REPLACE_ROOT" /* CANNOT_REPLACE_ROOT */);
113
+ }
114
+ function cannotRemoveRoot() {
115
+ return new FluxError("Cannot remove root object", "CANNOT_REMOVE_ROOT" /* CANNOT_REMOVE_ROOT */);
116
+ }
117
+
118
+ // src/storage/BunSQLiteStorage.ts
2
119
  var _bunsqlite = require('bun:sqlite');
3
120
  var BunSQLiteStorage = (_class = class {
4
121
 
@@ -217,8 +334,10 @@ var BunSQLiteStorage = (_class = class {
217
334
  }, _class);
218
335
  function validateSqlIdentifier(value, field) {
219
336
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
220
- throw new Error(
221
- `Invalid ${field}: "${value}". Only letters, numbers, and underscores are allowed.`
337
+ throw new FluxError(
338
+ `Invalid ${field}: "${value}". Only letters, numbers, and underscores are allowed.`,
339
+ "WORKFLOW_INVALID_INPUT" /* WORKFLOW_INVALID_INPUT */,
340
+ { field, value }
222
341
  );
223
342
  }
224
343
  return value;
@@ -226,5 +345,21 @@ function validateSqlIdentifier(value, field) {
226
345
 
227
346
 
228
347
 
229
- exports.BunSQLiteStorage = BunSQLiteStorage;
230
- //# sourceMappingURL=chunk-ZE2RDS47.cjs.map
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+ exports.FluxErrorCode = FluxErrorCode; exports.FluxError = FluxError; exports.workflowNotFound = workflowNotFound; exports.invalidStateTransition = invalidStateTransition; exports.invalidInput = invalidInput; exports.workflowNameMismatch = workflowNameMismatch; exports.workflowDefinitionChanged = workflowDefinitionChanged; exports.workflowNotSuspended = workflowNotSuspended; exports.stepNotFound = stepNotFound; exports.invalidStepIndex = invalidStepIndex; exports.emptyWorkflow = emptyWorkflow; exports.noRecoveryAction = noRecoveryAction; exports.invalidJsonPointer = invalidJsonPointer; exports.invalidPathTraversal = invalidPathTraversal; exports.cannotReplaceRoot = cannotReplaceRoot; exports.cannotRemoveRoot = cannotRemoveRoot; exports.BunSQLiteStorage = BunSQLiteStorage;
365
+ //# sourceMappingURL=chunk-OAJWPPYG.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/chunk-OAJWPPYG.cjs","../src/errors.ts","../src/storage/BunSQLiteStorage.ts"],"names":["FluxErrorCode"],"mappings":"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","file":"/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/chunk-OAJWPPYG.cjs","sourcesContent":[null,"import { QueueException, type InfrastructureExceptionOptions } from '@gravito/core'\n\n/**\n * Standard error codes for FluxEngine operations.\n *\n * Used to programmatically identify the cause of a `FluxError`.\n */\nexport enum FluxErrorCode {\n /** The requested workflow instance could not be found in storage. */\n WORKFLOW_NOT_FOUND = 'WORKFLOW_NOT_FOUND',\n /** The input data provided to the workflow failed validation. */\n WORKFLOW_INVALID_INPUT = 'WORKFLOW_INVALID_INPUT',\n /** The workflow definition has changed since the instance was created, making it unsafe to resume. */\n WORKFLOW_DEFINITION_CHANGED = 'WORKFLOW_DEFINITION_CHANGED',\n /** The workflow name in the definition does not match the stored state. */\n WORKFLOW_NAME_MISMATCH = 'WORKFLOW_NAME_MISMATCH',\n /** An attempt was made to transition the workflow to an incompatible state. */\n INVALID_STATE_TRANSITION = 'INVALID_STATE_TRANSITION',\n /** An operation requiring a suspended state was attempted on a workflow that is not suspended. */\n WORKFLOW_NOT_SUSPENDED = 'WORKFLOW_NOT_SUSPENDED',\n /** The requested step index is out of bounds for the current workflow definition. */\n INVALID_STEP_INDEX = 'INVALID_STEP_INDEX',\n /** A workflow step exceeded its configured execution time limit. */\n STEP_TIMEOUT = 'STEP_TIMEOUT',\n /** The requested step could not be found in the workflow definition. */\n STEP_NOT_FOUND = 'STEP_NOT_FOUND',\n /** Multiple concurrent attempts to modify the same workflow instance were detected. */\n CONCURRENT_MODIFICATION = 'CONCURRENT_MODIFICATION',\n /** A workflow definition must contain at least one step to be executable. */\n EMPTY_WORKFLOW = 'EMPTY_WORKFLOW',\n /** No recovery action is registered for a step that requires recovery. */\n NO_RECOVERY_ACTION = 'NO_RECOVERY_ACTION',\n /** An invalid JSON Pointer was provided for state manipulation. */\n INVALID_JSON_POINTER = 'INVALID_JSON_POINTER',\n /** Cannot access a property on a non-object value in the state tree. */\n INVALID_PATH_TRAVERSAL = 'INVALID_PATH_TRAVERSAL',\n /** Cannot replace the root object of the workflow state. */\n CANNOT_REPLACE_ROOT = 'CANNOT_REPLACE_ROOT',\n /** Cannot remove the root object of the workflow state. */\n CANNOT_REMOVE_ROOT = 'CANNOT_REMOVE_ROOT',\n}\n\n/**\n * Namespace of dot-separated flux error codes for use with FluxErrorCodes const.\n * Maps enum values to `flux.*` namespace per GravitoException convention.\n */\nexport const FluxErrorCodes = {\n WORKFLOW_NOT_FOUND: 'flux.workflow_not_found',\n WORKFLOW_INVALID_INPUT: 'flux.workflow_invalid_input',\n WORKFLOW_DEFINITION_CHANGED: 'flux.workflow_definition_changed',\n WORKFLOW_NAME_MISMATCH: 'flux.workflow_name_mismatch',\n INVALID_STATE_TRANSITION: 'flux.invalid_state_transition',\n WORKFLOW_NOT_SUSPENDED: 'flux.workflow_not_suspended',\n INVALID_STEP_INDEX: 'flux.invalid_step_index',\n STEP_TIMEOUT: 'flux.step_timeout',\n STEP_NOT_FOUND: 'flux.step_not_found',\n CONCURRENT_MODIFICATION: 'flux.concurrent_modification',\n EMPTY_WORKFLOW: 'flux.empty_workflow',\n NO_RECOVERY_ACTION: 'flux.no_recovery_action',\n INVALID_JSON_POINTER: 'flux.invalid_json_pointer',\n INVALID_PATH_TRAVERSAL: 'flux.invalid_path_traversal',\n CANNOT_REPLACE_ROOT: 'flux.cannot_replace_root',\n CANNOT_REMOVE_ROOT: 'flux.cannot_remove_root',\n} as const\n\n/**\n * Base class for all errors thrown by the FluxEngine.\n *\n * Extends QueueException from @gravito/core, enabling consistent infrastructure\n * error handling across the GravitoException hierarchy.\n *\n * Includes a machine-readable error code and optional context for debugging.\n *\n * @example\n * ```typescript\n * try {\n * await engine.execute(flow, input);\n * } catch (err) {\n * if (err instanceof FluxError && err.code === FluxErrorCode.STEP_TIMEOUT) {\n * console.error('Workflow timed out');\n * }\n * }\n * ```\n */\nexport class FluxError extends QueueException {\n /**\n * Additional metadata related to the error.\n */\n public readonly context?: Record<string, unknown>\n\n /**\n * Creates a new FluxError.\n *\n * @param message - Human-readable error description.\n * @param code - Machine-readable error code (FluxErrorCode enum value).\n * @param context - Additional metadata related to the error.\n */\n constructor(\n message: string,\n code: FluxErrorCode | string,\n context?: Record<string, unknown>\n ) {\n const options: InfrastructureExceptionOptions = { message }\n super(422, code, options)\n this.name = 'FluxError'\n this.context = context\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\n/**\n * Creates a FluxError for a missing workflow instance.\n *\n * @param id - The unique identifier of the missing workflow.\n * @returns A FluxError with the WORKFLOW_NOT_FOUND code.\n *\n * @example\n * ```typescript\n * throw workflowNotFound('wf-123');\n * ```\n */\nexport function workflowNotFound(id: string): FluxError {\n return new FluxError(`Workflow not found: ${id}`, FluxErrorCode.WORKFLOW_NOT_FOUND, {\n workflowId: id,\n })\n}\n\n/**\n * Creates a FluxError for an illegal state transition.\n *\n * @param from - The current state of the workflow.\n * @param to - The attempted target state.\n * @returns A FluxError with the INVALID_STATE_TRANSITION code.\n *\n * @example\n * ```typescript\n * throw invalidStateTransition('completed', 'running');\n * ```\n */\nexport function invalidStateTransition(from: string, to: string): FluxError {\n return new FluxError(\n `Invalid state transition: ${from} → ${to}`,\n FluxErrorCode.INVALID_STATE_TRANSITION,\n { from, to }\n )\n}\n\n/**\n * Creates a FluxError for invalid workflow input.\n *\n * @param workflowName - The name of the workflow definition.\n * @returns A FluxError with the WORKFLOW_INVALID_INPUT code.\n *\n * @example\n * ```typescript\n * throw invalidInput('order-process');\n * ```\n */\nexport function invalidInput(workflowName: string): FluxError {\n return new FluxError(\n `Invalid input for workflow \"${workflowName}\"`,\n FluxErrorCode.WORKFLOW_INVALID_INPUT,\n { workflowName }\n )\n}\n\n/**\n * Creates a FluxError for a workflow name mismatch.\n *\n * @param expected - The name expected by the definition.\n * @param received - The name found in the stored state.\n * @returns A FluxError with the WORKFLOW_NAME_MISMATCH code.\n */\nexport function workflowNameMismatch(expected: string, received: string): FluxError {\n return new FluxError(\n `Workflow name mismatch: ${received} !== ${expected}`,\n FluxErrorCode.WORKFLOW_NAME_MISMATCH,\n { expected, received }\n )\n}\n\n/**\n * Creates a FluxError when a workflow definition has changed incompatibly.\n *\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n */\nexport function workflowDefinitionChanged(): FluxError {\n return new FluxError(\n 'Workflow definition changed; operation is not safe',\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED\n )\n}\n\n/**\n * Creates a FluxError for a workflow version mismatch.\n *\n * @param stored - The version stored in the workflow instance.\n * @param current - The version in the current workflow definition.\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n *\n * @example\n * ```typescript\n * throw workflowVersionMismatch('1.0.0', '2.0.0');\n * ```\n */\nexport function workflowVersionMismatch(stored: string, current: string): FluxError {\n return new FluxError(\n `Workflow version mismatch: stored version \"${stored}\" does not match current \"${current}\"`,\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED,\n { storedVersion: stored, currentVersion: current }\n )\n}\n\n/**\n * Creates a FluxError when an operation requires a suspended workflow.\n *\n * @param status - The current status of the workflow.\n * @returns A FluxError with the WORKFLOW_NOT_SUSPENDED code.\n */\nexport function workflowNotSuspended(status: string): FluxError {\n return new FluxError(\n `Workflow is not suspended (status: ${status})`,\n FluxErrorCode.WORKFLOW_NOT_SUSPENDED,\n { status }\n )\n}\n\n/**\n * Creates a FluxError when a specific step cannot be found.\n *\n * @param step - The name or index of the missing step.\n * @returns A FluxError with the STEP_NOT_FOUND code.\n */\nexport function stepNotFound(step: string | number): FluxError {\n return new FluxError(`Step not found: ${step}`, FluxErrorCode.STEP_NOT_FOUND, { step })\n}\n\n/**\n * Creates a FluxError for an out-of-bounds step index.\n *\n * @param index - The invalid step index.\n * @returns A FluxError with the INVALID_STEP_INDEX code.\n */\nexport function invalidStepIndex(index: number): FluxError {\n return new FluxError(`Invalid step index: ${index}`, FluxErrorCode.INVALID_STEP_INDEX, { index })\n}\n\n/**\n * Creates a FluxError for an empty workflow (no steps defined).\n *\n * @param workflowName - The name of the workflow.\n * @returns A FluxError with the EMPTY_WORKFLOW code.\n */\nexport function emptyWorkflow(workflowName: string): FluxError {\n return new FluxError(`Workflow \"${workflowName}\" has no steps`, FluxErrorCode.EMPTY_WORKFLOW, {\n workflowName,\n })\n}\n\n/**\n * Creates a FluxError when no recovery action is registered for a step.\n *\n * @param stepName - The name of the step requiring recovery.\n * @returns A FluxError with the NO_RECOVERY_ACTION code.\n */\nexport function noRecoveryAction(stepName: string): FluxError {\n return new FluxError(\n `No recovery action registered for step: ${stepName}`,\n FluxErrorCode.NO_RECOVERY_ACTION,\n { stepName }\n )\n}\n\n/**\n * Creates a FluxError for invalid JSON Pointer syntax.\n *\n * @param path - The invalid JSON Pointer.\n * @returns A FluxError with the INVALID_JSON_POINTER code.\n */\nexport function invalidJsonPointer(path: string): FluxError {\n return new FluxError(`Invalid JSON Pointer: ${path}`, FluxErrorCode.INVALID_JSON_POINTER, {\n path,\n })\n}\n\n/**\n * Creates a FluxError when attempting to traverse a non-object value.\n *\n * @param segment - The property being accessed.\n * @param current - The current value type.\n * @returns A FluxError with the INVALID_PATH_TRAVERSAL code.\n */\nexport function invalidPathTraversal(segment: string, current: unknown): FluxError {\n return new FluxError(\n `Cannot access property '${segment}' on ${current}`,\n FluxErrorCode.INVALID_PATH_TRAVERSAL,\n { segment, currentType: typeof current }\n )\n}\n\n/**\n * Creates a FluxError when attempting to replace the root object.\n *\n * @returns A FluxError with the CANNOT_REPLACE_ROOT code.\n */\nexport function cannotReplaceRoot(): FluxError {\n return new FluxError('Cannot replace root object', FluxErrorCode.CANNOT_REPLACE_ROOT)\n}\n\n/**\n * Creates a FluxError when attempting to remove the root object.\n *\n * @returns A FluxError with the CANNOT_REMOVE_ROOT code.\n */\nexport function cannotRemoveRoot(): FluxError {\n return new FluxError('Cannot remove root object', FluxErrorCode.CANNOT_REMOVE_ROOT)\n}\n","import { Database } from 'bun:sqlite'\nimport type { WorkflowFilter, WorkflowState, WorkflowStorage } from '../types'\nimport { FluxError, FluxErrorCode } from '../errors'\n\n/**\n * Configuration options for the Bun SQLite storage adapter.\n */\nexport interface BunSQLiteStorageOptions {\n /**\n * Path to the SQLite database file.\n * Use ':memory:' for an ephemeral in-memory database.\n */\n path?: string\n /**\n * Name of the table used to store workflow states.\n */\n tableName?: string\n}\n\n/**\n * BunSQLiteStorage provides a persistent storage backend for Flux workflows using Bun's native SQLite module.\n *\n * It handles automatic table creation, indexing for performance, and serialization of workflow state\n * into a relational format.\n *\n * @example\n * ```typescript\n * const storage = new BunSQLiteStorage({\n * path: './workflows.db',\n * tableName: 'my_workflows'\n * });\n * await storage.init();\n * ```\n */\nexport class BunSQLiteStorage implements WorkflowStorage {\n private db: Database\n private tableName: string\n private initialized = false\n\n /**\n * Creates a new instance of BunSQLiteStorage.\n *\n * @param options - Configuration for the database connection and table naming.\n */\n constructor(options: BunSQLiteStorageOptions = {}) {\n this.db = new Database(options.path ?? ':memory:')\n this.tableName = validateSqlIdentifier(options.tableName ?? 'flux_workflows', 'tableName')\n }\n\n /**\n * Initializes the database schema and required indexes.\n *\n * This method is idempotent and will be called automatically by other operations if not invoked manually.\n *\n * @throws {Error} If the database schema cannot be created or indexes fail to initialize.\n */\n async init(): Promise<void> {\n if (this.initialized) {\n return\n }\n\n this.db.run(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n status TEXT NOT NULL,\n input TEXT NOT NULL,\n data TEXT NOT NULL,\n current_step INTEGER NOT NULL,\n history TEXT NOT NULL,\n error TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n completed_at TEXT,\n version INTEGER NOT NULL DEFAULT 1,\n definition_version TEXT\n )\n `)\n\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_name \n ON ${this.tableName}(name)\n `)\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_status \n ON ${this.tableName}(status)\n `)\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_created \n ON ${this.tableName}(created_at DESC)\n `)\n\n this.initialized = true\n }\n\n /**\n * Persists or updates a workflow state in the database.\n *\n * Uses an \"INSERT OR REPLACE\" strategy to ensure the latest state is always stored for a given ID.\n *\n * @param state - The current state of the workflow to be saved.\n * @throws {Error} If the database write operation fails or serialization errors occur.\n */\n async save(state: WorkflowState): Promise<void> {\n await this.init()\n\n const stmt = this.db.prepare(`\n INSERT OR REPLACE INTO ${this.tableName} \n (id, name, status, input, data, current_step, history, error, created_at, updated_at, completed_at, version, definition_version)\n VALUES ($id, $name, $status, $input, $data, $currentStep, $history, $error, $createdAt, $updatedAt, $completedAt, $version, $definitionVersion)\n `)\n\n stmt.run({\n $id: state.id,\n $name: state.name,\n $status: state.status,\n $input: JSON.stringify(state.input),\n $data: JSON.stringify(state.data),\n $currentStep: state.currentStep,\n $history: JSON.stringify(state.history),\n $error: state.error ?? null,\n $createdAt: state.createdAt.toISOString(),\n $updatedAt: state.updatedAt.toISOString(),\n $completedAt: state.completedAt?.toISOString() ?? null,\n $version: state.version,\n $definitionVersion: state.definitionVersion ?? null,\n })\n }\n\n /**\n * Retrieves a workflow state by its unique identifier.\n *\n * @param id - The unique ID of the workflow to load.\n * @returns The reconstructed workflow state, or null if no record is found.\n * @throws {Error} If the database query fails or deserialization of stored JSON fails.\n */\n async load(id: string): Promise<WorkflowState | null> {\n await this.init()\n\n const stmt = this.db.prepare(`\n SELECT * FROM ${this.tableName} WHERE id = $id\n `)\n\n const row = stmt.get({ $id: id }) as SQLiteRow | null\n\n if (!row) {\n return null\n }\n\n return this.rowToState(row)\n }\n\n /**\n * Lists workflow states based on the provided filtering criteria.\n *\n * Results are returned in descending order of creation time.\n *\n * @param filter - Criteria for filtering and paginating the results.\n * @returns An array of workflow states matching the filter.\n * @throws {Error} If the database query fails.\n */\n async list(filter?: WorkflowFilter): Promise<WorkflowState[]> {\n await this.init()\n\n let query = `SELECT * FROM ${this.tableName} WHERE 1=1`\n const params: Record<string, unknown> = {}\n\n if (filter?.name) {\n query += ' AND name = $name'\n params.$name = filter.name\n }\n\n if (filter?.status) {\n if (Array.isArray(filter.status)) {\n const placeholders = filter.status.map((_, i) => `$status${i}`).join(', ')\n query += ` AND status IN (${placeholders})`\n filter.status.forEach((s, i) => {\n params[`$status${i}`] = s\n })\n } else {\n query += ' AND status = $status'\n params.$status = filter.status\n }\n }\n\n if (filter?.version) {\n query += ' AND definition_version = $version'\n params.$version = filter.version\n }\n\n query += ' ORDER BY created_at DESC'\n\n if (filter?.limit) {\n query += ' LIMIT $limit'\n params.$limit = filter.limit\n }\n\n if (filter?.offset) {\n query += ' OFFSET $offset'\n params.$offset = filter.offset\n }\n\n const stmt = this.db.prepare(query)\n const rows = stmt.all(params as Record<string, any>) as SQLiteRow[]\n\n return rows.map((row) => this.rowToState(row))\n }\n\n /**\n * Deletes a workflow state from the database.\n *\n * @param id - The unique ID of the workflow to delete.\n * @throws {Error} If the database deletion fails.\n */\n async delete(id: string): Promise<void> {\n await this.init()\n\n const stmt = this.db.prepare(`\n DELETE FROM ${this.tableName} WHERE id = $id\n `)\n\n stmt.run({ $id: id })\n }\n\n /**\n * Closes the database connection and resets the initialization state.\n *\n * @throws {Error} If the database connection cannot be closed cleanly.\n */\n async close(): Promise<void> {\n this.db.close()\n this.initialized = false\n }\n\n /**\n * Converts a raw database row into a structured WorkflowState object.\n *\n * @param row - The raw SQLite row data.\n * @returns The parsed workflow state.\n * @private\n */\n private rowToState(row: SQLiteRow): WorkflowState {\n return {\n id: row.id,\n name: row.name,\n status: row.status as WorkflowState['status'],\n input: JSON.parse(row.input),\n data: JSON.parse(row.data),\n currentStep: row.current_step,\n history: JSON.parse(row.history),\n error: row.error ?? undefined,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n completedAt: row.completed_at ? new Date(row.completed_at) : undefined,\n version: row.version,\n definitionVersion: row.definition_version ?? undefined,\n }\n }\n\n /**\n * Provides direct access to the underlying Bun SQLite Database instance.\n *\n * Useful for performing custom queries or maintenance tasks.\n *\n * @returns The raw Database instance.\n */\n getDatabase(): Database {\n return this.db\n }\n\n /**\n * Performs a VACUUM operation to reclaim unused space and defragment the database.\n *\n * @throws {Error} If the VACUUM operation fails.\n */\n vacuum(): void {\n this.db.run('VACUUM')\n }\n}\n\nfunction validateSqlIdentifier(value: string, field: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {\n throw new FluxError(\n `Invalid ${field}: \"${value}\". Only letters, numbers, and underscores are allowed.`,\n FluxErrorCode.WORKFLOW_INVALID_INPUT,\n { field, value }\n )\n }\n return value\n}\n\n/**\n * Internal representation of a workflow record in the SQLite database.\n */\ninterface SQLiteRow {\n id: string\n name: string\n status: string\n input: string\n data: string\n current_step: number\n history: string\n error: string | null\n created_at: string\n updated_at: string\n completed_at: string | null\n version: number\n definition_version: string | null\n}\n"]}
@@ -1,3 +1,120 @@
1
+ // src/errors.ts
2
+ import { QueueException } from "@gravito/core";
3
+ var FluxErrorCode = /* @__PURE__ */ ((FluxErrorCode2) => {
4
+ FluxErrorCode2["WORKFLOW_NOT_FOUND"] = "WORKFLOW_NOT_FOUND";
5
+ FluxErrorCode2["WORKFLOW_INVALID_INPUT"] = "WORKFLOW_INVALID_INPUT";
6
+ FluxErrorCode2["WORKFLOW_DEFINITION_CHANGED"] = "WORKFLOW_DEFINITION_CHANGED";
7
+ FluxErrorCode2["WORKFLOW_NAME_MISMATCH"] = "WORKFLOW_NAME_MISMATCH";
8
+ FluxErrorCode2["INVALID_STATE_TRANSITION"] = "INVALID_STATE_TRANSITION";
9
+ FluxErrorCode2["WORKFLOW_NOT_SUSPENDED"] = "WORKFLOW_NOT_SUSPENDED";
10
+ FluxErrorCode2["INVALID_STEP_INDEX"] = "INVALID_STEP_INDEX";
11
+ FluxErrorCode2["STEP_TIMEOUT"] = "STEP_TIMEOUT";
12
+ FluxErrorCode2["STEP_NOT_FOUND"] = "STEP_NOT_FOUND";
13
+ FluxErrorCode2["CONCURRENT_MODIFICATION"] = "CONCURRENT_MODIFICATION";
14
+ FluxErrorCode2["EMPTY_WORKFLOW"] = "EMPTY_WORKFLOW";
15
+ FluxErrorCode2["NO_RECOVERY_ACTION"] = "NO_RECOVERY_ACTION";
16
+ FluxErrorCode2["INVALID_JSON_POINTER"] = "INVALID_JSON_POINTER";
17
+ FluxErrorCode2["INVALID_PATH_TRAVERSAL"] = "INVALID_PATH_TRAVERSAL";
18
+ FluxErrorCode2["CANNOT_REPLACE_ROOT"] = "CANNOT_REPLACE_ROOT";
19
+ FluxErrorCode2["CANNOT_REMOVE_ROOT"] = "CANNOT_REMOVE_ROOT";
20
+ return FluxErrorCode2;
21
+ })(FluxErrorCode || {});
22
+ var FluxError = class extends QueueException {
23
+ /**
24
+ * Additional metadata related to the error.
25
+ */
26
+ context;
27
+ /**
28
+ * Creates a new FluxError.
29
+ *
30
+ * @param message - Human-readable error description.
31
+ * @param code - Machine-readable error code (FluxErrorCode enum value).
32
+ * @param context - Additional metadata related to the error.
33
+ */
34
+ constructor(message, code, context) {
35
+ const options = { message };
36
+ super(422, code, options);
37
+ this.name = "FluxError";
38
+ this.context = context;
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ }
41
+ };
42
+ function workflowNotFound(id) {
43
+ return new FluxError(`Workflow not found: ${id}`, "WORKFLOW_NOT_FOUND" /* WORKFLOW_NOT_FOUND */, {
44
+ workflowId: id
45
+ });
46
+ }
47
+ function invalidStateTransition(from, to) {
48
+ return new FluxError(
49
+ `Invalid state transition: ${from} \u2192 ${to}`,
50
+ "INVALID_STATE_TRANSITION" /* INVALID_STATE_TRANSITION */,
51
+ { from, to }
52
+ );
53
+ }
54
+ function invalidInput(workflowName) {
55
+ return new FluxError(
56
+ `Invalid input for workflow "${workflowName}"`,
57
+ "WORKFLOW_INVALID_INPUT" /* WORKFLOW_INVALID_INPUT */,
58
+ { workflowName }
59
+ );
60
+ }
61
+ function workflowNameMismatch(expected, received) {
62
+ return new FluxError(
63
+ `Workflow name mismatch: ${received} !== ${expected}`,
64
+ "WORKFLOW_NAME_MISMATCH" /* WORKFLOW_NAME_MISMATCH */,
65
+ { expected, received }
66
+ );
67
+ }
68
+ function workflowDefinitionChanged() {
69
+ return new FluxError(
70
+ "Workflow definition changed; operation is not safe",
71
+ "WORKFLOW_DEFINITION_CHANGED" /* WORKFLOW_DEFINITION_CHANGED */
72
+ );
73
+ }
74
+ function workflowNotSuspended(status) {
75
+ return new FluxError(
76
+ `Workflow is not suspended (status: ${status})`,
77
+ "WORKFLOW_NOT_SUSPENDED" /* WORKFLOW_NOT_SUSPENDED */,
78
+ { status }
79
+ );
80
+ }
81
+ function stepNotFound(step) {
82
+ return new FluxError(`Step not found: ${step}`, "STEP_NOT_FOUND" /* STEP_NOT_FOUND */, { step });
83
+ }
84
+ function invalidStepIndex(index) {
85
+ return new FluxError(`Invalid step index: ${index}`, "INVALID_STEP_INDEX" /* INVALID_STEP_INDEX */, { index });
86
+ }
87
+ function emptyWorkflow(workflowName) {
88
+ return new FluxError(`Workflow "${workflowName}" has no steps`, "EMPTY_WORKFLOW" /* EMPTY_WORKFLOW */, {
89
+ workflowName
90
+ });
91
+ }
92
+ function noRecoveryAction(stepName) {
93
+ return new FluxError(
94
+ `No recovery action registered for step: ${stepName}`,
95
+ "NO_RECOVERY_ACTION" /* NO_RECOVERY_ACTION */,
96
+ { stepName }
97
+ );
98
+ }
99
+ function invalidJsonPointer(path) {
100
+ return new FluxError(`Invalid JSON Pointer: ${path}`, "INVALID_JSON_POINTER" /* INVALID_JSON_POINTER */, {
101
+ path
102
+ });
103
+ }
104
+ function invalidPathTraversal(segment, current) {
105
+ return new FluxError(
106
+ `Cannot access property '${segment}' on ${current}`,
107
+ "INVALID_PATH_TRAVERSAL" /* INVALID_PATH_TRAVERSAL */,
108
+ { segment, currentType: typeof current }
109
+ );
110
+ }
111
+ function cannotReplaceRoot() {
112
+ return new FluxError("Cannot replace root object", "CANNOT_REPLACE_ROOT" /* CANNOT_REPLACE_ROOT */);
113
+ }
114
+ function cannotRemoveRoot() {
115
+ return new FluxError("Cannot remove root object", "CANNOT_REMOVE_ROOT" /* CANNOT_REMOVE_ROOT */);
116
+ }
117
+
1
118
  // src/storage/BunSQLiteStorage.ts
2
119
  import { Database } from "bun:sqlite";
3
120
  var BunSQLiteStorage = class {
@@ -217,14 +334,32 @@ var BunSQLiteStorage = class {
217
334
  };
218
335
  function validateSqlIdentifier(value, field) {
219
336
  if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {
220
- throw new Error(
221
- `Invalid ${field}: "${value}". Only letters, numbers, and underscores are allowed.`
337
+ throw new FluxError(
338
+ `Invalid ${field}: "${value}". Only letters, numbers, and underscores are allowed.`,
339
+ "WORKFLOW_INVALID_INPUT" /* WORKFLOW_INVALID_INPUT */,
340
+ { field, value }
222
341
  );
223
342
  }
224
343
  return value;
225
344
  }
226
345
 
227
346
  export {
347
+ FluxErrorCode,
348
+ FluxError,
349
+ workflowNotFound,
350
+ invalidStateTransition,
351
+ invalidInput,
352
+ workflowNameMismatch,
353
+ workflowDefinitionChanged,
354
+ workflowNotSuspended,
355
+ stepNotFound,
356
+ invalidStepIndex,
357
+ emptyWorkflow,
358
+ noRecoveryAction,
359
+ invalidJsonPointer,
360
+ invalidPathTraversal,
361
+ cannotReplaceRoot,
362
+ cannotRemoveRoot,
228
363
  BunSQLiteStorage
229
364
  };
230
- //# sourceMappingURL=chunk-EZGSU6AW.js.map
365
+ //# sourceMappingURL=chunk-UZKSACBE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/storage/BunSQLiteStorage.ts"],"sourcesContent":["import { QueueException, type InfrastructureExceptionOptions } from '@gravito/core'\n\n/**\n * Standard error codes for FluxEngine operations.\n *\n * Used to programmatically identify the cause of a `FluxError`.\n */\nexport enum FluxErrorCode {\n /** The requested workflow instance could not be found in storage. */\n WORKFLOW_NOT_FOUND = 'WORKFLOW_NOT_FOUND',\n /** The input data provided to the workflow failed validation. */\n WORKFLOW_INVALID_INPUT = 'WORKFLOW_INVALID_INPUT',\n /** The workflow definition has changed since the instance was created, making it unsafe to resume. */\n WORKFLOW_DEFINITION_CHANGED = 'WORKFLOW_DEFINITION_CHANGED',\n /** The workflow name in the definition does not match the stored state. */\n WORKFLOW_NAME_MISMATCH = 'WORKFLOW_NAME_MISMATCH',\n /** An attempt was made to transition the workflow to an incompatible state. */\n INVALID_STATE_TRANSITION = 'INVALID_STATE_TRANSITION',\n /** An operation requiring a suspended state was attempted on a workflow that is not suspended. */\n WORKFLOW_NOT_SUSPENDED = 'WORKFLOW_NOT_SUSPENDED',\n /** The requested step index is out of bounds for the current workflow definition. */\n INVALID_STEP_INDEX = 'INVALID_STEP_INDEX',\n /** A workflow step exceeded its configured execution time limit. */\n STEP_TIMEOUT = 'STEP_TIMEOUT',\n /** The requested step could not be found in the workflow definition. */\n STEP_NOT_FOUND = 'STEP_NOT_FOUND',\n /** Multiple concurrent attempts to modify the same workflow instance were detected. */\n CONCURRENT_MODIFICATION = 'CONCURRENT_MODIFICATION',\n /** A workflow definition must contain at least one step to be executable. */\n EMPTY_WORKFLOW = 'EMPTY_WORKFLOW',\n /** No recovery action is registered for a step that requires recovery. */\n NO_RECOVERY_ACTION = 'NO_RECOVERY_ACTION',\n /** An invalid JSON Pointer was provided for state manipulation. */\n INVALID_JSON_POINTER = 'INVALID_JSON_POINTER',\n /** Cannot access a property on a non-object value in the state tree. */\n INVALID_PATH_TRAVERSAL = 'INVALID_PATH_TRAVERSAL',\n /** Cannot replace the root object of the workflow state. */\n CANNOT_REPLACE_ROOT = 'CANNOT_REPLACE_ROOT',\n /** Cannot remove the root object of the workflow state. */\n CANNOT_REMOVE_ROOT = 'CANNOT_REMOVE_ROOT',\n}\n\n/**\n * Namespace of dot-separated flux error codes for use with FluxErrorCodes const.\n * Maps enum values to `flux.*` namespace per GravitoException convention.\n */\nexport const FluxErrorCodes = {\n WORKFLOW_NOT_FOUND: 'flux.workflow_not_found',\n WORKFLOW_INVALID_INPUT: 'flux.workflow_invalid_input',\n WORKFLOW_DEFINITION_CHANGED: 'flux.workflow_definition_changed',\n WORKFLOW_NAME_MISMATCH: 'flux.workflow_name_mismatch',\n INVALID_STATE_TRANSITION: 'flux.invalid_state_transition',\n WORKFLOW_NOT_SUSPENDED: 'flux.workflow_not_suspended',\n INVALID_STEP_INDEX: 'flux.invalid_step_index',\n STEP_TIMEOUT: 'flux.step_timeout',\n STEP_NOT_FOUND: 'flux.step_not_found',\n CONCURRENT_MODIFICATION: 'flux.concurrent_modification',\n EMPTY_WORKFLOW: 'flux.empty_workflow',\n NO_RECOVERY_ACTION: 'flux.no_recovery_action',\n INVALID_JSON_POINTER: 'flux.invalid_json_pointer',\n INVALID_PATH_TRAVERSAL: 'flux.invalid_path_traversal',\n CANNOT_REPLACE_ROOT: 'flux.cannot_replace_root',\n CANNOT_REMOVE_ROOT: 'flux.cannot_remove_root',\n} as const\n\n/**\n * Base class for all errors thrown by the FluxEngine.\n *\n * Extends QueueException from @gravito/core, enabling consistent infrastructure\n * error handling across the GravitoException hierarchy.\n *\n * Includes a machine-readable error code and optional context for debugging.\n *\n * @example\n * ```typescript\n * try {\n * await engine.execute(flow, input);\n * } catch (err) {\n * if (err instanceof FluxError && err.code === FluxErrorCode.STEP_TIMEOUT) {\n * console.error('Workflow timed out');\n * }\n * }\n * ```\n */\nexport class FluxError extends QueueException {\n /**\n * Additional metadata related to the error.\n */\n public readonly context?: Record<string, unknown>\n\n /**\n * Creates a new FluxError.\n *\n * @param message - Human-readable error description.\n * @param code - Machine-readable error code (FluxErrorCode enum value).\n * @param context - Additional metadata related to the error.\n */\n constructor(\n message: string,\n code: FluxErrorCode | string,\n context?: Record<string, unknown>\n ) {\n const options: InfrastructureExceptionOptions = { message }\n super(422, code, options)\n this.name = 'FluxError'\n this.context = context\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\n/**\n * Creates a FluxError for a missing workflow instance.\n *\n * @param id - The unique identifier of the missing workflow.\n * @returns A FluxError with the WORKFLOW_NOT_FOUND code.\n *\n * @example\n * ```typescript\n * throw workflowNotFound('wf-123');\n * ```\n */\nexport function workflowNotFound(id: string): FluxError {\n return new FluxError(`Workflow not found: ${id}`, FluxErrorCode.WORKFLOW_NOT_FOUND, {\n workflowId: id,\n })\n}\n\n/**\n * Creates a FluxError for an illegal state transition.\n *\n * @param from - The current state of the workflow.\n * @param to - The attempted target state.\n * @returns A FluxError with the INVALID_STATE_TRANSITION code.\n *\n * @example\n * ```typescript\n * throw invalidStateTransition('completed', 'running');\n * ```\n */\nexport function invalidStateTransition(from: string, to: string): FluxError {\n return new FluxError(\n `Invalid state transition: ${from} → ${to}`,\n FluxErrorCode.INVALID_STATE_TRANSITION,\n { from, to }\n )\n}\n\n/**\n * Creates a FluxError for invalid workflow input.\n *\n * @param workflowName - The name of the workflow definition.\n * @returns A FluxError with the WORKFLOW_INVALID_INPUT code.\n *\n * @example\n * ```typescript\n * throw invalidInput('order-process');\n * ```\n */\nexport function invalidInput(workflowName: string): FluxError {\n return new FluxError(\n `Invalid input for workflow \"${workflowName}\"`,\n FluxErrorCode.WORKFLOW_INVALID_INPUT,\n { workflowName }\n )\n}\n\n/**\n * Creates a FluxError for a workflow name mismatch.\n *\n * @param expected - The name expected by the definition.\n * @param received - The name found in the stored state.\n * @returns A FluxError with the WORKFLOW_NAME_MISMATCH code.\n */\nexport function workflowNameMismatch(expected: string, received: string): FluxError {\n return new FluxError(\n `Workflow name mismatch: ${received} !== ${expected}`,\n FluxErrorCode.WORKFLOW_NAME_MISMATCH,\n { expected, received }\n )\n}\n\n/**\n * Creates a FluxError when a workflow definition has changed incompatibly.\n *\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n */\nexport function workflowDefinitionChanged(): FluxError {\n return new FluxError(\n 'Workflow definition changed; operation is not safe',\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED\n )\n}\n\n/**\n * Creates a FluxError for a workflow version mismatch.\n *\n * @param stored - The version stored in the workflow instance.\n * @param current - The version in the current workflow definition.\n * @returns A FluxError with the WORKFLOW_DEFINITION_CHANGED code.\n *\n * @example\n * ```typescript\n * throw workflowVersionMismatch('1.0.0', '2.0.0');\n * ```\n */\nexport function workflowVersionMismatch(stored: string, current: string): FluxError {\n return new FluxError(\n `Workflow version mismatch: stored version \"${stored}\" does not match current \"${current}\"`,\n FluxErrorCode.WORKFLOW_DEFINITION_CHANGED,\n { storedVersion: stored, currentVersion: current }\n )\n}\n\n/**\n * Creates a FluxError when an operation requires a suspended workflow.\n *\n * @param status - The current status of the workflow.\n * @returns A FluxError with the WORKFLOW_NOT_SUSPENDED code.\n */\nexport function workflowNotSuspended(status: string): FluxError {\n return new FluxError(\n `Workflow is not suspended (status: ${status})`,\n FluxErrorCode.WORKFLOW_NOT_SUSPENDED,\n { status }\n )\n}\n\n/**\n * Creates a FluxError when a specific step cannot be found.\n *\n * @param step - The name or index of the missing step.\n * @returns A FluxError with the STEP_NOT_FOUND code.\n */\nexport function stepNotFound(step: string | number): FluxError {\n return new FluxError(`Step not found: ${step}`, FluxErrorCode.STEP_NOT_FOUND, { step })\n}\n\n/**\n * Creates a FluxError for an out-of-bounds step index.\n *\n * @param index - The invalid step index.\n * @returns A FluxError with the INVALID_STEP_INDEX code.\n */\nexport function invalidStepIndex(index: number): FluxError {\n return new FluxError(`Invalid step index: ${index}`, FluxErrorCode.INVALID_STEP_INDEX, { index })\n}\n\n/**\n * Creates a FluxError for an empty workflow (no steps defined).\n *\n * @param workflowName - The name of the workflow.\n * @returns A FluxError with the EMPTY_WORKFLOW code.\n */\nexport function emptyWorkflow(workflowName: string): FluxError {\n return new FluxError(`Workflow \"${workflowName}\" has no steps`, FluxErrorCode.EMPTY_WORKFLOW, {\n workflowName,\n })\n}\n\n/**\n * Creates a FluxError when no recovery action is registered for a step.\n *\n * @param stepName - The name of the step requiring recovery.\n * @returns A FluxError with the NO_RECOVERY_ACTION code.\n */\nexport function noRecoveryAction(stepName: string): FluxError {\n return new FluxError(\n `No recovery action registered for step: ${stepName}`,\n FluxErrorCode.NO_RECOVERY_ACTION,\n { stepName }\n )\n}\n\n/**\n * Creates a FluxError for invalid JSON Pointer syntax.\n *\n * @param path - The invalid JSON Pointer.\n * @returns A FluxError with the INVALID_JSON_POINTER code.\n */\nexport function invalidJsonPointer(path: string): FluxError {\n return new FluxError(`Invalid JSON Pointer: ${path}`, FluxErrorCode.INVALID_JSON_POINTER, {\n path,\n })\n}\n\n/**\n * Creates a FluxError when attempting to traverse a non-object value.\n *\n * @param segment - The property being accessed.\n * @param current - The current value type.\n * @returns A FluxError with the INVALID_PATH_TRAVERSAL code.\n */\nexport function invalidPathTraversal(segment: string, current: unknown): FluxError {\n return new FluxError(\n `Cannot access property '${segment}' on ${current}`,\n FluxErrorCode.INVALID_PATH_TRAVERSAL,\n { segment, currentType: typeof current }\n )\n}\n\n/**\n * Creates a FluxError when attempting to replace the root object.\n *\n * @returns A FluxError with the CANNOT_REPLACE_ROOT code.\n */\nexport function cannotReplaceRoot(): FluxError {\n return new FluxError('Cannot replace root object', FluxErrorCode.CANNOT_REPLACE_ROOT)\n}\n\n/**\n * Creates a FluxError when attempting to remove the root object.\n *\n * @returns A FluxError with the CANNOT_REMOVE_ROOT code.\n */\nexport function cannotRemoveRoot(): FluxError {\n return new FluxError('Cannot remove root object', FluxErrorCode.CANNOT_REMOVE_ROOT)\n}\n","import { Database } from 'bun:sqlite'\nimport type { WorkflowFilter, WorkflowState, WorkflowStorage } from '../types'\nimport { FluxError, FluxErrorCode } from '../errors'\n\n/**\n * Configuration options for the Bun SQLite storage adapter.\n */\nexport interface BunSQLiteStorageOptions {\n /**\n * Path to the SQLite database file.\n * Use ':memory:' for an ephemeral in-memory database.\n */\n path?: string\n /**\n * Name of the table used to store workflow states.\n */\n tableName?: string\n}\n\n/**\n * BunSQLiteStorage provides a persistent storage backend for Flux workflows using Bun's native SQLite module.\n *\n * It handles automatic table creation, indexing for performance, and serialization of workflow state\n * into a relational format.\n *\n * @example\n * ```typescript\n * const storage = new BunSQLiteStorage({\n * path: './workflows.db',\n * tableName: 'my_workflows'\n * });\n * await storage.init();\n * ```\n */\nexport class BunSQLiteStorage implements WorkflowStorage {\n private db: Database\n private tableName: string\n private initialized = false\n\n /**\n * Creates a new instance of BunSQLiteStorage.\n *\n * @param options - Configuration for the database connection and table naming.\n */\n constructor(options: BunSQLiteStorageOptions = {}) {\n this.db = new Database(options.path ?? ':memory:')\n this.tableName = validateSqlIdentifier(options.tableName ?? 'flux_workflows', 'tableName')\n }\n\n /**\n * Initializes the database schema and required indexes.\n *\n * This method is idempotent and will be called automatically by other operations if not invoked manually.\n *\n * @throws {Error} If the database schema cannot be created or indexes fail to initialize.\n */\n async init(): Promise<void> {\n if (this.initialized) {\n return\n }\n\n this.db.run(`\n CREATE TABLE IF NOT EXISTS ${this.tableName} (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n status TEXT NOT NULL,\n input TEXT NOT NULL,\n data TEXT NOT NULL,\n current_step INTEGER NOT NULL,\n history TEXT NOT NULL,\n error TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n completed_at TEXT,\n version INTEGER NOT NULL DEFAULT 1,\n definition_version TEXT\n )\n `)\n\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_name \n ON ${this.tableName}(name)\n `)\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_status \n ON ${this.tableName}(status)\n `)\n this.db.run(`\n CREATE INDEX IF NOT EXISTS idx_${this.tableName}_created \n ON ${this.tableName}(created_at DESC)\n `)\n\n this.initialized = true\n }\n\n /**\n * Persists or updates a workflow state in the database.\n *\n * Uses an \"INSERT OR REPLACE\" strategy to ensure the latest state is always stored for a given ID.\n *\n * @param state - The current state of the workflow to be saved.\n * @throws {Error} If the database write operation fails or serialization errors occur.\n */\n async save(state: WorkflowState): Promise<void> {\n await this.init()\n\n const stmt = this.db.prepare(`\n INSERT OR REPLACE INTO ${this.tableName} \n (id, name, status, input, data, current_step, history, error, created_at, updated_at, completed_at, version, definition_version)\n VALUES ($id, $name, $status, $input, $data, $currentStep, $history, $error, $createdAt, $updatedAt, $completedAt, $version, $definitionVersion)\n `)\n\n stmt.run({\n $id: state.id,\n $name: state.name,\n $status: state.status,\n $input: JSON.stringify(state.input),\n $data: JSON.stringify(state.data),\n $currentStep: state.currentStep,\n $history: JSON.stringify(state.history),\n $error: state.error ?? null,\n $createdAt: state.createdAt.toISOString(),\n $updatedAt: state.updatedAt.toISOString(),\n $completedAt: state.completedAt?.toISOString() ?? null,\n $version: state.version,\n $definitionVersion: state.definitionVersion ?? null,\n })\n }\n\n /**\n * Retrieves a workflow state by its unique identifier.\n *\n * @param id - The unique ID of the workflow to load.\n * @returns The reconstructed workflow state, or null if no record is found.\n * @throws {Error} If the database query fails or deserialization of stored JSON fails.\n */\n async load(id: string): Promise<WorkflowState | null> {\n await this.init()\n\n const stmt = this.db.prepare(`\n SELECT * FROM ${this.tableName} WHERE id = $id\n `)\n\n const row = stmt.get({ $id: id }) as SQLiteRow | null\n\n if (!row) {\n return null\n }\n\n return this.rowToState(row)\n }\n\n /**\n * Lists workflow states based on the provided filtering criteria.\n *\n * Results are returned in descending order of creation time.\n *\n * @param filter - Criteria for filtering and paginating the results.\n * @returns An array of workflow states matching the filter.\n * @throws {Error} If the database query fails.\n */\n async list(filter?: WorkflowFilter): Promise<WorkflowState[]> {\n await this.init()\n\n let query = `SELECT * FROM ${this.tableName} WHERE 1=1`\n const params: Record<string, unknown> = {}\n\n if (filter?.name) {\n query += ' AND name = $name'\n params.$name = filter.name\n }\n\n if (filter?.status) {\n if (Array.isArray(filter.status)) {\n const placeholders = filter.status.map((_, i) => `$status${i}`).join(', ')\n query += ` AND status IN (${placeholders})`\n filter.status.forEach((s, i) => {\n params[`$status${i}`] = s\n })\n } else {\n query += ' AND status = $status'\n params.$status = filter.status\n }\n }\n\n if (filter?.version) {\n query += ' AND definition_version = $version'\n params.$version = filter.version\n }\n\n query += ' ORDER BY created_at DESC'\n\n if (filter?.limit) {\n query += ' LIMIT $limit'\n params.$limit = filter.limit\n }\n\n if (filter?.offset) {\n query += ' OFFSET $offset'\n params.$offset = filter.offset\n }\n\n const stmt = this.db.prepare(query)\n const rows = stmt.all(params as Record<string, any>) as SQLiteRow[]\n\n return rows.map((row) => this.rowToState(row))\n }\n\n /**\n * Deletes a workflow state from the database.\n *\n * @param id - The unique ID of the workflow to delete.\n * @throws {Error} If the database deletion fails.\n */\n async delete(id: string): Promise<void> {\n await this.init()\n\n const stmt = this.db.prepare(`\n DELETE FROM ${this.tableName} WHERE id = $id\n `)\n\n stmt.run({ $id: id })\n }\n\n /**\n * Closes the database connection and resets the initialization state.\n *\n * @throws {Error} If the database connection cannot be closed cleanly.\n */\n async close(): Promise<void> {\n this.db.close()\n this.initialized = false\n }\n\n /**\n * Converts a raw database row into a structured WorkflowState object.\n *\n * @param row - The raw SQLite row data.\n * @returns The parsed workflow state.\n * @private\n */\n private rowToState(row: SQLiteRow): WorkflowState {\n return {\n id: row.id,\n name: row.name,\n status: row.status as WorkflowState['status'],\n input: JSON.parse(row.input),\n data: JSON.parse(row.data),\n currentStep: row.current_step,\n history: JSON.parse(row.history),\n error: row.error ?? undefined,\n createdAt: new Date(row.created_at),\n updatedAt: new Date(row.updated_at),\n completedAt: row.completed_at ? new Date(row.completed_at) : undefined,\n version: row.version,\n definitionVersion: row.definition_version ?? undefined,\n }\n }\n\n /**\n * Provides direct access to the underlying Bun SQLite Database instance.\n *\n * Useful for performing custom queries or maintenance tasks.\n *\n * @returns The raw Database instance.\n */\n getDatabase(): Database {\n return this.db\n }\n\n /**\n * Performs a VACUUM operation to reclaim unused space and defragment the database.\n *\n * @throws {Error} If the VACUUM operation fails.\n */\n vacuum(): void {\n this.db.run('VACUUM')\n }\n}\n\nfunction validateSqlIdentifier(value: string, field: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) {\n throw new FluxError(\n `Invalid ${field}: \"${value}\". Only letters, numbers, and underscores are allowed.`,\n FluxErrorCode.WORKFLOW_INVALID_INPUT,\n { field, value }\n )\n }\n return value\n}\n\n/**\n * Internal representation of a workflow record in the SQLite database.\n */\ninterface SQLiteRow {\n id: string\n name: string\n status: string\n input: string\n data: string\n current_step: number\n history: string\n error: string | null\n created_at: string\n updated_at: string\n completed_at: string | null\n version: number\n definition_version: string | null\n}\n"],"mappings":"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","names":["FluxErrorCode"]}
package/dist/index.cjs CHANGED
@@ -15,6 +15,7 @@
15
15
 
16
16
 
17
17
 
18
+ var _chunkAVWZYY7Ucjs = require('./chunk-AVWZYY7U.cjs');
18
19
 
19
20
 
20
21
 
@@ -31,10 +32,9 @@
31
32
 
32
33
 
33
34
 
34
- var _chunkDN7SIQ34cjs = require('./chunk-DN7SIQ34.cjs');
35
35
 
36
36
 
37
- var _chunkZE2RDS47cjs = require('./chunk-ZE2RDS47.cjs');
37
+ var _chunkOAJWPPYGcjs = require('./chunk-OAJWPPYG.cjs');
38
38
 
39
39
 
40
40
  var _chunk6AZNHVEOcjs = require('./chunk-6AZNHVEO.cjs');
@@ -50,8 +50,8 @@ var WorkflowProfiler = class {
50
50
  constructor(engine) {
51
51
  this.engine = engine;
52
52
  if (!this.engine) {
53
- this.engine = new (0, _chunkDN7SIQ34cjs.FluxEngine)({
54
- logger: new (0, _chunkDN7SIQ34cjs.FluxSilentLogger)()
53
+ this.engine = new (0, _chunkAVWZYY7Ucjs.FluxEngine)({
54
+ logger: new (0, _chunkAVWZYY7Ucjs.FluxSilentLogger)()
55
55
  });
56
56
  }
57
57
  }
@@ -219,5 +219,5 @@ var Flux = {
219
219
 
220
220
 
221
221
 
222
- exports.BatchExecutor = _chunkDN7SIQ34cjs.BatchExecutor; exports.BunSQLiteStorage = _chunkZE2RDS47cjs.BunSQLiteStorage; exports.ContextManager = _chunkDN7SIQ34cjs.ContextManager; exports.CronTrigger = _chunkDN7SIQ34cjs.CronTrigger; exports.Flux = Flux; exports.FluxConsoleLogger = _chunkDN7SIQ34cjs.FluxConsoleLogger; exports.FluxEngine = _chunkDN7SIQ34cjs.FluxEngine; exports.FluxError = _chunkDN7SIQ34cjs.FluxError; exports.FluxErrorCode = _chunkDN7SIQ34cjs.FluxErrorCode; exports.FluxSilentLogger = _chunkDN7SIQ34cjs.FluxSilentLogger; exports.JsonFileTraceSink = _chunkDN7SIQ34cjs.JsonFileTraceSink; exports.MemoryLockProvider = _chunkDN7SIQ34cjs.MemoryLockProvider; exports.MemoryStorage = _chunkDN7SIQ34cjs.MemoryStorage; exports.MermaidGenerator = _chunk6AZNHVEOcjs.MermaidGenerator; exports.OrbitFlux = _chunkDN7SIQ34cjs.OrbitFlux; exports.PostgreSQLStorage = _chunkDN7SIQ34cjs.PostgreSQLStorage; exports.RedisLockProvider = _chunkDN7SIQ34cjs.RedisLockProvider; exports.StateMachine = _chunkDN7SIQ34cjs.StateMachine; exports.StepExecutor = _chunkDN7SIQ34cjs.StepExecutor; exports.WorkflowBuilder = _chunkDN7SIQ34cjs.WorkflowBuilder; exports.WorkflowProfiler = WorkflowProfiler; exports.cannotRemoveRoot = _chunkDN7SIQ34cjs.cannotRemoveRoot; exports.cannotReplaceRoot = _chunkDN7SIQ34cjs.cannotReplaceRoot; exports.createWorkflow = _chunkDN7SIQ34cjs.createWorkflow; exports.emptyWorkflow = _chunkDN7SIQ34cjs.emptyWorkflow; exports.invalidInput = _chunkDN7SIQ34cjs.invalidInput; exports.invalidJsonPointer = _chunkDN7SIQ34cjs.invalidJsonPointer; exports.invalidPathTraversal = _chunkDN7SIQ34cjs.invalidPathTraversal; exports.invalidStateTransition = _chunkDN7SIQ34cjs.invalidStateTransition; exports.invalidStepIndex = _chunkDN7SIQ34cjs.invalidStepIndex; exports.noRecoveryAction = _chunkDN7SIQ34cjs.noRecoveryAction; exports.stepNotFound = _chunkDN7SIQ34cjs.stepNotFound; exports.workflowDefinitionChanged = _chunkDN7SIQ34cjs.workflowDefinitionChanged; exports.workflowNameMismatch = _chunkDN7SIQ34cjs.workflowNameMismatch; exports.workflowNotFound = _chunkDN7SIQ34cjs.workflowNotFound; exports.workflowNotSuspended = _chunkDN7SIQ34cjs.workflowNotSuspended;
222
+ exports.BatchExecutor = _chunkAVWZYY7Ucjs.BatchExecutor; exports.BunSQLiteStorage = _chunkOAJWPPYGcjs.BunSQLiteStorage; exports.ContextManager = _chunkAVWZYY7Ucjs.ContextManager; exports.CronTrigger = _chunkAVWZYY7Ucjs.CronTrigger; exports.Flux = Flux; exports.FluxConsoleLogger = _chunkAVWZYY7Ucjs.FluxConsoleLogger; exports.FluxEngine = _chunkAVWZYY7Ucjs.FluxEngine; exports.FluxError = _chunkOAJWPPYGcjs.FluxError; exports.FluxErrorCode = _chunkOAJWPPYGcjs.FluxErrorCode; exports.FluxSilentLogger = _chunkAVWZYY7Ucjs.FluxSilentLogger; exports.JsonFileTraceSink = _chunkAVWZYY7Ucjs.JsonFileTraceSink; exports.MemoryLockProvider = _chunkAVWZYY7Ucjs.MemoryLockProvider; exports.MemoryStorage = _chunkAVWZYY7Ucjs.MemoryStorage; exports.MermaidGenerator = _chunk6AZNHVEOcjs.MermaidGenerator; exports.OrbitFlux = _chunkAVWZYY7Ucjs.OrbitFlux; exports.PostgreSQLStorage = _chunkAVWZYY7Ucjs.PostgreSQLStorage; exports.RedisLockProvider = _chunkAVWZYY7Ucjs.RedisLockProvider; exports.StateMachine = _chunkAVWZYY7Ucjs.StateMachine; exports.StepExecutor = _chunkAVWZYY7Ucjs.StepExecutor; exports.WorkflowBuilder = _chunkAVWZYY7Ucjs.WorkflowBuilder; exports.WorkflowProfiler = WorkflowProfiler; exports.cannotRemoveRoot = _chunkOAJWPPYGcjs.cannotRemoveRoot; exports.cannotReplaceRoot = _chunkOAJWPPYGcjs.cannotReplaceRoot; exports.createWorkflow = _chunkAVWZYY7Ucjs.createWorkflow; exports.emptyWorkflow = _chunkOAJWPPYGcjs.emptyWorkflow; exports.invalidInput = _chunkOAJWPPYGcjs.invalidInput; exports.invalidJsonPointer = _chunkOAJWPPYGcjs.invalidJsonPointer; exports.invalidPathTraversal = _chunkOAJWPPYGcjs.invalidPathTraversal; exports.invalidStateTransition = _chunkOAJWPPYGcjs.invalidStateTransition; exports.invalidStepIndex = _chunkOAJWPPYGcjs.invalidStepIndex; exports.noRecoveryAction = _chunkOAJWPPYGcjs.noRecoveryAction; exports.stepNotFound = _chunkOAJWPPYGcjs.stepNotFound; exports.workflowDefinitionChanged = _chunkOAJWPPYGcjs.workflowDefinitionChanged; exports.workflowNameMismatch = _chunkOAJWPPYGcjs.workflowNameMismatch; exports.workflowNotFound = _chunkOAJWPPYGcjs.workflowNotFound; exports.workflowNotSuspended = _chunkOAJWPPYGcjs.workflowNotSuspended;
223
223
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/index.cjs","../src/profiler/WorkflowProfiler.ts","../src/index.ts"],"names":["cpus"],"mappings":"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","file":"/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/index.cjs","sourcesContent":[null,"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"]}
1
+ {"version":3,"sources":["/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/index.cjs","../src/profiler/WorkflowProfiler.ts","../src/index.ts"],"names":["cpus"],"mappings":"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","file":"/Users/carl/Dev/Carl/gravito-core/packages/flux/dist/index.cjs","sourcesContent":[null,"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"]}
package/dist/index.d.cts CHANGED
@@ -2,8 +2,8 @@ import { C as CronScheduleOptions, W as WorkflowDefinition, a as WorkflowState,
2
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-CGIEQPFv.cjs';
3
3
  import { FluxEngine } from './index.node.cjs';
4
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.cjs';
5
+ import { QueueException } from '@gravito/core';
5
6
  export { BunSQLiteStorage, BunSQLiteStorageOptions } from './bun.cjs';
6
- import '@gravito/core';
7
7
  import 'bun:sqlite';
8
8
 
9
9
  /**
@@ -48,6 +48,9 @@ declare enum FluxErrorCode {
48
48
  /**
49
49
  * Base class for all errors thrown by the FluxEngine.
50
50
  *
51
+ * Extends QueueException from @gravito/core, enabling consistent infrastructure
52
+ * error handling across the GravitoException hierarchy.
53
+ *
51
54
  * Includes a machine-readable error code and optional context for debugging.
52
55
  *
53
56
  * @example
@@ -61,17 +64,19 @@ declare enum FluxErrorCode {
61
64
  * }
62
65
  * ```
63
66
  */
64
- declare class FluxError extends Error {
65
- readonly code: FluxErrorCode;
66
- readonly context?: Record<string, unknown> | undefined;
67
+ declare class FluxError extends QueueException {
68
+ /**
69
+ * Additional metadata related to the error.
70
+ */
71
+ readonly context?: Record<string, unknown>;
67
72
  /**
68
73
  * Creates a new FluxError.
69
74
  *
70
75
  * @param message - Human-readable error description.
71
- * @param code - Machine-readable error code.
76
+ * @param code - Machine-readable error code (FluxErrorCode enum value).
72
77
  * @param context - Additional metadata related to the error.
73
78
  */
74
- constructor(message: string, code: FluxErrorCode, context?: Record<string, unknown> | undefined);
79
+ constructor(message: string, code: FluxErrorCode | string, context?: Record<string, unknown>);
75
80
  }
76
81
  /**
77
82
  * Creates a FluxError for a missing workflow instance.