@pedrohb/errors 0.0.0-stage → 1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["createParamPlaceholder","DEFAULT_PARAM_DELIMITERS","BASE_ERROR_BRAND","serializeBaseError","isBaseError","serializeCauseError","isUpperSnakeCase","InvalidErrorCode","EitherUnwrapError"],"sources":["../src/interpolate-error-message.ts","../src/base-error.ts","../src/define-error-catalog.ts","../src/either.ts"],"sourcesContent":["import {\r\n createParamPlaceholder,\r\n type DefaultParamDelimiters,\r\n} from \"./functions/create-param-placeholder.js\";\r\nimport type { ErrorDescriptor } from \"./types/error-descriptor.js\";\r\nimport type { ErrorParamDelimiters } from \"./types/error-param-delimiters.js\";\r\nimport type {\r\n ErrorParamValue,\r\n ParamsFromMessage,\r\n} from \"./types/params-from-message.js\";\r\n\r\n/**\r\n * Deriva, em tempo de compilação a lista de argumentos extras exigida para\r\n * interpolar uma mensagem de erro.\r\n *\r\n * - Se a mensagem **não** tiver placeholders o resultado é uma tupla vazia\r\n * (`[]`), ou seja, nenhum argumento adicional deve ser passado.\r\n * - Se tiver placeholders o resultado é uma tupla com um único argumento\r\n * obrigatório, `params` do tipo {@link ParamsFromMessage}.\r\n *\r\n * É pensado para ser usado como tipo de parâmetro rest (`...args`) de modo\r\n * que o objeto de parâmetros seja exigido apenas quando necessário.\r\n *\r\n * @template Message - Mensagem a ser analisada.\r\n * @template Delimiters - Objeto com os delimitadores `open` e `close` do\r\n * placeholder. Por padrão, {@link DefaultParamDelimiters}.\r\n *\r\n * @example\r\n * ```ts\r\n * type A = ErrorMessageArgs<\"Usuário {id} não encontrado\">;\r\n * // [params: Readonly<{ id: ErrorParamValue }>]\r\n *\r\n * type B = ErrorMessageArgs<\"Token inválido\">;\r\n * // []\r\n *\r\n * type C = ErrorMessageArgs<\r\n * \"Rota [route] não encontrada\",\r\n * { readonly open: \"[\"; readonly close: \"]\" }\r\n * >;\r\n * // [params: Readonly<{ route: ErrorParamValue }>]\r\n * ```\r\n */\r\nexport type ErrorMessageArgs<\r\n Message extends string,\r\n Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters,\r\n> = [ParamsFromMessage<Message, Delimiters>] extends [never]\r\n ? []\r\n : [params: ParamsFromMessage<Message, Delimiters>];\r\n\r\n/**\r\n * Interpola os parâmetros informados na mensagem de um descritor de erro\r\n * substituindo cada placeholder pelo valor correspondente.\r\n *\r\n * Os placeholders são localizados com {@link createParamPlaceholder} a partir\r\n * dos delimitadores informados. O nome de cada placeholder é aparado\r\n * (`{ id }` equivale a `{id}`) e o valor é convertido para texto com `String`.\r\n *\r\n * O placeholder é mantido exatamente como está na mensagem (sem substituição)\r\n * quando:\r\n * - o nome é vazio (ex.: `{}` ou `{ }`);\r\n * - o nome não existe como propriedade própria de `params`.\r\n *\r\n * O objeto de parâmetros é exigido ou omitido conforme a mensagem via\r\n * {@link ErrorMessageArgs}: mensagens sem placeholders não aceitam `params` e\r\n * mensagens com placeholders exigem todos eles.\r\n *\r\n * @template Descriptor - Tipo do descritor de erro cuja `message` define os\r\n * parâmetros exigidos.\r\n * @template Delimiters - Tipo dos delimitadores dos placeholders. Por padrão,\r\n * {@link DefaultParamDelimiters}.\r\n * @param descriptor - Descritor de erro cuja mensagem será interpolada.\r\n * @param delimiters - Delimitadores `open` e `close` dos placeholders.\r\n * @param args - Objeto `params` com os valores dos placeholders exigido\r\n * apenas se a mensagem tiver placeholders.\r\n * @returns A mensagem com os placeholders substituídos.\r\n * @throws {InvalidParamDelimitersError} Se `open` ou `close` for uma string\r\n * vazia (lançado por {@link createParamPlaceholder}).\r\n *\r\n * @example\r\n * ```ts\r\n * const keys = { open: \"{\", close: \"}\" } as const;\r\n *\r\n * const USER_NOT_FOUND = {\r\n * code: \"USER_NOT_FOUND\",\r\n * message: \"Usuário {id} não encontrado em {table}\",\r\n * } as const satisfies ErrorDescriptor;\r\n *\r\n * interpolateErrorMessage(USER_NOT_FOUND, keys, {\r\n * id: 42,\r\n * table: \"users\",\r\n * });\r\n * // \"Usuário 42 não encontrado em users\"\r\n *\r\n * const INVALID_TOKEN = {\r\n * code: \"INVALID_TOKEN\",\r\n * message: \"Token inválido\",\r\n * } as const satisfies ErrorDescriptor;\r\n *\r\n * interpolateErrorMessage(INVALID_TOKEN, keys);\r\n * // \"Token inválido\" (sem params)\r\n *\r\n * // Delimitadores personalizados\r\n * const ROUTE_NOT_FOUND = {\r\n * code: \"ROUTE_NOT_FOUND\",\r\n * message: \"Rota [route] não encontrada\",\r\n * } as const satisfies ErrorDescriptor;\r\n *\r\n * interpolateErrorMessage(\r\n * ROUTE_NOT_FOUND,\r\n * { open: \"[\", close: \"]\" } as const,\r\n * { route: \"/home\" },\r\n * );\r\n * // \"Rota /home não encontrada\"\r\n * ```\r\n */\r\nexport function interpolateErrorMessage<\r\n Descriptor extends ErrorDescriptor,\r\n Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters,\r\n>(\r\n descriptor: Descriptor,\r\n delimiters: Delimiters,\r\n ...args: ErrorMessageArgs<Descriptor[\"message\"], Delimiters>\r\n) {\r\n const params = (args[0] ?? {}) as Record<string, ErrorParamValue>;\r\n const placeholder = createParamPlaceholder(delimiters);\r\n\r\n return descriptor.message.replace(placeholder, (match, rawKey: string) => {\r\n const key = rawKey.trim();\r\n\r\n if (key === \"\" || !Object.hasOwn(params, key)) {\r\n return match;\r\n }\r\n\r\n return String(params[key]);\r\n });\r\n}\r\n","import {\r\n DEFAULT_PARAM_DELIMITERS,\r\n type DefaultParamDelimiters,\r\n} from \"./functions/create-param-placeholder.js\";\r\nimport { BASE_ERROR_BRAND, isBaseError } from \"./functions/is-base-error.js\";\r\nimport { serializeBaseError } from \"./functions/serialize-base-error.js\";\r\nimport { serializeCauseError } from \"./functions/serialize-cause-error.js\";\r\nimport {\r\n type ErrorMessageArgs,\r\n interpolateErrorMessage,\r\n} from \"./interpolate-error-message.js\";\r\nimport type { CatalogCode } from \"./types/catalog-code.js\";\r\nimport type { CatalogDescriptor } from \"./types/catalog-descriptor.js\";\r\nimport type { ErrorCatalog } from \"./types/error-catalog.js\";\r\nimport type { ErrorParamDelimiters } from \"./types/error-param-delimiters.js\";\r\nimport type { ErrorParams } from \"./types/error-params.js\";\r\n\r\n/**\r\n * Opções aceitas pelo construtor de {@link BaseError}.\r\n *\r\n * Estende `ErrorOptions` (que fornece `cause`) e acrescenta:\r\n * - `delimiters`: delimitadores dos placeholders da mensagem sempre opcional;\r\n * - `params`: valores dos placeholders **exigido apenas** quando a mensagem\r\n * do código possui placeholders (ver {@link ErrorParams}). Se a mensagem não\r\n * tiver placeholders a propriedade `params` não existe no tipo.\r\n *\r\n * @template Catalog - Catálogo de erros ao qual o código pertence. Por padrão,\r\n * `ErrorCatalog`.\r\n * @template Code - Código do erro dentro do catálogo. Por padrão, todos os\r\n * códigos do catálogo.\r\n * @template Delimiters - Tipo dos delimitadores dos placeholders. Por padrão,\r\n * {@link DefaultParamDelimiters}.\r\n *\r\n * @example\r\n * ```ts\r\n * // Mensagem sem placeholders: apenas `cause` e `delimiters` são aceitos\r\n * type A = BaseErrorOptions<typeof ERROR_CODES, \"INVALID_TOKEN\">;\r\n * // ErrorOptions & { delimiters?: DefaultParamDelimiters }\r\n *\r\n * // Mensagem com placeholders: `params` é obrigatório\r\n * type B = BaseErrorOptions<typeof ERROR_CODES, \"USER_NOT_FOUND\">;\r\n * // ErrorOptions & { params: Readonly<{ id: ErrorParamValue }>; delimiters?: ... }\r\n * ```\r\n */\r\nexport type BaseErrorOptions<\r\n Catalog extends ErrorCatalog = ErrorCatalog,\r\n Code extends CatalogCode<Catalog> = CatalogCode<Catalog>,\r\n Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters,\r\n> = [ErrorParams<Catalog, Code, Delimiters>] extends [never]\r\n ? ErrorOptions & {\r\n delimiters?: Delimiters;\r\n }\r\n : ErrorOptions & {\r\n params: ErrorParams<Catalog, Code, Delimiters>;\r\n delimiters?: Delimiters;\r\n };\r\n\r\n/**\r\n * Deriva em tempo de compilação a lista de argumentos de opções do\r\n * construtor de {@link BaseError}.\r\n *\r\n * - Se a mensagem **não** tiver placeholders `options` é opcional.\r\n * - Se tiver placeholders `options` é obrigatório (pois deve conter `params`).\r\n *\r\n * É pensado para ser usado como tipo de parâmetro rest (`...args`).\r\n *\r\n * @template Catalog - Catálogo de erros ao qual o código pertence. Por padrão,\r\n * `ErrorCatalog`.\r\n * @template Code - Código do erro dentro do catálogo. Por padrão, todos os\r\n * códigos do catálogo.\r\n * @template Delimiters - Tipo dos delimitadores dos placeholders. Por padrão,\r\n * {@link DefaultParamDelimiters}.\r\n *\r\n * @example\r\n * ```ts\r\n * type A = BaseErrorOptionsArgs<typeof ERROR_CODES, \"INVALID_TOKEN\">;\r\n * // [options?: BaseErrorOptions<...>]\r\n *\r\n * type B = BaseErrorOptionsArgs<typeof ERROR_CODES, \"USER_NOT_FOUND\">;\r\n * // [options: BaseErrorOptions<...>]\r\n * ```\r\n */\r\nexport type BaseErrorOptionsArgs<\r\n Catalog extends ErrorCatalog = ErrorCatalog,\r\n Code extends CatalogCode<Catalog> = CatalogCode<Catalog>,\r\n Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters,\r\n> = [ErrorParams<Catalog, Code, Delimiters>] extends [never]\r\n ? [options?: BaseErrorOptions<Catalog, Code, Delimiters>]\r\n : [options: BaseErrorOptions<Catalog, Code, Delimiters>];\r\n\r\n/**\r\n * Classe base abstrata para erros tipados a partir de um catálogo de erros.\r\n *\r\n * Cada erro é criado a partir de um descritor do catálogo (código e mensagem).\r\n * A mensagem é interpolada com os `params` informados e o tipo dos `params` é\r\n * derivado dos placeholders da mensagem, de modo que o compilador exige\r\n * exatamente os parâmetros necessários.\r\n *\r\n * O construtor é `protected`: a classe não pode ser instanciada diretamente e\r\n * deve ser estendida por classes que escolhem o descritor e repassam as\r\n * opções.\r\n *\r\n * Além de `message`, `cause`, `stack` e `name` herdados de `Error`, a\r\n * instância expõe:\r\n * - `code`: o código do erro, com tipo literal;\r\n * - `params`: os parâmetros usados na interpolação (ou `undefined`);\r\n * - {@link BaseError.serialize} e {@link BaseError.toJSON} para serialização;\r\n * - uma marca interna ({@link BASE_ERROR_BRAND}) que permite reconhecer o\r\n * erro com {@link isBaseError} mesmo com múltiplas cópias do pacote.\r\n *\r\n * O `name` do erro é o nome da classe concreta (`new.target.name`) e o\r\n * protótipo é ajustado explicitamente para que `instanceof` funcione em\r\n * subclasses mesmo em alvos de compilação antigos.\r\n *\r\n * @template Catalog - Catálogo de erros ao qual o código pertence. Por padrão,\r\n * `ErrorCatalog`.\r\n * @template Code - Código do erro dentro do catálogo. Por padrão, todos os\r\n * códigos do catálogo.\r\n * @template Delimiters - Tipo dos delimitadores dos placeholders. Por padrão,\r\n * {@link DefaultParamDelimiters}.\r\n *\r\n * @example\r\n * ```ts\r\n * const TEST_ERROR_CODES = defineErrorCatalog({\r\n * USER_NOT_FOUND: \"Usuário {id} não encontrado\",\r\n * INVALID_TOKEN: \"Token inválido\",\r\n * });\r\n *\r\n * type TestErrorCodes = typeof TEST_ERROR_CODES;\r\n *\r\n * class UserNotFoundError extends BaseError<TestErrorCodes, \"USER_NOT_FOUND\"> {\r\n * public constructor(id: number, options?: ErrorOptions) {\r\n * super(TEST_ERROR_CODES.USER_NOT_FOUND, { params: { id }, ...options });\r\n * }\r\n * }\r\n *\r\n * class InvalidTokenError extends BaseError<TestErrorCodes, \"INVALID_TOKEN\"> {\r\n * public constructor(options?: ErrorOptions) {\r\n * super(TEST_ERROR_CODES.INVALID_TOKEN, options);\r\n * }\r\n * }\r\n *\r\n * const erro = new UserNotFoundError(42);\r\n * erro.message; // \"Usuário 42 não encontrado\"\r\n * erro.code; // \"USER_NOT_FOUND\"\r\n * erro.params; // { id: 42 }\r\n * erro.name; // \"UserNotFoundError\"\r\n *\r\n * BaseError.is(erro); // true\r\n * JSON.stringify(erro); // usa toJSON(), sem stack trace\r\n * erro.serialize(true); // inclui o stack trace\r\n * ```\r\n */\r\nexport abstract class BaseError<\r\n Catalog extends ErrorCatalog = ErrorCatalog,\r\n Code extends CatalogCode<Catalog> = CatalogCode<Catalog>,\r\n Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters,\r\n> extends Error {\r\n /** Código do erro conforme o catálogo (ex.: `\"USER_NOT_FOUND\"`). */\r\n public readonly code: Code;\r\n /**\r\n * Parâmetros usados para interpolar a mensagem. É `undefined` quando a\r\n * mensagem não possui placeholders (ou quando nenhum `params` foi informado).\r\n */\r\n public readonly params?: ErrorParams<Catalog, Code, Delimiters>;\r\n\r\n /**\r\n * Cria um erro a partir de um descritor do catálogo.\r\n *\r\n * A mensagem do descritor é interpolada com `options.params` usando os\r\n * delimitadores de `options.delimiters` (por padrão,\r\n * {@link DEFAULT_PARAM_DELIMITERS}). Os delimitadores são usados apenas na\r\n * interpolação e não são armazenados na instância. O objeto `options`\r\n * também é repassado ao construtor de `Error`, que utiliza `cause`.\r\n *\r\n * É `protected` então só pode ser chamado por subclasses.\r\n *\r\n * @param descriptor - Descritor do erro no catálogo com `code` e `message`.\r\n * @param args - Opções do erro ({@link BaseErrorOptions}). São obrigatórias\r\n * se a mensagem tiver placeholders (por conter `params`) e opcionais caso\r\n * contrário.\r\n * @throws {InvalidParamDelimitersError} Se algum dos delimitadores for uma\r\n * string vazia (lançado durante a interpolação).\r\n */\r\n protected constructor(\r\n descriptor: CatalogDescriptor<Catalog, Code>,\r\n ...args: BaseErrorOptionsArgs<Catalog, Code, Delimiters>\r\n ) {\r\n const options = args[0];\r\n const delimiters = (options?.delimiters ??\r\n DEFAULT_PARAM_DELIMITERS) as Delimiters;\r\n const params = options && \"params\" in options ? options.params : undefined;\r\n const interpolationArgs = (\r\n params === undefined ? [] : [params]\r\n ) as ErrorMessageArgs<\r\n CatalogDescriptor<Catalog, Code>[\"message\"],\r\n Delimiters\r\n >;\r\n\r\n super(\r\n interpolateErrorMessage(descriptor, delimiters, ...interpolationArgs),\r\n options,\r\n );\r\n\r\n this.name = new.target.name;\r\n this.code = descriptor.code;\r\n this.params = params;\r\n\r\n Object.setPrototypeOf(this, new.target.prototype);\r\n\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, new.target);\r\n }\r\n }\r\n\r\n /**\r\n * Marca interna que identifica a instância como um `BaseError`.\r\n *\r\n * Sempre retorna `true` e é lida por {@link isBaseError}. Por ser um\r\n * getter definido no protótipo, não é uma propriedade própria da instância\r\n * e portanto, não aparece em serializações nem em `Object.keys`.\r\n */\r\n public get [BASE_ERROR_BRAND]() {\r\n return true;\r\n }\r\n\r\n /**\r\n * Serializa o erro para um objeto simples apropriado para `JSON.stringify`,\r\n * logs ou transmissão. Veja {@link serializeBaseError} para os detalhes do\r\n * formato retornado.\r\n *\r\n * @param includeStack - Se `true` inclui o stack trace no resultado (e na\r\n * serialização de causas e parâmetros). Por padrão, `false`.\r\n * @returns Representação serializável do erro.\r\n */\r\n public serialize(includeStack = false) {\r\n return serializeBaseError(this as Readonly<BaseError>, includeStack);\r\n }\r\n\r\n /**\r\n * Chamado automaticamente por `JSON.stringify`. Equivale a\r\n * {@link BaseError.serialize} sem stack trace.\r\n *\r\n * @returns Representação serializável do erro sem stack trace.\r\n */\r\n public toJSON() {\r\n return this.serialize();\r\n }\r\n\r\n /**\r\n * Verifica se um valor é uma instância de `BaseError` (type guard).\r\n *\r\n * Atalho para {@link isBaseError}: usa a marca interna em vez de\r\n * `instanceof` funcionando mesmo com múltiplas cópias do pacote.\r\n *\r\n * @param error - Valor a ser verificado.\r\n * @returns `true` se `error` for um `BaseError`; caso contrário, `false`.\r\n */\r\n public static is(error: unknown): error is BaseError {\r\n return isBaseError(error);\r\n }\r\n\r\n /**\r\n * Serializa de forma segura qualquer valor usado como causa de um erro.\r\n *\r\n * Atalho para {@link serializeCauseError}: trata erros, datas, arrays,\r\n * objetos, funções, `bigint`, `symbol` e referências circulares.\r\n *\r\n * @param cause - Valor a ser serializado.\r\n * @param includeStack - Se `true` inclui o stack trace ao serializar\r\n * erros. Por padrão, `false`.\r\n * @returns Representação serializável do valor.\r\n */\r\n public static serializeCauseError(cause: unknown, includeStack = false) {\r\n return serializeCauseError(cause, includeStack);\r\n }\r\n}\r\n","import { InvalidErrorCode } from \"./errors/invalid-error-code.js\";\r\nimport type { ErrorCatalog } from \"./types/error-catalog.js\";\r\nimport type { ErrorDescriptor } from \"./types/error-descriptor.js\";\r\nimport type { ValidateErrorDefinitions } from \"./types/validate-error-definitions.js\";\r\nimport { isUpperSnakeCase } from \"./upper-snake-case.js\";\r\n\r\n/**\r\n * Cria um catálogo de erros imutável a partir de um objeto que associa cada\r\n * código de erro à sua mensagem.\r\n *\r\n * Para cada entrada de `definitions` gera um {@link ErrorDescriptor} com\r\n * `code` e `message` congelado com `Object.freeze`. O próprio catálogo\r\n * retornado também é congelado, de modo que nem o catálogo nem seus\r\n * descritores podem ser alterados depois de criados.\r\n *\r\n * A validação ocorre em duas camadas:\r\n * - em tempo de compilação via {@link ValidateErrorDefinitions}: códigos fora\r\n * de UPPER_SNAKE_CASE geram um erro de tipo com uma mensagem explicativa;\r\n * - em tempo de execução via {@link isUpperSnakeCase}: códigos inválidos\r\n * lançam {@link InvalidErrorCode}, o que protege contra definições que\r\n * escapem da checagem de tipos (ex.: objetos tipados como `any` ou\r\n * `Record<string, string>`).\r\n *\r\n * O parâmetro de tipo `T` é declarado como `const`, o que preserva os tipos\r\n * literais dos códigos e das mensagens sem a necessidade de `as const` na\r\n * chamada.\r\n *\r\n * @template Codes - Objeto que mapeia códigos de erro para suas mensagens.\r\n * @param definitions - Definições do catálogo: chaves são os códigos em\r\n * UPPER_SNAKE_CASE.\r\n * @returns Catálogo de erros somente leitura com um descritor para cada\r\n * código informado.\r\n * @throws {InvalidErrorCode} Se algum código não estiver em UPPER_SNAKE_CASE.\r\n *\r\n * @example\r\n * ```ts\r\n * const TEST_ERROR_CODES = defineErrorCatalog({\r\n * USER_NOT_FOUND: \"Usuário {id} não encontrado\",\r\n * INVALID_TOKEN: \"Token inválido\",\r\n * });\r\n *\r\n * TEST_ERROR_CODES.USER_NOT_FOUND.code; // \"USER_NOT_FOUND\"\r\n * TEST_ERROR_CODES.USER_NOT_FOUND.message; // \"Usuário {id} não encontrado\"\r\n *\r\n * // Erro de compilação (e de execução): código fora de UPPER_SNAKE_CASE\r\n * defineErrorCatalog({\r\n * userNotFound: \"Usuário não encontrado\",\r\n * });\r\n * // Lança InvalidErrorCode\r\n * ```\r\n */\r\nexport function defineErrorCatalog<const Codes extends Record<string, string>>(\r\n definitions: ValidateErrorDefinitions<Codes>,\r\n): ErrorCatalog<Codes> {\r\n const catalog: Record<string, ErrorDescriptor> = {};\r\n\r\n for (const [code, message] of Object.entries(\r\n definitions as Record<string, string>,\r\n )) {\r\n if (!isUpperSnakeCase(code)) {\r\n throw new InvalidErrorCode(code);\r\n }\r\n\r\n catalog[code] = Object.freeze({ code, message });\r\n }\r\n\r\n return Object.freeze(catalog) as ErrorCatalog<Codes>;\r\n}\r\n","import { EitherUnwrapError } from \"./errors/either-unwrap-error.js\";\r\n\r\n/**\r\n * Representa o resultado de uma operação que pode ter sucesso (`Ok`) ou\r\n * falhar (`Err`), tornando o erro parte explícita do tipo de retorno em vez\r\n * de depender de exceções.\r\n *\r\n * Um `Either<O, E>` é sempre uma instância de {@link Ok} que carrega um\r\n * valor de sucesso do tipo `O`, ou de {@link Err} que carrega um valor de\r\n * erro do tipo `E`. Use {@link ok} e {@link err} para criá-los.\r\n *\r\n * Os métodos {@link Either.map}, {@link Either.mapErr}, {@link Either.flatMap}\r\n * e {@link Either.orElse} retornam um novo `Either` e não alteram o original.\r\n * Para tratar os dois casos use {@link Either.match}, ou os type guards\r\n * {@link Either.isOk} e {@link Either.isErr}.\r\n *\r\n * @template O - Tipo do valor de sucesso.\r\n * @template E - Tipo do valor de erro.\r\n *\r\n * @example\r\n * ```ts\r\n * function toDivide(a: number, b: number): Either<number, string> {\r\n * return b === 0 ? err(\"Divisão por zero\") : ok(a / b);\r\n * }\r\n *\r\n * const message = toDivide(10, 2)\r\n * .map((resultado) => resultado * 3)\r\n * .match({\r\n * onOk: (valor) => `Resultado: ${valor}`,\r\n * onErr: (erro) => `Falha: ${erro}`,\r\n * });\r\n * // \"Resultado: 15\"\r\n * ```\r\n */\r\nexport abstract class Either<O, E> {\r\n /** Discriminante da variante: `\"Ok\"` para sucesso e `\"Err\"` para erro. */\r\n public abstract readonly tag: \"Ok\" | \"Err\";\r\n\r\n /**\r\n * Retorna o valor de sucesso.\r\n *\r\n * @returns O valor contido em `Ok`.\r\n * @throws {EitherUnwrapError} Se for um `Err`. A `cause` do erro é o valor\r\n * de erro contido.\r\n */\r\n public abstract unwrap(): O;\r\n\r\n /**\r\n * Retorna o valor de erro.\r\n *\r\n * @returns O valor contido em `Err`.\r\n * @throws {EitherUnwrapError} Se for um `Ok`. A `cause` do erro é o valor\r\n * de sucesso contido.\r\n */\r\n public abstract unwrapErr(): E;\r\n\r\n /**\r\n * Verifica se é um `Ok` funcionando como type guard.\r\n *\r\n * @returns `true` se for `Ok` (restringindo o tipo para {@link Ok});\r\n * caso contrário, `false`.\r\n */\r\n public abstract isOk(): this is Ok<O, E>;\r\n\r\n /**\r\n * Verifica se é um `Err` funcionando como type guard.\r\n *\r\n * @returns `true` se for `Err` (restringindo o tipo para {@link Err});\r\n * caso contrário, `false`.\r\n */\r\n public abstract isErr(): this is Err<O, E>;\r\n\r\n /**\r\n * Transforma o valor de sucesso mantendo o erro intacto.\r\n *\r\n * Se for `Ok` aplica `fn` ao valor e retorna um novo `Ok` com o resultado.\r\n * Se for `Err` `fn` não é chamada e um novo `Err` com o mesmo erro é\r\n * retornado. Exceções lançadas por `fn` não são capturadas.\r\n *\r\n * @template O2 - Tipo do novo valor de sucesso.\r\n * @param fn - Função que converte o valor de sucesso.\r\n * @returns Um `Either` com o valor transformado ou o erro original.\r\n *\r\n * @example\r\n * ```ts\r\n * ok<number, string>(2).map((n) => n * 2).unwrap(); // 4\r\n * err<number, string>(\"falhou\").map((n) => n * 2).unwrapErr(); // \"falhou\"\r\n * ```\r\n */\r\n public map<O2>(fn: (value: O) => O2): Either<O2, E> {\r\n if (this.isOk()) {\r\n return ok(fn(this.unwrap()));\r\n }\r\n\r\n return err(this.unwrapErr());\r\n }\r\n\r\n /**\r\n * Transforma o valor de erro mantendo o sucesso intacto.\r\n *\r\n * Se for `Err` aplica `fn` ao erro e retorna um novo `Err` com o resultado.\r\n * Se for `Ok` `fn` não é chamada e um novo `Ok` com o mesmo valor é\r\n * retornado. Exceções lançadas por `fn` não são capturadas.\r\n *\r\n * @template E2 - Tipo do novo valor de erro.\r\n * @param fn - Função que converte o valor de erro.\r\n * @returns Um `Either` com o erro transformado ou o valor original.\r\n *\r\n * @example\r\n * ```ts\r\n * err<number, string>(\"falhou\").mapErr((e) => e.length).unwrapErr(); // 7\r\n * ok<number, string>(1).mapErr((e) => e.length).unwrap(); // 1\r\n * ```\r\n */\r\n public mapErr<E2>(fn: (value: E) => E2): Either<O, E2> {\r\n if (this.isErr()) {\r\n return err(fn(this.unwrapErr()));\r\n }\r\n\r\n return ok(this.unwrap());\r\n }\r\n\r\n /**\r\n * Encadeia uma operação que também retorna um `Either` usada quando o\r\n * próximo passo também pode falhar.\r\n *\r\n * Se for `Ok`, retorna diretamente o `Either` produzido por `fn` (sem\r\n * aninhamento). Se for `Err` `fn` não é chamada e o erro é propagado.\r\n * O tipo de erro resultante é a união `E | E2`. Exceções lançadas por `fn`\r\n * não são capturadas.\r\n *\r\n * @template O2 - Tipo do valor de sucesso retornado por `fn`.\r\n * @template E2 - Tipo do valor de erro retornado por `fn`.\r\n * @param fn - Função que recebe o valor de sucesso e retorna um `Either`.\r\n * @returns O `Either` retornado por `fn`, ou o erro original.\r\n *\r\n * @example\r\n * ```ts\r\n * const forNumber = (s: string): Either<number, string> => {\r\n * const n = Number(s);\r\n * return Number.isNaN(n) ? err(\"Não é número\") : ok(n);\r\n * };\r\n *\r\n * ok<string, string>(\"42\").flatMap(forNumber).unwrap(); // 42\r\n * ok<string, string>(\"abc\").flatMap(forNumber).unwrapErr(); // \"Não é número\"\r\n * ```\r\n */\r\n public flatMap<O2, E2>(fn: (value: O) => Either<O2, E2>): Either<O2, E | E2> {\r\n if (this.isOk()) {\r\n return fn(this.unwrap());\r\n }\r\n\r\n return err(this.unwrapErr());\r\n }\r\n\r\n /**\r\n * Tenta se recuperar de um erro encadeando uma operação alternativa que\r\n * também retorna um `Either`. É o oposto de {@link Either.flatMap}.\r\n *\r\n * Se for `Err` retorna diretamente o `Either` produzido por `fn`. Se for\r\n * `Ok` `fn` não é chamada e o valor é mantido. O tipo de sucesso\r\n * resultante é a união `O | O2`. Exceções lançadas por `fn` não são\r\n * capturadas.\r\n *\r\n * @template O2 - Tipo do valor de sucesso retornado por `fn`.\r\n * @template E2 - Tipo do valor de erro retornado por `fn`.\r\n * @param fn - Função que recebe o valor de erro e retorna um `Either`.\r\n * @returns O `Either` retornado por `fn`, ou o valor de sucesso original.\r\n *\r\n * @example\r\n * ```ts\r\n * err<number, string>(\"falhou\").orElse(() => ok(0)).unwrap(); // 0\r\n * ok<number, string>(5).orElse(() => ok(0)).unwrap(); // 5\r\n * ```\r\n */\r\n public orElse<O2, E2>(fn: (value: E) => Either<O2, E2>): Either<O | O2, E2> {\r\n if (this.isErr()) {\r\n return fn(this.unwrapErr());\r\n }\r\n\r\n return ok(this.unwrap());\r\n }\r\n\r\n /**\r\n * Trata os dois casos e produz um único valor chamando o handler da\r\n * variante correspondente.\r\n *\r\n * @template R - Tipo do valor retornado pelos handlers.\r\n * @param handlers - Objeto com `onOk` chamado com o valor de sucesso e\r\n * `onErr` chamado com o valor de erro.\r\n * @returns O resultado do handler chamado.\r\n *\r\n * @example\r\n * ```ts\r\n * const texto = resultado.match({\r\n * onOk: (valor) => `Sucesso: ${valor}`,\r\n * onErr: (erro) => `Erro: ${erro}`,\r\n * });\r\n * ```\r\n */\r\n public match<R>(\r\n handlers: Readonly<{ onOk(value: O): R; onErr(value: E): R }>,\r\n ): R {\r\n if (this.isOk()) {\r\n return handlers.onOk(this.unwrap());\r\n }\r\n\r\n return handlers.onErr(this.unwrapErr());\r\n }\r\n}\r\n\r\n/**\r\n * Variante de sucesso de {@link Either} que carrega um valor do tipo `O`.\r\n *\r\n * O construtor é `protected`; para criar uma instância use {@link Ok.create}\r\n * ou a função {@link ok}.\r\n *\r\n * @template O - Tipo do valor de sucesso. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro usado apenas para compatibilidade com\r\n * {@link Either}. Por padrão, `never`.\r\n */\r\nexport class Ok<O = never, E = never> extends Either<O, E> {\r\n /** Discriminante da variante sempre `\"Ok\"`. */\r\n public readonly tag = \"Ok\" as const;\r\n /** Valor de sucesso armazenado. */\r\n private readonly value: O;\r\n\r\n /**\r\n * @param value - Valor de sucesso a ser armazenado.\r\n */\r\n protected constructor(value: O) {\r\n super();\r\n\r\n this.value = value;\r\n }\r\n\r\n /**\r\n * Retorna o valor de sucesso armazenado.\r\n *\r\n * @returns O valor contido.\r\n */\r\n public unwrap(): O {\r\n return this.value;\r\n }\r\n\r\n /**\r\n * Sempre lança um erro pois um `Ok` não possui valor de erro.\r\n *\r\n * @throws {EitherUnwrapError} Sempre. A `cause` é o valor de sucesso contido.\r\n */\r\n public unwrapErr(): E {\r\n throw new EitherUnwrapError(\"Chamado unwrapErr() em Ok.\", {\r\n cause: this.value,\r\n });\r\n }\r\n\r\n /** @returns Sempre `true`. */\r\n public isOk(): this is Ok<O, E> {\r\n return true;\r\n }\r\n\r\n /** @returns Sempre `false`. */\r\n public isErr(): this is Err<O, E> {\r\n return false;\r\n }\r\n\r\n /**\r\n * Cria um `Ok` com o valor informado.\r\n *\r\n * @template O - Tipo do valor de sucesso. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro. Por padrão, `never`.\r\n * @param value - Valor de sucesso.\r\n * @returns Uma nova instância de `Ok`.\r\n */\r\n public static create<O = never, E = never>(value: O): Ok<O, E> {\r\n return new Ok(value);\r\n }\r\n}\r\n\r\n/**\r\n * Variante de erro de {@link Either} que carrega um valor do tipo `E`.\r\n *\r\n * O construtor é `protected`; para criar uma instância use {@link Err.create}\r\n * ou a função {@link err}.\r\n *\r\n * @template O - Tipo do valor de sucesso usado apenas para compatibilidade\r\n * com {@link Either}. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro. Por padrão, `never`.\r\n */\r\nexport class Err<O = never, E = never> extends Either<O, E> {\r\n /** Discriminante da variante sempre `\"Err\"`. */\r\n public readonly tag = \"Err\" as const;\r\n /** Valor de erro armazenado. */\r\n private readonly value: E;\r\n\r\n /**\r\n * @param value - Valor de erro a ser armazenado.\r\n */\r\n protected constructor(value: E) {\r\n super();\r\n\r\n this.value = value;\r\n }\r\n\r\n /**\r\n * Sempre lança um erro pois um `Err` não possui valor de sucesso.\r\n *\r\n * @throws {EitherUnwrapError} Sempre. A `cause` é o valor de erro contido.\r\n */\r\n public unwrap(): O {\r\n throw new EitherUnwrapError(\"Chamado unwrap() em Err.\", {\r\n cause: this.value,\r\n });\r\n }\r\n\r\n /**\r\n * Retorna o valor de erro armazenado.\r\n *\r\n * @returns O valor contido.\r\n */\r\n public unwrapErr(): E {\r\n return this.value;\r\n }\r\n\r\n /** @returns Sempre `false`. */\r\n public isOk(): this is Ok<O, E> {\r\n return false;\r\n }\r\n\r\n /** @returns Sempre `true`. */\r\n public isErr(): this is Err<O, E> {\r\n return true;\r\n }\r\n\r\n /**\r\n * Cria um `Err` com o valor informado.\r\n *\r\n * @template O - Tipo do valor de sucesso. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro. Por padrão, `never`.\r\n * @param value - Valor de erro.\r\n * @returns Uma nova instância de `Err`.\r\n */\r\n public static create<O = never, E = never>(value: E): Err<O, E> {\r\n return new Err(value);\r\n }\r\n}\r\n\r\n/**\r\n * Cria um {@link Either} de sucesso (`Ok`) com o valor informado.\r\n *\r\n * O retorno é tipado como `Either<O, E>` e não como `Ok` para que possa ser\r\n * usado onde se espera qualquer variante. Como `E` não pode ser inferido a\r\n * partir do argumento, informe-o explicitamente quando necessário.\r\n *\r\n * @template O - Tipo do valor de sucesso. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro. Por padrão, `never`.\r\n * @param value - Valor de sucesso.\r\n * @returns Um `Either` que é um `Ok` contendo `value`.\r\n *\r\n * @example\r\n * ```ts\r\n * const result = ok<number, string>(42);\r\n * result.isOk(); // true\r\n * result.unwrap(); // 42\r\n * ```\r\n */\r\nexport function ok<O = never, E = never>(value: O): Either<O, E> {\r\n return Ok.create(value);\r\n}\r\n\r\n/**\r\n * Cria um {@link Either} de erro (`Err`) com o valor informado.\r\n *\r\n * O retorno é tipado como `Either<O, E>` e não como `Err` para que possa ser\r\n * usado onde se espera qualquer variante. Como `O` não pode ser inferido a\r\n * partir do argumento, informe-o explicitamente quando necessário.\r\n *\r\n * @template O - Tipo do valor de sucesso. Por padrão, `never`.\r\n * @template E - Tipo do valor de erro. Por padrão, `never`.\r\n * @param value - Valor de erro.\r\n * @returns Um `Either` que é um `Err` contendo `value`.\r\n *\r\n * @example\r\n * ```ts\r\n * const result = err<number, string>(\"Algo deu errado\");\r\n * result.isErr(); // true\r\n * result.unwrapErr(); // \"Algo deu errado\"\r\n * ```\r\n */\r\nexport function err<O = never, E = never>(value: E): Either<O, E> {\r\n return Err.create(value);\r\n}\r\n"],"mappings":"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"}
@@ -0,0 +1,510 @@
1
+ import { EitherUnwrapError, InvalidErrorCode, InvalidParamDelimitersError } from "./errors/index.cjs";
2
+ import { a as Trim, c as CatalogCode, d as DEFAULT_PARAM_DELIMITERS, f as DefaultParamDelimiters, i as ExtractPlaceholders, l as ErrorCatalog, m as ErrorParamDelimiters, n as ErrorParamValue, o as Whitespace, p as createParamPlaceholder, r as ParamsFromMessage, s as CatalogDescriptor, t as ErrorParams, u as ErrorDescriptor } from "./error-params-CR2parjT.cjs";
3
+ import { a as CIRCULAR_MARKER, c as BASE_ERROR_BRAND, d as BaseErrorOptions, f as BaseErrorOptionsArgs, i as serializeBaseError, l as isBaseError, n as serializeNativeError, o as SeenReferences, p as escapeRegExp, r as SerializedBaseError, s as serializeCauseError, t as SerializedNativeError, u as BaseError } from "./index-BzFCOXvr.cjs";
4
+ import { AlphaNumeric, Digit, InvalidCodeMessage, IsUpperSnakeCase, Segment, Tail, UpperLetter, ValidateErrorDefinitions } from "./types/index.cjs";
5
+ //#region src/define-error-catalog.d.ts
6
+ /**
7
+ * Cria um catálogo de erros imutável a partir de um objeto que associa cada
8
+ * código de erro à sua mensagem.
9
+ *
10
+ * Para cada entrada de `definitions` gera um {@link ErrorDescriptor} com
11
+ * `code` e `message` congelado com `Object.freeze`. O próprio catálogo
12
+ * retornado também é congelado, de modo que nem o catálogo nem seus
13
+ * descritores podem ser alterados depois de criados.
14
+ *
15
+ * A validação ocorre em duas camadas:
16
+ * - em tempo de compilação via {@link ValidateErrorDefinitions}: códigos fora
17
+ * de UPPER_SNAKE_CASE geram um erro de tipo com uma mensagem explicativa;
18
+ * - em tempo de execução via {@link isUpperSnakeCase}: códigos inválidos
19
+ * lançam {@link InvalidErrorCode}, o que protege contra definições que
20
+ * escapem da checagem de tipos (ex.: objetos tipados como `any` ou
21
+ * `Record<string, string>`).
22
+ *
23
+ * O parâmetro de tipo `T` é declarado como `const`, o que preserva os tipos
24
+ * literais dos códigos e das mensagens sem a necessidade de `as const` na
25
+ * chamada.
26
+ *
27
+ * @template Codes - Objeto que mapeia códigos de erro para suas mensagens.
28
+ * @param definitions - Definições do catálogo: chaves são os códigos em
29
+ * UPPER_SNAKE_CASE.
30
+ * @returns Catálogo de erros somente leitura com um descritor para cada
31
+ * código informado.
32
+ * @throws {InvalidErrorCode} Se algum código não estiver em UPPER_SNAKE_CASE.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const TEST_ERROR_CODES = defineErrorCatalog({
37
+ * USER_NOT_FOUND: "Usuário {id} não encontrado",
38
+ * INVALID_TOKEN: "Token inválido",
39
+ * });
40
+ *
41
+ * TEST_ERROR_CODES.USER_NOT_FOUND.code; // "USER_NOT_FOUND"
42
+ * TEST_ERROR_CODES.USER_NOT_FOUND.message; // "Usuário {id} não encontrado"
43
+ *
44
+ * // Erro de compilação (e de execução): código fora de UPPER_SNAKE_CASE
45
+ * defineErrorCatalog({
46
+ * userNotFound: "Usuário não encontrado",
47
+ * });
48
+ * // Lança InvalidErrorCode
49
+ * ```
50
+ */
51
+ export declare function defineErrorCatalog<const Codes extends Record<string, string>>(definitions: ValidateErrorDefinitions<Codes>): ErrorCatalog<Codes>;
52
+ //#endregion
53
+ //#region src/either.d.ts
54
+ /**
55
+ * Representa o resultado de uma operação que pode ter sucesso (`Ok`) ou
56
+ * falhar (`Err`), tornando o erro parte explícita do tipo de retorno em vez
57
+ * de depender de exceções.
58
+ *
59
+ * Um `Either<O, E>` é sempre uma instância de {@link Ok} que carrega um
60
+ * valor de sucesso do tipo `O`, ou de {@link Err} que carrega um valor de
61
+ * erro do tipo `E`. Use {@link ok} e {@link err} para criá-los.
62
+ *
63
+ * Os métodos {@link Either.map}, {@link Either.mapErr}, {@link Either.flatMap}
64
+ * e {@link Either.orElse} retornam um novo `Either` e não alteram o original.
65
+ * Para tratar os dois casos use {@link Either.match}, ou os type guards
66
+ * {@link Either.isOk} e {@link Either.isErr}.
67
+ *
68
+ * @template O - Tipo do valor de sucesso.
69
+ * @template E - Tipo do valor de erro.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * function toDivide(a: number, b: number): Either<number, string> {
74
+ * return b === 0 ? err("Divisão por zero") : ok(a / b);
75
+ * }
76
+ *
77
+ * const message = toDivide(10, 2)
78
+ * .map((resultado) => resultado * 3)
79
+ * .match({
80
+ * onOk: (valor) => `Resultado: ${valor}`,
81
+ * onErr: (erro) => `Falha: ${erro}`,
82
+ * });
83
+ * // "Resultado: 15"
84
+ * ```
85
+ */
86
+ export declare abstract class Either<O, E> {
87
+ /** Discriminante da variante: `"Ok"` para sucesso e `"Err"` para erro. */
88
+ abstract readonly tag: "Ok" | "Err";
89
+ /**
90
+ * Retorna o valor de sucesso.
91
+ *
92
+ * @returns O valor contido em `Ok`.
93
+ * @throws {EitherUnwrapError} Se for um `Err`. A `cause` do erro é o valor
94
+ * de erro contido.
95
+ */
96
+ abstract unwrap(): O;
97
+ /**
98
+ * Retorna o valor de erro.
99
+ *
100
+ * @returns O valor contido em `Err`.
101
+ * @throws {EitherUnwrapError} Se for um `Ok`. A `cause` do erro é o valor
102
+ * de sucesso contido.
103
+ */
104
+ abstract unwrapErr(): E;
105
+ /**
106
+ * Verifica se é um `Ok` funcionando como type guard.
107
+ *
108
+ * @returns `true` se for `Ok` (restringindo o tipo para {@link Ok});
109
+ * caso contrário, `false`.
110
+ */
111
+ abstract isOk(): this is Ok<O, E>;
112
+ /**
113
+ * Verifica se é um `Err` funcionando como type guard.
114
+ *
115
+ * @returns `true` se for `Err` (restringindo o tipo para {@link Err});
116
+ * caso contrário, `false`.
117
+ */
118
+ abstract isErr(): this is Err<O, E>;
119
+ /**
120
+ * Transforma o valor de sucesso mantendo o erro intacto.
121
+ *
122
+ * Se for `Ok` aplica `fn` ao valor e retorna um novo `Ok` com o resultado.
123
+ * Se for `Err` `fn` não é chamada e um novo `Err` com o mesmo erro é
124
+ * retornado. Exceções lançadas por `fn` não são capturadas.
125
+ *
126
+ * @template O2 - Tipo do novo valor de sucesso.
127
+ * @param fn - Função que converte o valor de sucesso.
128
+ * @returns Um `Either` com o valor transformado ou o erro original.
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * ok<number, string>(2).map((n) => n * 2).unwrap(); // 4
133
+ * err<number, string>("falhou").map((n) => n * 2).unwrapErr(); // "falhou"
134
+ * ```
135
+ */
136
+ map<O2>(fn: (value: O) => O2): Either<O2, E>;
137
+ /**
138
+ * Transforma o valor de erro mantendo o sucesso intacto.
139
+ *
140
+ * Se for `Err` aplica `fn` ao erro e retorna um novo `Err` com o resultado.
141
+ * Se for `Ok` `fn` não é chamada e um novo `Ok` com o mesmo valor é
142
+ * retornado. Exceções lançadas por `fn` não são capturadas.
143
+ *
144
+ * @template E2 - Tipo do novo valor de erro.
145
+ * @param fn - Função que converte o valor de erro.
146
+ * @returns Um `Either` com o erro transformado ou o valor original.
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * err<number, string>("falhou").mapErr((e) => e.length).unwrapErr(); // 7
151
+ * ok<number, string>(1).mapErr((e) => e.length).unwrap(); // 1
152
+ * ```
153
+ */
154
+ mapErr<E2>(fn: (value: E) => E2): Either<O, E2>;
155
+ /**
156
+ * Encadeia uma operação que também retorna um `Either` usada quando o
157
+ * próximo passo também pode falhar.
158
+ *
159
+ * Se for `Ok`, retorna diretamente o `Either` produzido por `fn` (sem
160
+ * aninhamento). Se for `Err` `fn` não é chamada e o erro é propagado.
161
+ * O tipo de erro resultante é a união `E | E2`. Exceções lançadas por `fn`
162
+ * não são capturadas.
163
+ *
164
+ * @template O2 - Tipo do valor de sucesso retornado por `fn`.
165
+ * @template E2 - Tipo do valor de erro retornado por `fn`.
166
+ * @param fn - Função que recebe o valor de sucesso e retorna um `Either`.
167
+ * @returns O `Either` retornado por `fn`, ou o erro original.
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * const forNumber = (s: string): Either<number, string> => {
172
+ * const n = Number(s);
173
+ * return Number.isNaN(n) ? err("Não é número") : ok(n);
174
+ * };
175
+ *
176
+ * ok<string, string>("42").flatMap(forNumber).unwrap(); // 42
177
+ * ok<string, string>("abc").flatMap(forNumber).unwrapErr(); // "Não é número"
178
+ * ```
179
+ */
180
+ flatMap<O2, E2>(fn: (value: O) => Either<O2, E2>): Either<O2, E | E2>;
181
+ /**
182
+ * Tenta se recuperar de um erro encadeando uma operação alternativa que
183
+ * também retorna um `Either`. É o oposto de {@link Either.flatMap}.
184
+ *
185
+ * Se for `Err` retorna diretamente o `Either` produzido por `fn`. Se for
186
+ * `Ok` `fn` não é chamada e o valor é mantido. O tipo de sucesso
187
+ * resultante é a união `O | O2`. Exceções lançadas por `fn` não são
188
+ * capturadas.
189
+ *
190
+ * @template O2 - Tipo do valor de sucesso retornado por `fn`.
191
+ * @template E2 - Tipo do valor de erro retornado por `fn`.
192
+ * @param fn - Função que recebe o valor de erro e retorna um `Either`.
193
+ * @returns O `Either` retornado por `fn`, ou o valor de sucesso original.
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * err<number, string>("falhou").orElse(() => ok(0)).unwrap(); // 0
198
+ * ok<number, string>(5).orElse(() => ok(0)).unwrap(); // 5
199
+ * ```
200
+ */
201
+ orElse<O2, E2>(fn: (value: E) => Either<O2, E2>): Either<O | O2, E2>;
202
+ /**
203
+ * Trata os dois casos e produz um único valor chamando o handler da
204
+ * variante correspondente.
205
+ *
206
+ * @template R - Tipo do valor retornado pelos handlers.
207
+ * @param handlers - Objeto com `onOk` chamado com o valor de sucesso e
208
+ * `onErr` chamado com o valor de erro.
209
+ * @returns O resultado do handler chamado.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * const texto = resultado.match({
214
+ * onOk: (valor) => `Sucesso: ${valor}`,
215
+ * onErr: (erro) => `Erro: ${erro}`,
216
+ * });
217
+ * ```
218
+ */
219
+ match<R>(handlers: Readonly<{
220
+ onOk(value: O): R;
221
+ onErr(value: E): R;
222
+ }>): R;
223
+ }
224
+ /**
225
+ * Variante de sucesso de {@link Either} que carrega um valor do tipo `O`.
226
+ *
227
+ * O construtor é `protected`; para criar uma instância use {@link Ok.create}
228
+ * ou a função {@link ok}.
229
+ *
230
+ * @template O - Tipo do valor de sucesso. Por padrão, `never`.
231
+ * @template E - Tipo do valor de erro usado apenas para compatibilidade com
232
+ * {@link Either}. Por padrão, `never`.
233
+ */
234
+ export declare class Ok<O = never, E = never> extends Either<O, E> {
235
+ /** Discriminante da variante sempre `"Ok"`. */
236
+ readonly tag: "Ok";
237
+ /** Valor de sucesso armazenado. */
238
+ private readonly value;
239
+ /**
240
+ * @param value - Valor de sucesso a ser armazenado.
241
+ */
242
+ protected constructor(value: O);
243
+ /**
244
+ * Retorna o valor de sucesso armazenado.
245
+ *
246
+ * @returns O valor contido.
247
+ */
248
+ unwrap(): O;
249
+ /**
250
+ * Sempre lança um erro pois um `Ok` não possui valor de erro.
251
+ *
252
+ * @throws {EitherUnwrapError} Sempre. A `cause` é o valor de sucesso contido.
253
+ */
254
+ unwrapErr(): E;
255
+ /** @returns Sempre `true`. */
256
+ isOk(): this is Ok<O, E>;
257
+ /** @returns Sempre `false`. */
258
+ isErr(): this is Err<O, E>;
259
+ /**
260
+ * Cria um `Ok` com o valor informado.
261
+ *
262
+ * @template O - Tipo do valor de sucesso. Por padrão, `never`.
263
+ * @template E - Tipo do valor de erro. Por padrão, `never`.
264
+ * @param value - Valor de sucesso.
265
+ * @returns Uma nova instância de `Ok`.
266
+ */
267
+ static create<O = never, E = never>(value: O): Ok<O, E>;
268
+ }
269
+ /**
270
+ * Variante de erro de {@link Either} que carrega um valor do tipo `E`.
271
+ *
272
+ * O construtor é `protected`; para criar uma instância use {@link Err.create}
273
+ * ou a função {@link err}.
274
+ *
275
+ * @template O - Tipo do valor de sucesso usado apenas para compatibilidade
276
+ * com {@link Either}. Por padrão, `never`.
277
+ * @template E - Tipo do valor de erro. Por padrão, `never`.
278
+ */
279
+ export declare class Err<O = never, E = never> extends Either<O, E> {
280
+ /** Discriminante da variante sempre `"Err"`. */
281
+ readonly tag: "Err";
282
+ /** Valor de erro armazenado. */
283
+ private readonly value;
284
+ /**
285
+ * @param value - Valor de erro a ser armazenado.
286
+ */
287
+ protected constructor(value: E);
288
+ /**
289
+ * Sempre lança um erro pois um `Err` não possui valor de sucesso.
290
+ *
291
+ * @throws {EitherUnwrapError} Sempre. A `cause` é o valor de erro contido.
292
+ */
293
+ unwrap(): O;
294
+ /**
295
+ * Retorna o valor de erro armazenado.
296
+ *
297
+ * @returns O valor contido.
298
+ */
299
+ unwrapErr(): E;
300
+ /** @returns Sempre `false`. */
301
+ isOk(): this is Ok<O, E>;
302
+ /** @returns Sempre `true`. */
303
+ isErr(): this is Err<O, E>;
304
+ /**
305
+ * Cria um `Err` com o valor informado.
306
+ *
307
+ * @template O - Tipo do valor de sucesso. Por padrão, `never`.
308
+ * @template E - Tipo do valor de erro. Por padrão, `never`.
309
+ * @param value - Valor de erro.
310
+ * @returns Uma nova instância de `Err`.
311
+ */
312
+ static create<O = never, E = never>(value: E): Err<O, E>;
313
+ }
314
+ /**
315
+ * Cria um {@link Either} de sucesso (`Ok`) com o valor informado.
316
+ *
317
+ * O retorno é tipado como `Either<O, E>` e não como `Ok` para que possa ser
318
+ * usado onde se espera qualquer variante. Como `E` não pode ser inferido a
319
+ * partir do argumento, informe-o explicitamente quando necessário.
320
+ *
321
+ * @template O - Tipo do valor de sucesso. Por padrão, `never`.
322
+ * @template E - Tipo do valor de erro. Por padrão, `never`.
323
+ * @param value - Valor de sucesso.
324
+ * @returns Um `Either` que é um `Ok` contendo `value`.
325
+ *
326
+ * @example
327
+ * ```ts
328
+ * const result = ok<number, string>(42);
329
+ * result.isOk(); // true
330
+ * result.unwrap(); // 42
331
+ * ```
332
+ */
333
+ export declare function ok<O = never, E = never>(value: O): Either<O, E>;
334
+ /**
335
+ * Cria um {@link Either} de erro (`Err`) com o valor informado.
336
+ *
337
+ * O retorno é tipado como `Either<O, E>` e não como `Err` para que possa ser
338
+ * usado onde se espera qualquer variante. Como `O` não pode ser inferido a
339
+ * partir do argumento, informe-o explicitamente quando necessário.
340
+ *
341
+ * @template O - Tipo do valor de sucesso. Por padrão, `never`.
342
+ * @template E - Tipo do valor de erro. Por padrão, `never`.
343
+ * @param value - Valor de erro.
344
+ * @returns Um `Either` que é um `Err` contendo `value`.
345
+ *
346
+ * @example
347
+ * ```ts
348
+ * const result = err<number, string>("Algo deu errado");
349
+ * result.isErr(); // true
350
+ * result.unwrapErr(); // "Algo deu errado"
351
+ * ```
352
+ */
353
+ export declare function err<O = never, E = never>(value: E): Either<O, E>;
354
+ //#endregion
355
+ //#region src/interpolate-error-message.d.ts
356
+ /**
357
+ * Deriva, em tempo de compilação a lista de argumentos extras exigida para
358
+ * interpolar uma mensagem de erro.
359
+ *
360
+ * - Se a mensagem **não** tiver placeholders o resultado é uma tupla vazia
361
+ * (`[]`), ou seja, nenhum argumento adicional deve ser passado.
362
+ * - Se tiver placeholders o resultado é uma tupla com um único argumento
363
+ * obrigatório, `params` do tipo {@link ParamsFromMessage}.
364
+ *
365
+ * É pensado para ser usado como tipo de parâmetro rest (`...args`) de modo
366
+ * que o objeto de parâmetros seja exigido apenas quando necessário.
367
+ *
368
+ * @template Message - Mensagem a ser analisada.
369
+ * @template Delimiters - Objeto com os delimitadores `open` e `close` do
370
+ * placeholder. Por padrão, {@link DefaultParamDelimiters}.
371
+ *
372
+ * @example
373
+ * ```ts
374
+ * type A = ErrorMessageArgs<"Usuário {id} não encontrado">;
375
+ * // [params: Readonly<{ id: ErrorParamValue }>]
376
+ *
377
+ * type B = ErrorMessageArgs<"Token inválido">;
378
+ * // []
379
+ *
380
+ * type C = ErrorMessageArgs<
381
+ * "Rota [route] não encontrada",
382
+ * { readonly open: "["; readonly close: "]" }
383
+ * >;
384
+ * // [params: Readonly<{ route: ErrorParamValue }>]
385
+ * ```
386
+ */
387
+ export type ErrorMessageArgs<Message extends string, Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters> = [ParamsFromMessage<Message, Delimiters>] extends [never] ? [] : [params: ParamsFromMessage<Message, Delimiters>];
388
+ /**
389
+ * Interpola os parâmetros informados na mensagem de um descritor de erro
390
+ * substituindo cada placeholder pelo valor correspondente.
391
+ *
392
+ * Os placeholders são localizados com {@link createParamPlaceholder} a partir
393
+ * dos delimitadores informados. O nome de cada placeholder é aparado
394
+ * (`{ id }` equivale a `{id}`) e o valor é convertido para texto com `String`.
395
+ *
396
+ * O placeholder é mantido exatamente como está na mensagem (sem substituição)
397
+ * quando:
398
+ * - o nome é vazio (ex.: `{}` ou `{ }`);
399
+ * - o nome não existe como propriedade própria de `params`.
400
+ *
401
+ * O objeto de parâmetros é exigido ou omitido conforme a mensagem via
402
+ * {@link ErrorMessageArgs}: mensagens sem placeholders não aceitam `params` e
403
+ * mensagens com placeholders exigem todos eles.
404
+ *
405
+ * @template Descriptor - Tipo do descritor de erro cuja `message` define os
406
+ * parâmetros exigidos.
407
+ * @template Delimiters - Tipo dos delimitadores dos placeholders. Por padrão,
408
+ * {@link DefaultParamDelimiters}.
409
+ * @param descriptor - Descritor de erro cuja mensagem será interpolada.
410
+ * @param delimiters - Delimitadores `open` e `close` dos placeholders.
411
+ * @param args - Objeto `params` com os valores dos placeholders exigido
412
+ * apenas se a mensagem tiver placeholders.
413
+ * @returns A mensagem com os placeholders substituídos.
414
+ * @throws {InvalidParamDelimitersError} Se `open` ou `close` for uma string
415
+ * vazia (lançado por {@link createParamPlaceholder}).
416
+ *
417
+ * @example
418
+ * ```ts
419
+ * const keys = { open: "{", close: "}" } as const;
420
+ *
421
+ * const USER_NOT_FOUND = {
422
+ * code: "USER_NOT_FOUND",
423
+ * message: "Usuário {id} não encontrado em {table}",
424
+ * } as const satisfies ErrorDescriptor;
425
+ *
426
+ * interpolateErrorMessage(USER_NOT_FOUND, keys, {
427
+ * id: 42,
428
+ * table: "users",
429
+ * });
430
+ * // "Usuário 42 não encontrado em users"
431
+ *
432
+ * const INVALID_TOKEN = {
433
+ * code: "INVALID_TOKEN",
434
+ * message: "Token inválido",
435
+ * } as const satisfies ErrorDescriptor;
436
+ *
437
+ * interpolateErrorMessage(INVALID_TOKEN, keys);
438
+ * // "Token inválido" (sem params)
439
+ *
440
+ * // Delimitadores personalizados
441
+ * const ROUTE_NOT_FOUND = {
442
+ * code: "ROUTE_NOT_FOUND",
443
+ * message: "Rota [route] não encontrada",
444
+ * } as const satisfies ErrorDescriptor;
445
+ *
446
+ * interpolateErrorMessage(
447
+ * ROUTE_NOT_FOUND,
448
+ * { open: "[", close: "]" } as const,
449
+ * { route: "/home" },
450
+ * );
451
+ * // "Rota /home não encontrada"
452
+ * ```
453
+ */
454
+ export declare function interpolateErrorMessage<Descriptor extends ErrorDescriptor, Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters>(descriptor: Descriptor, delimiters: Delimiters, ...args: ErrorMessageArgs<Descriptor["message"], Delimiters>): string;
455
+ //#endregion
456
+ //#region src/upper-snake-case.d.ts
457
+ /**
458
+ * Expressão regular que valida códigos em UPPER_SNAKE_CASE em tempo de
459
+ * execução.
460
+ *
461
+ * Regras (espelham o tipo {@link IsUpperSnakeCase}):
462
+ * - deve começar com uma letra maiúscula (`A-Z`);
463
+ * - pode conter letras maiúsculas, dígitos e `_`;
464
+ * - `_` só pode aparecer entre caracteres alfanuméricos, ou seja, não pode
465
+ * estar no início nem no fim e não pode ser repetido em sequência.
466
+ */
467
+ export declare const UPPER_SNAKE_CASE: RegExp;
468
+ /**
469
+ * Verifica em tempo de execução, se uma string está em UPPER_SNAKE_CASE.
470
+ *
471
+ * É o equivalente em runtime do tipo {@link IsUpperSnakeCase}, usando a
472
+ * expressão regular {@link UPPER_SNAKE_CASE}.
473
+ *
474
+ * @param value - String a ser verificada.
475
+ * @returns `true` se `value` estiver em UPPER_SNAKE_CASE; caso contrário,
476
+ * `false`.
477
+ *
478
+ * @example
479
+ * ```ts
480
+ * isUpperSnakeCase("USER_NOT_FOUND"); // true
481
+ * isUpperSnakeCase("ERROR_404"); // true
482
+ * isUpperSnakeCase("userNotFound"); // false
483
+ * isUpperSnakeCase("_USER"); // false
484
+ * isUpperSnakeCase("USER__NOT"); // false
485
+ * isUpperSnakeCase("1ERROR"); // false
486
+ * ```
487
+ */
488
+ export declare function isUpperSnakeCase(value: string): boolean;
489
+ /**
490
+ * Monta a mensagem de erro exibida quando um código não está em
491
+ * UPPER_SNAKE_CASE.
492
+ *
493
+ * O retorno é tipado como {@link InvalidCodeMessage}, de modo que o texto em
494
+ * runtime corresponde exatamente ao tipo literal usado na validação em tempo
495
+ * de compilação.
496
+ *
497
+ * @template Code - Tipo literal do código inválido.
498
+ * @param code - Código de erro inválido a ser incluído na mensagem.
499
+ * @returns Mensagem descrevendo o código inválido e o formato esperado.
500
+ *
501
+ * @example
502
+ * ```ts
503
+ * invalidCodeMessage("userNotFound");
504
+ * // 'Código de erro inválido "userNotFound". Os códigos de erro devem usar UPPER_SNAKE_CASE.'
505
+ * ```
506
+ */
507
+ export declare function invalidCodeMessage<Code extends string>(code: Code): InvalidCodeMessage<Code>;
508
+ //#endregion
509
+ export { AlphaNumeric, BASE_ERROR_BRAND, BaseError, BaseErrorOptions, BaseErrorOptionsArgs, CIRCULAR_MARKER, CatalogCode, CatalogDescriptor, DEFAULT_PARAM_DELIMITERS, DefaultParamDelimiters, Digit, EitherUnwrapError, ErrorCatalog, ErrorDescriptor, ErrorParamDelimiters, ErrorParamValue, ErrorParams, ExtractPlaceholders, InvalidCodeMessage, InvalidErrorCode, InvalidParamDelimitersError, IsUpperSnakeCase, ParamsFromMessage, SeenReferences, Segment, SerializedBaseError, SerializedNativeError, Tail, Trim, UpperLetter, ValidateErrorDefinitions, Whitespace, createParamPlaceholder, escapeRegExp, isBaseError, serializeBaseError, serializeCauseError, serializeNativeError };
510
+ //# sourceMappingURL=index.d.cts.map