@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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pedro Henrique Bergamo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,52 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # @pedrohb/errors
2
+
3
+ Um sistema de erros tipado para aplicações TypeScript. Defina catálogos imutáveis de códigos, associe mensagens parametrizadas a erros e serialize causas com segurança.
4
+
5
+ ## Instalação
6
+
7
+ ```sh
8
+ pnpm add @pedrohb/errors
9
+ ```
10
+
11
+ ## Catálogo e erros tipados
12
+
13
+ ```ts
14
+ import { BaseError, defineErrorCatalog } from "@pedrohb/errors";
15
+
16
+ const errors = defineErrorCatalog({
17
+ USER_NOT_FOUND: "Usuário {userId} não encontrado.",
18
+ INVALID_CREDENTIALS: "Credenciais inválidas.",
19
+ });
20
+
21
+ class UserNotFoundError extends BaseError<typeof errors, "USER_NOT_FOUND"> {
22
+ public constructor(userId: string, options?: ErrorOptions) {
23
+ super(errors.USER_NOT_FOUND, {
24
+ ...options,
25
+ params: { userId },
26
+ });
27
+ }
28
+ }
29
+
30
+ const error = new UserNotFoundError("user-123");
31
+ console.log(error.code, error.message);
32
+ ```
33
+
34
+ Os códigos devem estar em `UPPER_SNAKE_CASE`. Os placeholders entre chaves são inferidos pelo TypeScript e usados para tipar os parâmetros da mensagem.
35
+
36
+ ## Serialização
37
+
38
+ `BaseError` preserva `code`, `message` e parâmetros. `serialize()` retorna uma representação apropriada para logs e transporte; a pilha é omitida por padrão e pode ser incluída chamando `serialize(true)`. Causas nativas, erros da biblioteca, datas, valores não serializáveis por JSON e referências circulares são tratadas pela serialização.
39
+
40
+ ## Resultado `Either`
41
+
42
+ O pacote também exporta `Either`, `Ok`, `Err`, `ok` e `err` para representar resultados de sucesso ou falha sem lançar exceções. Os métodos `map`, `mapErr`, `flatMap`, `orElse` e `match` permitem compor e consumir esses resultados.
43
+
44
+ ## Imports por subpath
45
+
46
+ ```ts
47
+ import { InvalidErrorCode } from "@pedrohb/errors/errors";
48
+ import { serializeBaseError } from "@pedrohb/errors/functions";
49
+ import type { ErrorCatalog } from "@pedrohb/errors/types";
50
+ ```
51
+
52
+ O pacote fornece formatos ESM e CommonJS, com declarações TypeScript correspondentes.
@@ -0,0 +1,387 @@
1
+ //#region src/types/error-param-delimiters.d.ts
2
+ /**
3
+ * Delimitadores de abertura e fechamento usados para identificar os
4
+ * placeholders em uma mensagem de erro (ex.: `{id}`). Também pode
5
+ * ser usado para tipar, em runtime, o objeto de delimitadores.
6
+ *
7
+ * Os parâmetros de tipo têm `string` como padrão, de modo que
8
+ * `ErrorParamDelimiters` sem argumentos serve como restrição genérica
9
+ * (`extends ErrorParamDelimiters`) aceitando quaisquer delimitadores. Para o
10
+ * par padrão `{` e `}`, informe os literais explicitamente.
11
+ *
12
+ * @template Open - Tipo literal do delimitador de abertura. Por padrão, `string`.
13
+ * @template Close - Tipo literal do delimitador de fechamento. Por padrão, `string`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const keys = { open: "{", close: "}" } as const satisfies ErrorParamDelimiters;
18
+ *
19
+ * const brackets: ErrorParamDelimiters<"[", "]"> = {
20
+ * open: "[",
21
+ * close: "]",
22
+ * };
23
+ * // Mensagem correspondente: "Usuário [id] não encontrado"
24
+ * ```
25
+ */
26
+ type ErrorParamDelimiters<Open extends string = string, Close extends string = string> = Readonly<{
27
+ /** Delimitador que marca o início de um placeholder (ex.: `"{"`). */
28
+ open: Open;
29
+ /** Delimitador que marca o fim de um placeholder (ex.: `"}"`). */
30
+ close: Close;
31
+ }>;
32
+ //#endregion
33
+ //#region src/functions/create-param-placeholder.d.ts
34
+ /**
35
+ * Delimitadores padrão dos placeholders em mensagens de erro: `{` para abrir
36
+ * e `}` para fechar (ex.: `{id}`).
37
+ *
38
+ * Declarado com `as const`, então mantém os tipos literais `"{"` e `"}"`,
39
+ * o que permite derivar {@link DefaultParamDelimiters} a partir dele.
40
+ */
41
+ declare const DEFAULT_PARAM_DELIMITERS: {
42
+ readonly open: "{";
43
+ readonly close: "}";
44
+ };
45
+ /**
46
+ * Tipo dos delimitadores padrão equivalente a
47
+ * `{ readonly open: "{"; readonly close: "}" }`.
48
+ *
49
+ * É usado como valor padrão de `Delimiters` em tipos como `ErrorParams`.
50
+ */
51
+ type DefaultParamDelimiters = typeof DEFAULT_PARAM_DELIMITERS;
52
+ /**
53
+ * Cria uma expressão regular global que localiza os placeholders de uma
54
+ * mensagem de erro com base nos delimitadores informados.
55
+ *
56
+ * Os delimitadores são escapados com {@link escapeRegExp}, então símbolos como
57
+ * `[`, `(` ou `$` são tratados como texto literal. Delimitadores com mais de
58
+ * um caractere (ex.: `{{` e `}}`) também são aceitos.
59
+ *
60
+ * Em cada correspondência o grupo de captura `1` contém o texto entre os
61
+ * delimitadores, exatamente como aparece na mensagem (sem aparar espaços).
62
+ * O conteúdo pode ocupar várias linhas, mas não pode conter os delimitadores
63
+ * de abertura ou de fechamento. Em casos como `{{id}}` a correspondência
64
+ * recai sobre o par mais interno (`{id}`). Placeholders vazios (ex.: `{}`)
65
+ * também correspondem com o grupo `1` igual a `""`.
66
+ *
67
+ * Cada chamada devolve uma nova instância de `RegExp`. Como ela usa a flag
68
+ * `g` que mantém estado em `lastIndex`, isso evita que usos diferentes
69
+ * compartilhem o mesmo estado.
70
+ *
71
+ * @param delimiters - Delimitadores `open` e `close` do placeholder. Por
72
+ * padrão, {@link DEFAULT_PARAM_DELIMITERS} (`{` e `}`).
73
+ * @returns Expressão regular global que corresponde a cada placeholder.
74
+ * @throws {InvalidParamDelimitersError} Se `open` ou `close` for uma string
75
+ * vazia.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * const regex = createParamPlaceholder();
80
+ *
81
+ * for (const match of "Usuário {id} não encontrado em {table}".matchAll(regex)) {
82
+ * console.log(match[1]);
83
+ * }
84
+ * // "id"
85
+ * // "table"
86
+ *
87
+ * "Olá, {nome}!".replace(regex, (_, param) => `<${param}>`);
88
+ * // "Olá, <nome>!"
89
+ *
90
+ * // Delimitadores personalizados
91
+ * const brackets = createParamPlaceholder({ open: "[", close: "]" });
92
+ * "Rota [route] não encontrada".match(brackets); // ["[route]"]
93
+ *
94
+ * // Delimitadores vazios não são permitidos
95
+ * createParamPlaceholder({ open: "", close: "}" });
96
+ * // Lança InvalidParamDelimitersError
97
+ * ```
98
+ */
99
+ declare function createParamPlaceholder(delimiters?: ErrorParamDelimiters): RegExp;
100
+ //#endregion
101
+ //#region src/types/error-descriptor.d.ts
102
+ /**
103
+ * Descreve um erro do catálogo: um código identificador e a mensagem associada.
104
+ *
105
+ * A mensagem pode conter placeholders (ex.: `"Usuário {id} não encontrado"`),
106
+ * que são preenchidos com os parâmetros informados na criação do erro.
107
+ *
108
+ * @template Code - Tipo literal do código do erro. Por padrão, `string`.
109
+ * @template Message - Tipo literal da mensagem do erro. Por padrão, `string`.
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * const USER_NOT_FOUND = {
114
+ * code: "USER_NOT_FOUND",
115
+ * message: "Usuário {id} não encontrado",
116
+ * } as const satisfies ErrorDescriptor;
117
+ * ```
118
+ */
119
+ interface ErrorDescriptor<Code extends string = string, Message extends string = string> {
120
+ /** Código único que identifica o erro (ex.: `"USER_NOT_FOUND"`). */
121
+ readonly code: Code;
122
+ /** Mensagem do erro, podendo conter placeholders como `{id}`. */
123
+ readonly message: Message;
124
+ }
125
+ //#endregion
126
+ //#region src/types/error-catalog.d.ts
127
+ /**
128
+ * Catálogo de erros somente leitura, derivado de um objeto que associa cada
129
+ * código de erro à sua mensagem.
130
+ *
131
+ * Para cada entrada de `Definitions`, a chave vira o `code` e o valor vira a
132
+ * `message` de um {@link ErrorDescriptor}, preservando os tipos literais de
133
+ * ambos. Assim, `TEST_ERROR_CODES.USER_NOT_FOUND.code` tem o tipo `"USER_NOT_FOUND"`
134
+ * e `TEST_ERROR_CODES.USER_NOT_FOUND.message` tem o tipo literal da mensagem definida.
135
+ *
136
+ * Apenas chaves do tipo `string` são consideradas.
137
+ *
138
+ * @template Definitions - Objeto que mapeia códigos de erro para suas
139
+ * mensagens. Por padrão, `Record<string, string>`.
140
+ *
141
+ * @example
142
+ * ```ts
143
+ * type TEST_ERROR_CODES = ErrorCatalog<{
144
+ * USER_NOT_FOUND: "Usuário {id} não encontrado";
145
+ * INVALID_TOKEN: "Token inválido";
146
+ * }>;
147
+ * // {
148
+ * // readonly USER_NOT_FOUND: ErrorDescriptor<"USER_NOT_FOUND", "Usuário {id} não encontrado">;
149
+ * // readonly INVALID_TOKEN: ErrorDescriptor<"INVALID_TOKEN", "Token inválido">;
150
+ * // }
151
+ * ```
152
+ */
153
+ type ErrorCatalog<Definitions extends Record<string, string> = Record<string, string>> = Readonly<{ [Code in keyof Definitions & string]: ErrorDescriptor<Code, Definitions[Code]>; }>;
154
+ //#endregion
155
+ //#region src/types/catalog-code.d.ts
156
+ /**
157
+ * Extrai a união de todos os códigos de erro presentes em um catálogo.
158
+ *
159
+ * Percorre cada {@link ErrorDescriptor} do catálogo e coleta o tipo literal de
160
+ * sua propriedade `code`. Útil para tipar parâmetros que aceitam apenas
161
+ * códigos válidos de um catálogo específico.
162
+ *
163
+ * @template Catalog - Catálogo de erros a ser analisado. Por padrão,
164
+ * `ErrorCatalog`, caso em que o resultado é `string`.
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * type TEST_ERROR_CODES = ErrorCatalog<{
169
+ * USER_NOT_FOUND: "Usuário {id} não encontrado";
170
+ * INVALID_TOKEN: "Token inválido";
171
+ * }>;
172
+ *
173
+ * type TestErrorCatalogCode = CatalogCode<TEST_ERROR_CODES>;
174
+ * // "USER_NOT_FOUND" | "INVALID_TOKEN"
175
+ * ```
176
+ */
177
+ type CatalogCode<Catalog extends ErrorCatalog = ErrorCatalog> = Catalog[keyof Catalog]["code"];
178
+ //#endregion
179
+ //#region src/types/catalog-descriptor.d.ts
180
+ /**
181
+ * Obtém o descritor de erro correspondente a um código específico de um
182
+ * catálogo.
183
+ *
184
+ * Busca em `Catalog` a entrada cujo `code` é `Code` e retorna o respectivo
185
+ * `ErrorDescriptor`, com `code` e `message` em seus tipos literais. Se `Code`
186
+ * for uma união de códigos, o resultado é a união dos descritores
187
+ * correspondentes. Se `Code` não for informado, o resultado é a união de todos
188
+ * os descritores do catálogo.
189
+ *
190
+ * @template Catalog - Catálogo de erros a ser consultado. Por padrão,
191
+ * `ErrorCatalog`.
192
+ * @template Code - Código (ou união de códigos) a ser buscado, restrito aos
193
+ * códigos existentes no catálogo (ver {@link CatalogCode}). Por padrão, todos
194
+ * os códigos do catálogo.
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * type TEST_ERROR_CODES = ErrorCatalog<{
199
+ * USER_NOT_FOUND: "Usuário {id} não encontrado";
200
+ * INVALID_TOKEN: "Token inválido";
201
+ * }>;
202
+ *
203
+ * type A = CatalogDescriptor<TEST_ERROR_CODES, "USER_NOT_FOUND">;
204
+ * // ErrorDescriptor<"USER_NOT_FOUND", "Usuário {id} não encontrado">
205
+ *
206
+ * type B = CatalogDescriptor<TEST_ERROR_CODES, "USER_NOT_FOUND" | "INVALID_TOKEN">;
207
+ * // ErrorDescriptor<"USER_NOT_FOUND", ...> | ErrorDescriptor<"INVALID_TOKEN", ...>
208
+ *
209
+ * type C = CatalogDescriptor<TEST_ERROR_CODES>;
210
+ * // união de todos os descritores do catálogo
211
+ * ```
212
+ */
213
+ type CatalogDescriptor<Catalog extends ErrorCatalog = ErrorCatalog, Code extends CatalogCode<Catalog> = CatalogCode<Catalog>> = Extract<Catalog[Code], {
214
+ code: Code;
215
+ }>;
216
+ //#endregion
217
+ //#region src/types/extract-placeholders.d.ts
218
+ /**
219
+ * Caracteres de espaço em branco reconhecidos pelos tipos utilitários deste módulo.
220
+ *
221
+ * Inclui espaço, tabulação, quebra de linha (`\n`) e retorno de carro (`\r`).
222
+ */
223
+ type Whitespace = " " | "\t" | "\n" | "\r";
224
+ /**
225
+ * Remove, em tempo de compilação, todos os espaços em branco no início e no fim
226
+ * de uma string literal. É o equivalente em nível de tipos a `String.prototype.trim()`.
227
+ *
228
+ * O tipo é recursivo: remove um caractere de espaço por vez do início e
229
+ * quando não há mais nenhum, do fim até restar apenas o conteúdo "limpo".
230
+ *
231
+ * @template T - Tipo string literal a ser aparado. Por padrão, `string`.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * type A = Trim<" olá ">; // "olá"
236
+ * type B = Trim<"\n\tabc\r">; // "abc"
237
+ * type C = Trim<"sem-espaço">; // "sem-espaço"
238
+ * type D = Trim<string>; // string
239
+ * ```
240
+ */
241
+ type Trim<T extends string = string> = T extends `${Whitespace}${infer Rest}` ? Trim<Rest> : T extends `${infer Rest}${Whitespace}` ? Trim<Rest> : T;
242
+ /**
243
+ * Extrai, em tempo de compilação, os nomes dos placeholders presentes em uma
244
+ * string de mensagem, retornando-os como uma união de string literals.
245
+ *
246
+ * Os delimitadores de abertura e fechamento são informados por meio de um
247
+ * objeto {@link ErrorParamDelimiters}. O conteúdo de cada placeholder é
248
+ * aparado com {@link Trim} e placeholders vazios (ex.: `{}` ou `{ }`) são
249
+ * ignorados.
250
+ *
251
+ * Se `Message` for o tipo genérico `string` (ou seja, não for um literal),
252
+ * não é possível inferir os placeholders e o resultado é `string`. Se a
253
+ * mensagem não contiver nenhum placeholder, o resultado é `never`.
254
+ *
255
+ *
256
+ * @template Message - Mensagem a ser analisada. Por padrão, `string`.
257
+ * @template Delimiters - Objeto com os delimitadores `open` e `close` do
258
+ * placeholder. Por padrão, {@link DefaultParamDelimiters}.
259
+ *
260
+ * @example
261
+ * ```ts
262
+ * type Keys = { readonly open: "{"; readonly close: "}" };
263
+ *
264
+ * type A = ExtractPlaceholders<"Olá, {nome}! Você tem {qtd} mensagens.", Keys>;
265
+ * // "nome" | "qtd"
266
+ *
267
+ * type B = ExtractPlaceholders<"Valor: { valor }", Keys>;
268
+ * // "valor" (espaços internos são removidos)
269
+ *
270
+ * type C = ExtractPlaceholders<"Sem placeholders", Keys>;
271
+ * // never
272
+ *
273
+ * type D = ExtractPlaceholders<"Olá, {}!", Keys>;
274
+ * // never (placeholder vazio é ignorado)
275
+ *
276
+ * type E = ExtractPlaceholders<
277
+ * "Olá, [nome]!",
278
+ * { readonly open: "["; readonly close: "]" }
279
+ * >;
280
+ * // "nome" (delimitadores personalizados)
281
+ *
282
+ * type F = ExtractPlaceholders<string, Keys>;
283
+ * // string (mensagem não literal)
284
+ * ```
285
+ */
286
+ type ExtractPlaceholders<Message extends string = string, Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters> = string extends Message ? string : Message extends `${string}${Delimiters["open"]}${infer Param}${Delimiters["close"]}${infer Rest}` ? Trim<Param> extends "" ? ExtractPlaceholders<Rest, Delimiters> : Trim<Param> | ExtractPlaceholders<Rest, Delimiters> : never;
287
+ //#endregion
288
+ //#region src/types/params-from-message.d.ts
289
+ /**
290
+ * Valores aceitos como parâmetros para preencher os placeholders de uma
291
+ * mensagem de erro.
292
+ *
293
+ * Restringe-se a tipos primitivos simples e serializáveis, o que evita
294
+ * objetos arbitrários e referências circulares nos parâmetros do erro.
295
+ */
296
+ type ErrorParamValue = string | number | boolean | bigint | null;
297
+ /**
298
+ * Deriva em tempo de compilação, o tipo do objeto de parâmetros exigido por
299
+ * uma mensagem com base nos placeholders presentes nela.
300
+ *
301
+ * Cada placeholder encontrado (via {@link ExtractPlaceholders}) vira uma
302
+ * propriedade obrigatória e somente leitura do tipo {@link ErrorParamValue}.
303
+ * Os delimitadores dos placeholders são informados por meio de um objeto
304
+ * {@link ErrorParamDelimiters}.
305
+ *
306
+ * - Se a mensagem **não** tiver placeholders o resultado é `never`, indicando
307
+ * que nenhum parâmetro deve ser informado.
308
+ * - Se `Message` for o tipo genérico `string` (não literal), não é possível
309
+ * inferir os placeholders e o resultado é um objeto com chaves `string`
310
+ * arbitrárias, ou seja, `Readonly<Record<string, ErrorParamValue>>`.
311
+ *
312
+ * @template Message - Mensagem a ser analisada. Por padrão, `string`.
313
+ * @template Delimiters - Objeto com os delimitadores `open` e `close` do
314
+ * placeholder. Por padrão, {@link DefaultParamDelimiters}.
315
+ *
316
+ * @example
317
+ * ```ts
318
+ * type Keys = { readonly open: "{"; readonly close: "}" };
319
+ *
320
+ * type A = ParamsFromMessage<"Usuário {id} não encontrado em {table}", Keys>;
321
+ * // Readonly<{ id: ErrorParamValue; table: ErrorParamValue }>
322
+ *
323
+ * type B = ParamsFromMessage<"Algo deu errado", Keys>;
324
+ * // never (sem placeholders, sem parâmetros)
325
+ *
326
+ * type C = ParamsFromMessage<
327
+ * "Falha em [resource]",
328
+ * { readonly open: "["; readonly close: "]" }
329
+ * >;
330
+ * // Readonly<{ resource: ErrorParamValue }>
331
+ *
332
+ * type D = ParamsFromMessage<string, Keys>;
333
+ * // Readonly<Record<string, ErrorParamValue>>
334
+ * ```
335
+ */
336
+ type ParamsFromMessage<Message extends string = string, Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters> = [ExtractPlaceholders<Message, Delimiters>] extends [never] ? never : Readonly<{ [K in ExtractPlaceholders<Message, Delimiters>]: ErrorParamValue; }>;
337
+ //#endregion
338
+ //#region src/types/error-params.d.ts
339
+ /**
340
+ * Deriva em tempo de compilação, o tipo do objeto de parâmetros exigido para
341
+ * criar o erro de um código específico de um catálogo.
342
+ *
343
+ * Localiza o descritor do código em `Catalog` (via {@link CatalogDescriptor}),
344
+ * lê sua `message` e converte os placeholders encontrados em propriedades
345
+ * obrigatórias (via {@link ParamsFromMessage}). Os delimitadores dos
346
+ * placeholders são informados por meio de um objeto
347
+ * {@link ErrorParamDelimiters}.
348
+ *
349
+ * - Se a mensagem do código **não** tiver placeholders, o resultado é `never`,
350
+ * indicando que nenhum parâmetro deve ser informado.
351
+ * - Se `Code` for uma união de códigos, o resultado exige os placeholders de
352
+ * todas as mensagens correspondentes, e não apenas os de uma delas.
353
+ *
354
+ * @template Catalog - Catálogo de erros a ser consultado. Por padrão,
355
+ * `ErrorCatalog`.
356
+ * @template Code - Código (ou união de códigos) do erro, restrito aos códigos
357
+ * existentes no catálogo (ver {@link CatalogCode}). Por padrão, todos os
358
+ * códigos do catálogo.
359
+ * @template Delimiters - Objeto com os delimitadores `open` e `close` do
360
+ * placeholder. Por padrão, {@link DefaultParamDelimiters}.
361
+ *
362
+ * @example
363
+ * ```ts
364
+ * type TEST_ERROR_CODES = ErrorCatalog<{
365
+ * USER_NOT_FOUND: "Usuário {id} não encontrado em {tabela}";
366
+ * INVALID_TOKEN: "Token inválido";
367
+ * ROUTE_NOT_FOUND: "Rota [rota] não encontrada";
368
+ * }>;
369
+ *
370
+ * type A = ErrorParams<TEST_ERROR_CODES, "USER_NOT_FOUND">;
371
+ * // Readonly<{ id: ErrorParamValue; tabela: ErrorParamValue }>
372
+ *
373
+ * type B = ErrorParams<TEST_ERROR_CODES, "INVALID_TOKEN">;
374
+ * // never (sem placeholders, sem parâmetros)
375
+ *
376
+ * type C = ErrorParams<
377
+ * TEST_ERROR_CODES,
378
+ * "ROUTE_NOT_FOUND",
379
+ * { readonly open: "["; readonly close: "]" }
380
+ * >;
381
+ * // Readonly<{ rota: ErrorParamValue }> (delimitadores personalizados)
382
+ * ```
383
+ */
384
+ type ErrorParams<Catalog extends ErrorCatalog = ErrorCatalog, Code extends CatalogCode<Catalog> = CatalogCode<Catalog>, Delimiters extends ErrorParamDelimiters = DefaultParamDelimiters> = ParamsFromMessage<CatalogDescriptor<Catalog, Code>["message"], Delimiters>;
385
+ //#endregion
386
+ export { Trim as a, CatalogCode as c, DEFAULT_PARAM_DELIMITERS as d, DefaultParamDelimiters as f, ExtractPlaceholders as i, ErrorCatalog as l, ErrorParamDelimiters as m, ErrorParamValue as n, Whitespace as o, createParamPlaceholder as p, ParamsFromMessage as r, CatalogDescriptor as s, ErrorParams as t, ErrorDescriptor as u };
387
+ //# sourceMappingURL=error-params-CR2parjT.d.cts.map