Files
suaveplan/packages/foundation/flow/streams-metadata/src/errors/errors.ts
2026-05-27 23:47:53 +01:00

87 lines
2.6 KiB
TypeScript

import { defineCodes, SuaveplanError } from "@suaveplan/error";
/**
* Stable error codes for the `@suaveplan/streams-metadata` package. Every
* code is reachable from a real call site in `src/`.
*/
export const STREAMS_METADATA_CODES = defineCodes("STREAMS_METADATA", [
"MIME_FAILED",
"EXIF_FAILED",
"INVALID_PAYLOAD",
"ABORTED",
] as const);
export type StreamsMetadataErrorCode =
(typeof STREAMS_METADATA_CODES)[keyof typeof STREAMS_METADATA_CODES];
interface ErrorOpts {
cause?: unknown;
message?: string;
}
function asErrorCause(c: unknown): Error | undefined {
return c instanceof Error ? c : undefined;
}
/** Base error class for every `@suaveplan/streams-metadata` failure. */
export class StreamsMetadataError extends SuaveplanError<StreamsMetadataErrorCode> {}
/**
* Thrown by `MimeTransform` when MIME detection encounters an internal
* exception. The documented `application/octet-stream` fallback does NOT
* raise this — it is reserved for engine-level failures.
*/
export class MimeDetectionFailedError extends StreamsMetadataError {
constructor(opts: ErrorOpts = {}) {
super(
STREAMS_METADATA_CODES.MIME_FAILED,
opts.message ?? "MIME detection failed",
{ cause: asErrorCause(opts.cause) }
);
}
}
/**
* Thrown by `ExifTransform` when `@suaveplan/exif::readMetadata` raises.
* Preserves the underlying `ExifError` on `cause`.
*/
export class ExifFailedError extends StreamsMetadataError {
constructor(opts: ErrorOpts = {}) {
super(
STREAMS_METADATA_CODES.EXIF_FAILED,
opts.message ?? "EXIF extraction failed",
{ cause: asErrorCause(opts.cause) }
);
}
}
/**
* Thrown when a transform receives a payload missing the mandatory `bytes`
* field.
*/
export class InvalidPayloadError extends StreamsMetadataError {
constructor(opts: ErrorOpts = {}) {
super(
STREAMS_METADATA_CODES.INVALID_PAYLOAD,
opts.message ??
"Streams-metadata payload is missing required `bytes` Uint8Array"
);
}
}
/**
* Thrown when a transform is invoked with an already-aborted `AbortSignal`
* by callers that want every error in the streams-metadata namespace.
* Delegated to from `BaseTransform.assertNotAborted` indirectly when callers
* opt in to the typed wrapping.
*/
export class MetadataAbortedError extends StreamsMetadataError {
constructor(opts: ErrorOpts = {}) {
super(
STREAMS_METADATA_CODES.ABORTED,
opts.message ?? "Streams-metadata operation aborted",
{ cause: asErrorCause(opts.cause) }
);
}
}