@odg/chemical-x 2.1.3 → 2.3.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,223 @@
1
+ ## Chemical-X Helpers - Detailed Guide
2
+
3
+ Funções utilitárias para controle de fluxo assíncrono com tratamento de erros tipado. Não requerem browser driver.
4
+
5
+ ```typescript
6
+ import { retry, sleep, timeout, throwIf, RetryAction } from "@odg/chemical-x";
7
+ ```
8
+
9
+ ---
10
+
11
+ ### `retry(options)`
12
+
13
+ Retenta um callback N vezes com controle fino sobre sleep, abort e decisão por tentativa.
14
+
15
+ **Assinatura:**
16
+
17
+ ```typescript
18
+ // Quando `when` retorna Default | Retry | Throw (ou não fornecido): retorna ReturnType
19
+ async function retry<ReturnType>(options: {
20
+ times: number;
21
+ sleep?: number;
22
+ signal?: AbortSignal;
23
+ callback(attempt: number, signal?: AbortSignal): Promise<ReturnType> | ReturnType;
24
+ when?(exception: Exception, times: number): Promise<RetryAction> | RetryAction;
25
+ }): Promise<ReturnType>;
26
+
27
+ // Quando `when` pode retornar Resolve: retorno inclui undefined
28
+ async function retry<ReturnType>(options: {
29
+ times: number;
30
+ sleep?: number;
31
+ signal?: AbortSignal;
32
+ callback(attempt: number, signal?: AbortSignal): Promise<ReturnType> | ReturnType;
33
+ when?(exception: Exception, times: number): Promise<RetryAction> | RetryAction;
34
+ }): Promise<ReturnType | undefined>;
35
+ ```
36
+
37
+ **Parâmetros:**
38
+
39
+ | Parâmetro | Tipo | Obrigatório | Descrição |
40
+ |---|---|---|---|
41
+ | `times` | `number` | Sim | Número máximo de tentativas. `InvalidArgumentException` se < 1 |
42
+ | `sleep` | `number` | Não | Milissegundos entre tentativas |
43
+ | `signal` | `AbortSignal` | Não | Sinal de abort para cancelar retries |
44
+ | `callback` | `(attempt, signal?) => T` | Sim | Função a ser retentada. Recebe número da tentativa atual |
45
+ | `when` | `(exception, times) => RetryAction` | Não | Decide ação por tentativa: `Retry`, `Throw`, `Resolve`, `Default` |
46
+
47
+ **Comportamento:**
48
+
49
+ 1. Executa `callback(attempt, signal)` até `times` tentativas
50
+ 2. Se callback sucede → retorna resultado
51
+ 3. Se callback falha e `when` está definido → chama `when(exception, remainingTimes)`:
52
+ - `RetryAction.Retry` → retenta imediatamente (ignora `times`)
53
+ - `RetryAction.Throw` → lança exceção imediatamente
54
+ - `RetryAction.Resolve` → resolve com `undefined`
55
+ - `RetryAction.Default` → segue contagem normal de `times`
56
+ 4. Se todas tentativas esgotam → lança `RetryException`
57
+ 5. Entre tentativas, aguarda `sleep` ms (se definido)
58
+
59
+ **Exemplo:**
60
+
61
+ ```typescript
62
+ const data = await retry({
63
+ times: 3,
64
+ sleep: 1000,
65
+ callback: async (attempt) => {
66
+ return await fetchData(attempt);
67
+ },
68
+ when: (exception, times) => {
69
+ if (exception instanceof FatalError) return RetryAction.Throw;
70
+ return RetryAction.Default;
71
+ },
72
+ });
73
+ ```
74
+
75
+ See also: `tests/vitest/helpers/retry.test.ts` para exemplos completos de padrões com retry.
76
+
77
+ ---
78
+
79
+ ### `sleep(milliseconds, options?)`
80
+
81
+ Pausa assíncrona com suporte a cancelamento via `AbortSignal`.
82
+
83
+ **Assinatura:**
84
+
85
+ ```typescript
86
+ async function sleep(milliseconds: number, options?: { signal?: AbortSignal }): Promise<void>
87
+ ```
88
+
89
+ **Parâmetros:**
90
+
91
+ | Parâmetro | Tipo | Obrigatório | Descrição |
92
+ |---|---|---|---|
93
+ | `milliseconds` | `number` | Sim | Duração da pausa em milissegundos |
94
+ | `options.signal` | `AbortSignal` | Não | Sinal para cancelar o sleep antecipadamente |
95
+
96
+ **Exemplo:**
97
+
98
+ ```typescript
99
+ await sleep(2000); // Pausa 2 segundos
100
+
101
+ // Com abort
102
+ const controller = new AbortController();
103
+ await sleep(5000, { signal: controller.signal });
104
+ ```
105
+
106
+ ---
107
+
108
+ ### `timeout(options)`
109
+
110
+ Envolve uma operação assíncrona com limite de tempo. Lança `TimeoutException` se exceder.
111
+
112
+ **Assinatura:**
113
+
114
+ ```typescript
115
+ async function timeout<ReturnType>(options: {
116
+ name?: string;
117
+ timeout?: number;
118
+ callback(): Promise<ReturnType> | ReturnType;
119
+ }): Promise<ReturnType>
120
+ ```
121
+
122
+ **Parâmetros:**
123
+
124
+ | Parâmetro | Tipo | Obrigatório | Descrição |
125
+ |---|---|---|---|
126
+ | `name` | `string` | Não | Nome da operação (incluído na mensagem de `TimeoutException`) |
127
+ | `timeout` | `number` | Não | Limite em milissegundos |
128
+ | `callback` | `() => T` | Sim | Operação a ser executada com limite de tempo |
129
+
130
+ **Comportamento:**
131
+
132
+ - Se callback completa antes do limite → retorna resultado
133
+ - Se excede limite → lança `TimeoutException` com nome da operação (se fornecido)
134
+
135
+ **Exemplo:**
136
+
137
+ ```typescript
138
+ const result = await timeout({
139
+ name: "fetchData",
140
+ timeout: 5000,
141
+ callback: async () => {
142
+ return await longRunningOperation();
143
+ },
144
+ });
145
+ ```
146
+
147
+ See also: `tests/vitest/helpers/timeout.test.ts` para exemplos com timeout.
148
+
149
+ ---
150
+
151
+ ### `throwIf(condition, exception)`
152
+
153
+ Lança exceção condicionalmente com tipagem estrita — `never` quando condition é `true`.
154
+
155
+ **Assinatura:**
156
+
157
+ ```typescript
158
+ function throwIf(condition: true, exception: () => Exception): never;
159
+ function throwIf(condition: false, exception: () => Exception): void;
160
+ function throwIf(condition: boolean, exception: () => Exception): never | void;
161
+ ```
162
+
163
+ **Parâmetros:**
164
+
165
+ | Parâmetro | Tipo | Obrigatório | Descrição |
166
+ |---|---|---|---|
167
+ | `condition` | `boolean` | Sim | Se `true`, lança a exceção |
168
+ | `exception` | `() => Exception` | Sim | Factory que cria a exceção (lazy — só chamada se `condition: true`) |
169
+
170
+ **Exemplo:**
171
+
172
+ ```typescript
173
+ throwIf(!user, () => new InvalidArgumentException("User is required"));
174
+ // Após esta linha, TypeScript sabe que `user` existe (type narrowing via `never`)
175
+
176
+ throwIf(amount < 0, () => new InvalidArgumentException("Amount must be positive"));
177
+ ```
178
+
179
+ See also: `tests/vitest/helpers/throw-if.test.ts` para padrões de validação.
180
+
181
+ ---
182
+
183
+ ### Common Patterns
184
+
185
+ **Retry com exponential backoff:**
186
+
187
+ ```typescript
188
+ let delay = 500;
189
+ const result = await retry({
190
+ times: 5,
191
+ sleep: delay,
192
+ callback: async (attempt) => {
193
+ delay = 500 * Math.pow(2, attempt - 1); // 500, 1000, 2000, 4000, 8000
194
+ return await unstableApi();
195
+ },
196
+ });
197
+ ```
198
+
199
+ **Retry com timeout por tentativa:**
200
+
201
+ ```typescript
202
+ const result = await retry({
203
+ times: 3,
204
+ sleep: 1000,
205
+ callback: async (attempt) => {
206
+ return await timeout({
207
+ name: `attempt-${attempt}`,
208
+ timeout: 5000,
209
+ callback: () => fetchData(),
210
+ });
211
+ },
212
+ });
213
+ ```
214
+
215
+ **Validação com throwIf encadeado:**
216
+
217
+ ```typescript
218
+ throwIf(!config.url, () => new InvalidArgumentException("URL is required"));
219
+ throwIf(config.timeout < 0, () => new InvalidArgumentException("Timeout must be positive"));
220
+ // config agora está validado com tipagem correta
221
+ ```
222
+
223
+ See also: `tests/vitest/helpers/` para todos os testes de helpers.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odg/chemical-x",
3
- "version": "2.1.3",
3
+ "version": "2.3.0",
4
4
  "description": "Chemical-X Project It's the basis of everything",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,7 +30,9 @@
30
30
  },
31
31
  "files": [
32
32
  "./dist/",
33
- "./README.md"
33
+ "./README.md",
34
+ "agents.md",
35
+ "docs/**"
34
36
  ],
35
37
  "author": "Dragons Gamers <https://www.linkedin.com/in/victor-alves-odgodinho>",
36
38
  "license": "MIT",