{"version":3,"file":"codec-C6yDENv-.mjs","names":[],"sources":["../src/core/errors.ts","../src/storage/codec.ts"],"sourcesContent":["import type { PersistedValue } from './types'\n\n/**\n * Typed error hierarchy for Reflow.\n *\n * Every error Reflow throws extends `ReflowError`, so a single\n * `instanceof ReflowError` catch-all is always available. More specific\n * subclasses carry structured context (workflow name, step name, run ID, etc.)\n * so callers never need to parse error messages.\n */\n\n// ---------------------------------------------------------------------------\n// Base\n// ---------------------------------------------------------------------------\n\n/** Base class for all Reflow errors. */\nexport class ReflowError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = 'ReflowError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\n/** Thrown when engine, retry, or schedule configuration is invalid. */\nexport class ConfigError extends ReflowError {\n  constructor(message: string) {\n    super(message)\n    this.name = 'ConfigError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Workflow definition\n// ---------------------------------------------------------------------------\n\n/** Thrown when `enqueue()` or `schedule()` references an unregistered workflow name. */\nexport class WorkflowNotFoundError extends ReflowError {\n  constructor(public readonly workflowName: string) {\n    super(`Workflow \"${workflowName}\" not found`)\n    this.name = 'WorkflowNotFoundError'\n  }\n}\n\n/** Thrown when `createEngine()` receives the same workflow name twice. */\nexport class DuplicateWorkflowError extends ReflowError {\n  constructor(public readonly workflowName: string) {\n    super(`Workflow \"${workflowName}\" is registered more than once`)\n    this.name = 'DuplicateWorkflowError'\n  }\n}\n\n/** Thrown when `.step()` reuses a name that already exists in the workflow. */\nexport class DuplicateStepError extends ReflowError {\n  constructor(\n    public readonly workflowName: string,\n    public readonly stepName: string,\n  ) {\n    super(`Step \"${stepName}\" is already defined in workflow \"${workflowName}\"`)\n    this.name = 'DuplicateStepError'\n  }\n}\n\n/** Thrown when `complete()` is called inside a parallel step handler. */\nexport class ParallelCompleteError extends ReflowError {\n  constructor(public readonly stepName: string) {\n    super(`complete() cannot be called inside parallel step \"${stepName}\"`)\n    this.name = 'ParallelCompleteError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Input validation\n// ---------------------------------------------------------------------------\n\n/** A single validation issue from the input schema. */\nexport interface ValidationIssue {\n  readonly message: string\n  readonly path?: ReadonlyArray<PropertyKey | { readonly key: PropertyKey }>\n}\n\n/** Thrown when workflow input fails schema validation. */\nexport class ValidationError extends ReflowError {\n  constructor(\n    message: string,\n    public readonly issues: readonly ValidationIssue[],\n  ) {\n    super(message)\n    this.name = 'ValidationError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Idempotency\n// ---------------------------------------------------------------------------\n\n/** Thrown when `enqueue()` reuses an idempotency key with different input. */\nexport class IdempotencyConflictError extends ReflowError {\n  constructor(\n    public readonly workflowName: string,\n    public readonly idempotencyKey: string,\n  ) {\n    super(\n      `Idempotency key \"${idempotencyKey}\" for workflow \"${workflowName}\" is already associated with different input`,\n    )\n    this.name = 'IdempotencyConflictError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Serialization\n// ---------------------------------------------------------------------------\n\n/** Thrown when a step output or workflow input contains non-JSON-compatible data. */\nexport class SerializationError extends ReflowError {\n  constructor(\n    message: string,\n    public readonly path: string,\n  ) {\n    super(message)\n    this.name = 'SerializationError'\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Run lifecycle\n// ---------------------------------------------------------------------------\n\n/** Thrown when a step exceeds its `timeoutMs`. Reaches `onRunFailed`. */\nexport class StepTimeoutError extends ReflowError {\n  constructor(public readonly timeoutMs: number) {\n    super(`Step timed out after ${timeoutMs}ms`)\n    this.name = 'StepTimeoutError'\n  }\n}\n\n/**\n * Internal base class for errors that represent control-flow signals\n * (cancellation, lease loss) rather than real failures. These do NOT\n * reach `onRunFailed`.\n *\n * @internal Not exported from the public API.\n */\nexport class RunControlError extends ReflowError {\n  constructor(message: string) {\n    super(message)\n    this.name = 'RunControlError'\n  }\n}\n\n/** Thrown when a step calls `complete()` to finish the workflow early. */\nexport class EarlyCompleteError extends RunControlError {\n  constructor(public readonly value?: PersistedValue) {\n    super('Workflow completed early')\n    this.name = 'EarlyCompleteError'\n  }\n}\n\n/** Thrown when a run is cancelled via `engine.cancel()`. */\nexport class RunCancelledError extends RunControlError {\n  constructor(public readonly runId: string) {\n    super(`Run \"${runId}\" was cancelled`)\n    this.name = 'RunCancelledError'\n  }\n}\n\n/** Thrown when the engine loses its lease on a run (another worker reclaimed it). */\nexport class LeaseExpiredError extends RunControlError {\n  constructor(public readonly runId: string) {\n    super(`Run \"${runId}\" lease expired`)\n    this.name = 'LeaseExpiredError'\n  }\n}\n","import { SerializationError } from '../core/errors'\nimport type { PersistedObject, PersistedValue } from '../core/types'\n\nconst UNDEFINED_SENTINEL_KEY = '__reflowUndefined__'\nconst DATE_SENTINEL_KEY = '__reflowDate__'\n\nexport function serializePersistedValue(value: PersistedValue, context: string): string {\n  return JSON.stringify(encodePersistedValue(value, context, '$'))\n}\n\nexport function deserializePersistedValue(serialized: string | null): PersistedValue {\n  if (serialized === null) {\n    return null\n  }\n\n  return decodePersistedValue(JSON.parse(serialized))\n}\n\nexport function clonePersistedValue(value: PersistedValue, context: string): PersistedValue {\n  return deserializePersistedValue(serializePersistedValue(value, context))\n}\n\nexport function persistedValuesEqual(left: PersistedValue, right: PersistedValue): boolean {\n  if (left === right) return true\n  if (left === null || right === null || left === undefined || right === undefined) return left === right\n  if (typeof left !== typeof right) return false\n  if (typeof left !== 'object') return left === right\n  if (left instanceof Date || right instanceof Date) {\n    return left instanceof Date && right instanceof Date && left.getTime() === right.getTime()\n  }\n  if (Array.isArray(left) !== Array.isArray(right)) return false\n  if (Array.isArray(left) && Array.isArray(right)) {\n    if (left.length !== right.length) return false\n    return left.every((entry, index) => persistedValuesEqual(entry, right[index]))\n  }\n  const leftObj = left as Record<string, PersistedValue>\n  const rightObj = right as Record<string, PersistedValue>\n  const leftKeys = Object.keys(leftObj)\n  const rightKeys = Object.keys(rightObj)\n  if (leftKeys.length !== rightKeys.length) return false\n  return leftKeys.every((key) => persistedValuesEqual(leftObj[key], rightObj[key]))\n}\n\nfunction encodePersistedValue(value: PersistedValue, context: string, path: string): unknown {\n  if (value === undefined) {\n    return { [UNDEFINED_SENTINEL_KEY]: true }\n  }\n\n  if (\n    value === null\n    || typeof value === 'string'\n    || typeof value === 'boolean'\n  ) {\n    return value\n  }\n\n  if (typeof value === 'number') {\n    if (!Number.isFinite(value)) {\n      throw new SerializationError(`${context} must not contain NaN or Infinity at ${path}`, path)\n    }\n    return value\n  }\n\n  if (value instanceof Date) {\n    if (!Number.isFinite(value.getTime())) {\n      throw new SerializationError(`${context} must not contain an invalid Date at ${path}`, path)\n    }\n    return { [DATE_SENTINEL_KEY]: value.toISOString() }\n  }\n\n  if (Array.isArray(value)) {\n    return value.map((entry, index) => encodePersistedValue(entry, context, `${path}[${index}]`))\n  }\n\n  if (isPlainObject(value)) {\n    if (Object.prototype.hasOwnProperty.call(value, UNDEFINED_SENTINEL_KEY)) {\n      throw new SerializationError(\n        `${context} must not use the reserved key \"${UNDEFINED_SENTINEL_KEY}\" at ${path}`,\n        path,\n      )\n    }\n\n    if (Object.prototype.hasOwnProperty.call(value, DATE_SENTINEL_KEY)) {\n      throw new SerializationError(\n        `${context} must not use the reserved key \"${DATE_SENTINEL_KEY}\" at ${path}`,\n        path,\n      )\n    }\n\n    const encoded: Record<string, unknown> = {}\n    for (const [key, entry] of Object.entries(value)) {\n      encoded[key] = encodePersistedValue(entry, context, `${path}.${key}`)\n    }\n    return encoded\n  }\n\n  throw new SerializationError(\n    `${context} must be JSON-compatible data (plain objects, arrays, primitives, or undefined) at ${path}`,\n    path,\n  )\n}\n\nfunction decodePersistedValue(value: unknown): PersistedValue {\n  if (\n    value === null\n    || value === undefined\n    || typeof value === 'string'\n    || typeof value === 'number'\n    || typeof value === 'boolean'\n  ) {\n    return value\n  }\n\n  if (Array.isArray(value)) {\n    return value.map((entry) => decodePersistedValue(entry))\n  }\n\n  if (isPlainObject(value)) {\n    if (\n      Object.keys(value).length === 1\n      && value[UNDEFINED_SENTINEL_KEY] === true\n    ) {\n      return undefined\n    }\n\n    if (\n      Object.keys(value).length === 1\n      && typeof value[DATE_SENTINEL_KEY] === 'string'\n    ) {\n      const date = new Date(value[DATE_SENTINEL_KEY] as string)\n      if (!Number.isFinite(date.getTime())) {\n        throw new SerializationError(\n          `Stored value contains an invalid Date string: \"${value[DATE_SENTINEL_KEY]}\"`,\n          '$',\n        )\n      }\n      return date\n    }\n\n    const decoded: PersistedObject = {}\n    for (const [key, entry] of Object.entries(value)) {\n      decoded[key] = decodePersistedValue(entry)\n    }\n    return decoded\n  }\n\n  throw new SerializationError('Stored value is not a valid Reflow payload', '$')\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, PersistedValue> {\n  if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n    return false\n  }\n\n  const prototype = Object.getPrototypeOf(value)\n  return prototype === Object.prototype || prototype === null\n}\n"],"mappings":";;;;;;;;;;AAgBA,IAAa,cAAb,cAAiC,MAAM;CACrC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;AAShB,IAAa,cAAb,cAAiC,YAAY;CAC3C,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;AAShB,IAAa,wBAAb,cAA2C,YAAY;CACrD,YAAY,cAAsC;AAChD,QAAM,aAAa,aAAa,aAAa;AADnB,OAAA,eAAA;AAE1B,OAAK,OAAO;;;;AAKhB,IAAa,yBAAb,cAA4C,YAAY;CACtD,YAAY,cAAsC;AAChD,QAAM,aAAa,aAAa,gCAAgC;AADtC,OAAA,eAAA;AAE1B,OAAK,OAAO;;;;AAKhB,IAAa,qBAAb,cAAwC,YAAY;CAClD,YACE,cACA,UACA;AACA,QAAM,SAAS,SAAS,oCAAoC,aAAa,GAAG;AAH5D,OAAA,eAAA;AACA,OAAA,WAAA;AAGhB,OAAK,OAAO;;;;AAKhB,IAAa,wBAAb,cAA2C,YAAY;CACrD,YAAY,UAAkC;AAC5C,QAAM,qDAAqD,SAAS,GAAG;AAD7C,OAAA,WAAA;AAE1B,OAAK,OAAO;;;;AAehB,IAAa,kBAAb,cAAqC,YAAY;CAC/C,YACE,SACA,QACA;AACA,QAAM,QAAQ;AAFE,OAAA,SAAA;AAGhB,OAAK,OAAO;;;;AAShB,IAAa,2BAAb,cAA8C,YAAY;CACxD,YACE,cACA,gBACA;AACA,QACE,oBAAoB,eAAe,kBAAkB,aAAa,8CACnE;AALe,OAAA,eAAA;AACA,OAAA,iBAAA;AAKhB,OAAK,OAAO;;;;AAShB,IAAa,qBAAb,cAAwC,YAAY;CAClD,YACE,SACA,MACA;AACA,QAAM,QAAQ;AAFE,OAAA,OAAA;AAGhB,OAAK,OAAO;;;;AAShB,IAAa,mBAAb,cAAsC,YAAY;CAChD,YAAY,WAAmC;AAC7C,QAAM,wBAAwB,UAAU,IAAI;AADlB,OAAA,YAAA;AAE1B,OAAK,OAAO;;;;;;;;;;AAWhB,IAAa,kBAAb,cAAqC,YAAY;CAC/C,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;AAKhB,IAAa,qBAAb,cAAwC,gBAAgB;CACtD,YAAY,OAAwC;AAClD,QAAM,2BAA2B;AADP,OAAA,QAAA;AAE1B,OAAK,OAAO;;;;AAKhB,IAAa,oBAAb,cAAuC,gBAAgB;CACrD,YAAY,OAA+B;AACzC,QAAM,QAAQ,MAAM,iBAAiB;AADX,OAAA,QAAA;AAE1B,OAAK,OAAO;;;;AAKhB,IAAa,oBAAb,cAAuC,gBAAgB;CACrD,YAAY,OAA+B;AACzC,QAAM,QAAQ,MAAM,iBAAiB;AADX,OAAA,QAAA;AAE1B,OAAK,OAAO;;;;;AC1KhB,MAAM,yBAAyB;AAC/B,MAAM,oBAAoB;AAE1B,SAAgB,wBAAwB,OAAuB,SAAyB;AACtF,QAAO,KAAK,UAAU,qBAAqB,OAAO,SAAS,IAAI,CAAC;;AAGlE,SAAgB,0BAA0B,YAA2C;AACnF,KAAI,eAAe,KACjB,QAAO;AAGT,QAAO,qBAAqB,KAAK,MAAM,WAAW,CAAC;;AAGrD,SAAgB,oBAAoB,OAAuB,SAAiC;AAC1F,QAAO,0BAA0B,wBAAwB,OAAO,QAAQ,CAAC;;AAG3E,SAAgB,qBAAqB,MAAsB,OAAgC;AACzF,KAAI,SAAS,MAAO,QAAO;AAC3B,KAAI,SAAS,QAAQ,UAAU,QAAQ,SAAS,KAAA,KAAa,UAAU,KAAA,EAAW,QAAO,SAAS;AAClG,KAAI,OAAO,SAAS,OAAO,MAAO,QAAO;AACzC,KAAI,OAAO,SAAS,SAAU,QAAO,SAAS;AAC9C,KAAI,gBAAgB,QAAQ,iBAAiB,KAC3C,QAAO,gBAAgB,QAAQ,iBAAiB,QAAQ,KAAK,SAAS,KAAK,MAAM,SAAS;AAE5F,KAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,QAAQ,MAAM,CAAE,QAAO;AACzD,KAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,MAAM,EAAE;AAC/C,MAAI,KAAK,WAAW,MAAM,OAAQ,QAAO;AACzC,SAAO,KAAK,OAAO,OAAO,UAAU,qBAAqB,OAAO,MAAM,OAAO,CAAC;;CAEhF,MAAM,UAAU;CAChB,MAAM,WAAW;CACjB,MAAM,WAAW,OAAO,KAAK,QAAQ;CACrC,MAAM,YAAY,OAAO,KAAK,SAAS;AACvC,KAAI,SAAS,WAAW,UAAU,OAAQ,QAAO;AACjD,QAAO,SAAS,OAAO,QAAQ,qBAAqB,QAAQ,MAAM,SAAS,KAAK,CAAC;;AAGnF,SAAS,qBAAqB,OAAuB,SAAiB,MAAuB;AAC3F,KAAI,UAAU,KAAA,EACZ,QAAO,GAAG,yBAAyB,MAAM;AAG3C,KACE,UAAU,QACP,OAAO,UAAU,YACjB,OAAO,UAAU,UAEpB,QAAO;AAGT,KAAI,OAAO,UAAU,UAAU;AAC7B,MAAI,CAAC,OAAO,SAAS,MAAM,CACzB,OAAM,IAAI,mBAAmB,GAAG,QAAQ,uCAAuC,QAAQ,KAAK;AAE9F,SAAO;;AAGT,KAAI,iBAAiB,MAAM;AACzB,MAAI,CAAC,OAAO,SAAS,MAAM,SAAS,CAAC,CACnC,OAAM,IAAI,mBAAmB,GAAG,QAAQ,uCAAuC,QAAQ,KAAK;AAE9F,SAAO,GAAG,oBAAoB,MAAM,aAAa,EAAE;;AAGrD,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,OAAO,UAAU,qBAAqB,OAAO,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,CAAC;AAG/F,KAAI,cAAc,MAAM,EAAE;AACxB,MAAI,OAAO,UAAU,eAAe,KAAK,OAAO,uBAAuB,CACrE,OAAM,IAAI,mBACR,GAAG,QAAQ,kCAAkC,uBAAuB,OAAO,QAC3E,KACD;AAGH,MAAI,OAAO,UAAU,eAAe,KAAK,OAAO,kBAAkB,CAChE,OAAM,IAAI,mBACR,GAAG,QAAQ,kCAAkC,kBAAkB,OAAO,QACtE,KACD;EAGH,MAAM,UAAmC,EAAE;AAC3C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,SAAQ,OAAO,qBAAqB,OAAO,SAAS,GAAG,KAAK,GAAG,MAAM;AAEvE,SAAO;;AAGT,OAAM,IAAI,mBACR,GAAG,QAAQ,qFAAqF,QAChG,KACD;;AAGH,SAAS,qBAAqB,OAAgC;AAC5D,KACE,UAAU,QACP,UAAU,KAAA,KACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,UAEpB,QAAO;AAGT,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,UAAU,qBAAqB,MAAM,CAAC;AAG1D,KAAI,cAAc,MAAM,EAAE;AACxB,MACE,OAAO,KAAK,MAAM,CAAC,WAAW,KAC3B,MAAM,4BAA4B,KAErC;AAGF,MACE,OAAO,KAAK,MAAM,CAAC,WAAW,KAC3B,OAAO,MAAM,uBAAuB,UACvC;GACA,MAAM,OAAO,IAAI,KAAK,MAAM,mBAA6B;AACzD,OAAI,CAAC,OAAO,SAAS,KAAK,SAAS,CAAC,CAClC,OAAM,IAAI,mBACR,kDAAkD,MAAM,mBAAmB,IAC3E,IACD;AAEH,UAAO;;EAGT,MAAM,UAA2B,EAAE;AACnC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,SAAQ,OAAO,qBAAqB,MAAM;AAE5C,SAAO;;AAGT,OAAM,IAAI,mBAAmB,8CAA8C,IAAI;;AAGjF,SAAS,cAAc,OAAyD;AAC9E,KAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,MAAM,CACrE,QAAO;CAGT,MAAM,YAAY,OAAO,eAAe,MAAM;AAC9C,QAAO,cAAc,OAAO,aAAa,cAAc"}