{"version":3,"file":"errors.cjs","names":[],"sources":["../src/errors.ts"],"sourcesContent":["import { error as logError } from './_dev';\n\n// ─── Error policy ─────────────────────────────────────────────────────────────\n// One rule for the whole package — decide by whose code failed and whether it\n// can continue, never ad hoc per call site:\n//\n//   API misuse (wrong arguments, hook outside setup, duplicate define)\n//     → throw `OreApiError`, immediately, every build.\n//   User-authored code failing inside ore's execution (setup, onMounted,\n//     onFormReset, each() reconciliation)\n//     → wrap in `OreLifecycleError` and report via `reportRuntimeError()`\n//       (`ore:error` DOM event + dev console) so other callbacks keep running.\n//   Recoverable oddity (overwrite warnings, blocked attribute writes)\n//     → dev `warn()`/`error()` and continue. Never swallow silently.\n//   Internal impossibility (compiled template metadata out of sync)\n//     → `invariant()` throws `OreInternalError`, every build.\n\n// ─── Structured error types ───────────────────────────────────────────────────\n\n/** Base class for all Ore errors. Use `instanceof OreError` to catch any Ore-originated error. */\nexport class OreError extends Error {\n  constructor(message: string, opts?: ErrorOptions) {\n    super(message, opts);\n    this.name = new.target.name;\n    Object.setPrototypeOf(this, new.target.prototype);\n  }\n\n  static is(err: unknown): err is OreError {\n    return err instanceof OreError;\n  }\n}\n\n/** Thrown when Ore API is called incorrectly (e.g. outside setup, duplicate define, invalid prop). */\nexport class OreApiError extends OreError {}\n\n/**\n * Thrown when an internal invariant fails — e.g. compiled template metadata no\n * longer matching the DOM it was cloned from. Distinct from `OreApiError`: this\n * is never the caller's fault, it signals a bug in ore itself. See `invariant()`.\n */\nexport class OreInternalError extends OreError {}\n\n/**\n * The phase in which a component error occurred.\n * - `'setup'` — synchronous setup() threw\n * - `'mounted'` — an onMounted callback threw\n * - `'form-reset'` — an onFormReset callback threw\n * - `'each-reconcile'` — `each()` failed to reconcile a list update (e.g. duplicate keys)\n */\nexport type OreErrorPhase = 'each-reconcile' | 'form-reset' | 'mounted' | 'setup';\n\n/**\n * Structured error thrown by the Ore runtime when component setup fails.\n * Provides component name and original cause for debugging.\n */\nexport class OreLifecycleError extends OreError {\n  readonly component: string;\n  readonly phase: OreErrorPhase;\n\n  constructor(message: string, options: { cause: Error; component: string; phase: OreErrorPhase }) {\n    super(message, { cause: options.cause });\n    this.component = options.component;\n    this.phase = options.phase;\n  }\n}\n\n/**\n * Report a runtime error via the ore:error event and console.\n *\n * `target` only needs to be an `EventTarget` (not specifically an `HTMLElement`) — component\n * lifecycle errors dispatch on the host element, but non-lifecycle failures (e.g. `each()`\n * reconciliation, which has no single \"component\" to attribute the error to) dispatch on\n * whatever live DOM node is available, such as the directive's own anchor `Comment`. Either way\n * the event still bubbles and crosses shadow boundaries (`composed: true`), so a listener on\n * `document`/`window` observes every report regardless of where it originated.\n *\n * The console log (via `_dev.ts`'s `error()`) is still dev-gated like the rest of the package's\n * console diagnostics, but the `ore:error` DOM event dispatch below is **not** — it fires in\n * every build, so consumers always have a way to observe runtime failures programmatically even\n * when console output is stripped in production.\n */\nexport function reportRuntimeError(error: OreLifecycleError, target: EventTarget): void {\n  logError(`<${error.component}> lifecycle error (phase: ${error.phase}):`, error.cause);\n\n  target.dispatchEvent(\n    new CustomEvent('ore:error', {\n      bubbles: true,\n      composed: true,\n      detail: error,\n    }),\n  );\n}\n\n// ─── Error message constants ─────────────────────────────────────────────────\n\n/** Thrown by `flush()` in the testing sub-path when pending component work doesn't settle within the timeout. */\nexport class OreTimeoutError extends OreError {}\n\nexport const ORE_ERRORS = {\n  asyncSetupUnsupported: 'setup() must return an HTMLResult or null; use reactive state for asynchronous work',\n  defineDuplicate: (tag: string): string => `define('${tag}') called twice — custom element already registered`,\n  defineFieldRequiresFormAssociated: (tag: string): string =>\n    `useField() requires define('${tag}', { formAssociated: true })`,\n  defineRequiresTag: 'define() requires a tag name',\n  eachDuplicateKey: (key: string, index: number): string => `each() received duplicate key \"${key}\" at index ${index}`,\n  eventModifiersUnsupported: (eventName: string): string =>\n    `@${eventName}: event modifiers are unsupported; call native event methods in the handler instead`,\n  injectStrictFailed: (key: string, tag: string): string => `injectStrict() could not resolve key \"${key}\" in <${tag}>`,\n  invariantViolated: (message: string): string => `invariant violated: ${message}`,\n  lifecycleOutsideSetup: 'Lifecycle hooks must be called during component setup',\n  listenNullTarget: (eventName: string): string =>\n    `listen() called with a null/undefined target for event \"${eventName}\" — listener not attached`,\n  propInvalidReflect: 'Structured props cannot use reflect:true — use prop.json() with reflect:false',\n  templateInterpolationInTag:\n    'html`...`: interpolations inside a tag must be named attributes, boolean attributes, events, or refs',\n  useFieldAlreadyCalled: (tag: string): string =>\n    `useField() was already called on <${tag}>. Call it only once per component.`,\n  validationFailed: (tag: string, errors: string[]): string => `Validation failed for <${tag}>:\\n${errors.join('\\n')}`,\n} as const;\n\n/**\n * Assert an internal invariant that must always hold — e.g. compiled template\n * metadata staying in sync with the DOM it was cloned from. A failed invariant\n * means a bug in ore itself, never user input, so it throws `OreInternalError`\n * unconditionally (every build, never gated like `_dev.ts`'s `warn()`).\n *\n * Narrowing caveat: `asserts condition` only narrows the exact expression\n * passed in. Assign to a local `const` first — `invariant(el.parentNode, msg)`\n * does not narrow later reads of `el.parentNode`.\n */\nexport function invariant(condition: unknown, message: string): asserts condition {\n  if (!condition) throw new OreInternalError(ORE_ERRORS.invariantViolated(message));\n}\n"],"mappings":"sBAoBA,IAAa,EAAb,MAAa,UAAiB,KAAM,CAClC,YAAY,EAAiB,EAAqB,CAChD,MAAM,EAAS,CAAI,EACnB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CAEA,OAAO,GAAG,EAA+B,CACvC,OAAO,aAAe,CACxB,CACF,EAGa,EAAb,cAAiC,CAAS,CAAC,EAO9B,EAAb,cAAsC,CAAS,CAAC,EAenC,EAAb,cAAuC,CAAS,CAC9C,UACA,MAEA,YAAY,EAAiB,EAAoE,CAC/F,MAAM,EAAS,CAAE,MAAO,EAAQ,KAAM,CAAC,EACvC,KAAK,UAAY,EAAQ,UACzB,KAAK,MAAQ,EAAQ,KACvB,CACF,EAiBA,SAAgB,EAAmB,EAA0B,EAA2B,CAC7E,GAAI,EAAM,UAAV,EAAgD,EAAM,MAAtD,EAAiE,EAAM,MAEhF,EAAO,cACL,IAAI,YAAY,YAAa,CAC3B,QAAS,GACT,SAAU,GACV,OAAQ,CACV,CAAC,CACH,CACF,CAKA,IAAa,EAAb,cAAqC,CAAS,CAAC,EAElC,EAAa,CACxB,sBAAuB,sFACvB,gBAAkB,GAAwB,WAAW,EAAI,qDACzD,kCAAoC,GAClC,+BAA+B,EAAI,8BACrC,kBAAmB,+BACnB,kBAAmB,EAAa,IAA0B,kCAAkC,EAAI,aAAa,IAC7G,0BAA4B,GAC1B,IAAI,EAAU,qFAChB,oBAAqB,EAAa,IAAwB,yCAAyC,EAAI,QAAQ,EAAI,GACnH,kBAAoB,GAA4B,uBAAuB,IACvE,sBAAuB,wDACvB,iBAAmB,GACjB,2DAA2D,EAAU,2BACvE,mBAAoB,gFACpB,2BACE,uGACF,sBAAwB,GACtB,qCAAqC,EAAI,qCAC3C,kBAAmB,EAAa,IAA6B,0BAA0B,EAAI,MAAM,EAAO,KAAK;CAAI,GACnH,EAYA,SAAgB,EAAU,EAAoB,EAAoC,CAChF,GAAI,CAAC,EAAW,MAAM,IAAI,EAAiB,EAAW,kBAAkB,CAAO,CAAC,CAClF"}