jsegd-bpm 0.1.8 → 0.1.10

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # jsEGD BPM
2
2
 
3
- Biblioteca TypeScript de runtime para desenvolvimento de formulários e workflows no ambiente **EGD BPM** — EGD Tecnologia.
4
- Fornece componentes de anexo, gerenciamento de workers para datasets, controle do ciclo de vida do workflow e utilitários de formulário integrados ao DOM do EGD BPM.
3
+ Biblioteca TypeScript de runtime para desenvolvimento de formulários e workflows em um ambiente BPM genérico.
4
+ Fornece componentes de anexo, gerenciamento de workers para datasets, controle do ciclo de vida do fluxo e utilitários de formulário integrados ao DOM.
5
5
 
6
6
  > **Dependências par obrigatórias:** [`jsegd`](https://jsegd.netlify.app) ≥ 1.1.0 e [`alpinejs`](https://alpinejs.dev) ≥ 3.0.0
7
7
 
@@ -25,7 +25,7 @@ npm install jsegd-bpm jsegd alpinejs
25
25
 
26
26
  ## `WorkerManager` — Consultas de Dataset em Web Workers
27
27
 
28
- Gerencia um pool de Web Workers para executar consultas à API de Datasets do EGD BPM fora da thread principal. Suporta deduplicação de requisições, cache em IndexedDB e cancelamento HTTP real via `AbortController`.
28
+ Gerencia um pool de Web Workers para executar consultas à API de datasets fora da thread principal. Suporta deduplicação de requisições, cache em IndexedDB e cancelamento HTTP real via `AbortController`.
29
29
 
30
30
  ```typescript
31
31
  import { WorkerManager, ConstraintsType } from 'jsegd-bpm'
@@ -37,8 +37,8 @@ cache.initialize({ storeName: 'datasets', cacheExpirationMs: 60 * 60 * 1000 })
37
37
 
38
38
  const manager = new WorkerManager({ poolSize: 4, cache })
39
39
 
40
- const { promise, cancel } = manager.query('https://tenant.bpm.empresa.com', {
41
- datasetId: 'dsColaboradores',
40
+ const { promise, cancel } = manager.query('https://exemplo.local', {
41
+ datasetId: 'dsRegistros',
42
42
  field: ['nome', 'email', 'matricula'],
43
43
  constraintsField: ['ativo'],
44
44
  constraintsInitialValue: ['true'],
@@ -87,13 +87,13 @@ Botão com dropdown para upload de arquivos vinculados ao processo.
87
87
 
88
88
  ```html
89
89
  <!-- Tipo de anexo fixo -->
90
- <attachment-button description="CONTRATO"></attachment-button>
90
+ <attachment-button description="DOCUMENTO"></attachment-button>
91
91
 
92
92
  <!-- Prompt ao usuário para informar a descrição no upload -->
93
93
  <attachment-button></attachment-button>
94
94
 
95
95
  <!-- Somente leitura: oculta botão de adicionar -->
96
- <attachment-button description="CONTRATO" noaddbutton></attachment-button>
96
+ <attachment-button description="DOCUMENTO" noaddbutton></attachment-button>
97
97
  ```
98
98
 
99
99
  | Atributo | Tipo | Descrição |
@@ -117,7 +117,7 @@ Tabela que lista os anexos do processo com suporte a drag-and-drop para reordena
117
117
 
118
118
  ## `BeforeSendValidate` — Validação com feedback visual
119
119
 
120
- Integra validação de campos com o sistema de erros visuais do tema EGD BPM (`data-group` / `data-helper`).
120
+ Integra validação de campos com o sistema de erros visuais do tema do formulário (`data-group` / `data-helper`).
121
121
 
122
122
  ```typescript
123
123
  import { BeforeSendValidate } from 'jsegd-bpm'
@@ -126,9 +126,9 @@ import type { FieldError } from 'jsegd-bpm'
126
126
  function validarFormulario() {
127
127
  const erros: FieldError[] = []
128
128
 
129
- const campoNome = document.querySelector<HTMLInputElement>('[name="nome_solicitante"]')
130
- if (!campoNome?.value) {
131
- erros.push({ field: campoNome, errorMessage: 'Informe o nome do solicitante' })
129
+ const campoTexto = document.querySelector<HTMLInputElement>('[name="nome"]')
130
+ if (!campoTexto?.value) {
131
+ erros.push({ field: campoTexto, errorMessage: 'Informe o nome' })
132
132
  }
133
133
 
134
134
  if (erros.length > 0) {
@@ -138,13 +138,115 @@ function validarFormulario() {
138
138
  }
139
139
  ```
140
140
 
141
- `throwValidationError` lança sempre — use dentro de `beforeSendValidate` do EGD BPM ou em hooks de `WorkflowViewPatcher`.
141
+ `throwValidationError` lança sempre — use dentro de `beforeSendValidate` do formulário ou em hooks de `WorkflowViewPatcher`.
142
+
143
+ ---
144
+
145
+ ## `Validator` — Validação local e de submit
146
+
147
+ O `Validator` tem dois usos complementares:
148
+ - `Validator.add(...)` cria um validador isolado para cada instância de `Alpine.data(...)`
149
+ - `Validator.getInstance().register(code, rules)` agrupa várias regras de submit sob o mesmo código numérico
150
+
151
+ ```typescript
152
+ import { Validator } from 'jsegd-bpm'
153
+
154
+ function departamentoComponent() {
155
+ const regras: Record<string, () => boolean | Promise<boolean>> = {
156
+ taxa: () => this.possuiTaxa === '1' && !this.taxa,
157
+ campoExtra: () => this.possuiTaxa === '1' && this.campoExtra === 'invalido',
158
+ campoIndependente: () => !this.campoIndependente,
159
+ }
160
+
161
+ const validadores = Validator.add(regras)
162
+
163
+ return {
164
+ possuiTaxa: '0',
165
+ taxa: '',
166
+ campoExtra: '',
167
+ campoIndependente: '',
168
+ temErro: false,
169
+
170
+ async init() {
171
+ this.$watch('possuiTaxa', async () => {
172
+ await validadores.validate('taxa')
173
+ await validadores.validate('campoExtra')
174
+ this.temErro = await validadores.hasError()
175
+ })
176
+ },
177
+
178
+ async onInput(field: string) {
179
+ await validadores.validate(field)
180
+ this.temErro = await validadores.hasError()
181
+ },
182
+ }
183
+ }
184
+ ```
185
+
186
+ `hasError()` e `validate(field)` são assíncronos — armazene o resultado em uma propriedade reativa (`temErro`) para que o Alpine reflita o estado no template. Funções síncronas continuam aceitas sem alteração.
187
+
188
+ ```typescript
189
+ import { Validator } from 'jsegd-bpm'
190
+
191
+ const cancelarSubmit = Validator.getInstance().register(100, {
192
+ taxa: () => this.possuiTaxa === '1' && !this.taxa,
193
+ // exemplo de regra assíncrona — ex.: validação remota
194
+ campoExtra: async () => {
195
+ const resultado = await verificarCampoNoServidor(this.campoExtra)
196
+ return resultado.valido
197
+ },
198
+ campoIndependente: () => !this.campoIndependente,
199
+ })
200
+
201
+ try {
202
+ await Validator.getInstance().execute(100)
203
+ } catch (error) {
204
+ // impede o envio do formulário
205
+ }
206
+
207
+ cancelarSubmit()
208
+ ```
209
+
210
+ `register(code, rules)` aceita tanto uma função única quanto um mapa de regras — síncronas ou assíncronas. `unregister(code, rules)` remove o mesmo conjunto informado.
211
+
212
+ ### Exemplo no HTML
213
+
214
+ ```html
215
+ <section x-data="departamentoComponent()">
216
+ <label>
217
+ Possui taxa?
218
+ <select x-model="possuiTaxa" @change="onInput('taxa')">
219
+ <option value="0">Nao</option>
220
+ <option value="1">Sim</option>
221
+ </select>
222
+ </label>
223
+
224
+ <label>
225
+ Taxa
226
+ <input type="text" x-model="taxa" @input="onInput('taxa')" />
227
+ </label>
228
+
229
+ <label>
230
+ Campo extra
231
+ <input type="text" x-model="campoExtra" @input="onInput('campoExtra')" />
232
+ </label>
233
+
234
+ <label>
235
+ Campo independente
236
+ <input type="text" x-model="campoIndependente" @input="onInput('campoIndependente')" />
237
+ </label>
238
+
239
+ <p x-show="temErro">Existem campos invalidos.</p>
240
+ </section>
241
+ ```
242
+
243
+ > Como `hasError()` agora é assíncrono, use uma propriedade reativa (`temErro`) em vez de um getter direto no `x-show`.
142
244
 
143
245
  ---
144
246
 
145
247
  ## `WorkflowViewPatcher` — Hooks no widget de processo
146
248
 
147
- Substitui métodos do widget nativo `ECM_WKFView` para interceptar o ciclo de envio do processo sem modificar o EGD BPM.
249
+ Substitui métodos do widget nativo `ECM_WKFView` para interceptar o ciclo de envio do fluxo sem modificar o formulário.
148
250
 
149
251
  ```typescript
150
252
  import { WorkflowViewPatcher } from 'jsegd-bpm'
@@ -159,8 +261,8 @@ WorkflowViewPatcher.patchAll()
159
261
  WorkflowViewPatcher.addBeforeValidate(async () => {
160
262
  // Executado antes da validação do widget.
161
263
  // Lançar exceção cancela o envio e reabilita os botões.
162
- const valor = document.querySelector<HTMLInputElement>('[name="campo_critico"]')?.value
163
- if (!valor) throw new Error('Campo crítico obrigatório')
264
+ const valor = document.querySelector<HTMLInputElement>('[name="campo_principal"]')?.value
265
+ if (!valor) throw new Error('Campo principal obrigatório')
164
266
  })
165
267
 
166
268
  WorkflowViewPatcher.addAfterValidate(async () => {
@@ -178,7 +280,7 @@ WorkflowViewPatcher.addOnMoveError(() => {
178
280
 
179
281
  WorkflowViewPatcher.addOnCompletionLinkAdd((message) => {
180
282
  // Adiciona links à tela de conclusão após a movimentação
181
- message.links.push({ description: 'Abrir tarefa seguinte', href: '/minha-tarefa' })
283
+ message.links.push({ description: 'Abrir próxima etapa', href: '/proxima-etapa' })
182
284
  })
183
285
 
184
286
  // Ao desmontar o formulário (SPAs): restaura os métodos originais
@@ -217,12 +319,12 @@ onde `{domínio}` é o identificador do **agregado de negócio** ao qual o campo
217
319
 
218
320
  | Campo no DOM | Domínio | Atributo no modelo |
219
321
  | ------------------- | ----------- | ------------------ |
220
- | `contrato_indice` | `contrato` | `indice` |
221
- | `imovel_cep` | `imovel` | `cep` |
222
- | `vigencia_prazo` | `vigencia` | `prazo` |
223
- | `fornecedor_cep` | `fornecedor`| `cep` |
322
+ | `departamento_indice` | `departamento` | `indice` |
323
+ | `area_cep` | `area` | `cep` |
324
+ | `vigencia_prazo` | `vigencia` | `prazo` |
325
+ | `cadastro_cep` | `cadastro` | `cep` |
224
326
 
225
- > **Importante:** o `{domínio}` é o prefixo persistido no banco pelo Fluig — é parte integrante do nome da coluna e **não deve ser omitido** no HTML. O `load` e o `save` gerenciam a conversão entre o nome DOM e o atributo do modelo de forma transparente.
327
+ > **Importante:** o `{domínio}` é o prefixo persistido no banco — é parte integrante do nome da coluna e **não deve ser omitido** no HTML. O `load` e o `save` gerenciam a conversão entre o nome DOM e o atributo do modelo de forma transparente.
226
328
 
227
329
  O `moduleId` do workflow (quem exibe o campo na tela) e o `stage` (em que fase do processo estamos) são **independentes** do domínio do campo — um mesmo módulo pode exibir campos de múltiplos domínios.
228
330
 
@@ -236,13 +338,13 @@ Lê e escreve diretamente nos elementos `input`, `select` e `textarea` do formul
236
338
  ```typescript
237
339
  import { BpmFormRepository } from 'jsegd-bpm'
238
340
 
239
- interface Contrato {
341
+ interface Departamento {
240
342
  indice: string
241
343
  primeiroPagamento: string
242
344
  reajuste: string
243
345
  }
244
346
 
245
- interface Imovel {
347
+ interface Area {
246
348
  cep: string
247
349
  logradouro: string
248
350
  municipio: string
@@ -255,22 +357,22 @@ interface ItemTabela {
255
357
 
256
358
  const repo = new BpmFormRepository()
257
359
 
258
- // Ler domínio 'contrato' — lê campos com name="contrato_*" do DOM
259
- // DOM: contrato_indice, contrato_primeiro_pagamento, contrato_reajuste
260
- const contrato = repo.load<Contrato>('contrato')
261
- console.log(contrato.indice) // valor de input[name="contrato_indice"]
262
- console.log(contrato.primeiroPagamento) // valor de input[name="contrato_primeiro_pagamento"]
360
+ // Ler domínio 'departamento' — lê campos com name="departamento_*" do DOM
361
+ // DOM: departamento_indice, departamento_primeiro_pagamento, departamento_reajuste
362
+ const departamento = repo.load<Departamento>('departamento')
363
+ console.log(departamento.indice) // valor de input[name="departamento_indice"]
364
+ console.log(departamento.primeiroPagamento) // valor de input[name="departamento_primeiro_pagamento"]
263
365
 
264
- // Ler domínio 'imovel' — desambigua de 'fornecedor_cep', 'contrato_cep', etc.
265
- const imovel = repo.load<Imovel>('imovel')
266
- console.log(imovel.cep) // valor de input[name="imovel_cep"]
366
+ // Ler domínio 'area' — desambigua de 'cadastro_cep', 'departamento_cep', etc.
367
+ const area = repo.load<Area>('area')
368
+ console.log(area.cep) // valor de input[name="area_cep"]
267
369
 
268
370
  // Ler tabela filha
269
371
  const itens = repo.loadTable<ItemTabela>('tabItens')
270
372
 
271
373
  // Persistir no DOM — save converte camelCase → prefixo+snake_case
272
- repo.save<Contrato>('contrato', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
273
- // escreve: input[name="contrato_indice"] e input[name="contrato_primeiro_pagamento"]
374
+ repo.save<Departamento>('departamento', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
375
+ // escreve: input[name="departamento_indice"] e input[name="departamento_primeiro_pagamento"]
274
376
 
275
377
  // Substituir linhas da tabela filha
276
378
  repo.saveTable<ItemTabela>('tabItens', [
@@ -314,18 +416,18 @@ Processos existentes cujos campos não seguem a convenção `{domínio}_{atribut
314
416
  ```typescript
315
417
  import { loadFields } from 'jsegd-bpm'
316
418
 
317
- interface Solicitante {
419
+ interface Requisitante {
318
420
  nome: string
319
421
  email: string
320
422
  }
321
423
 
322
- // Campo legado: sufixo em vez de prefixo — nome_solicitante, email_solicitante
323
- const dados = loadFields<Solicitante>({
324
- nome: 'nome_solicitante',
325
- email: 'email_solicitante',
424
+ // Campo legado: sufixo em vez de prefixo — nome_requisitante, email_requisitante
425
+ const dados = loadFields<Requisitante>({
426
+ nome: 'nome_requisitante',
427
+ email: 'email_requisitante',
326
428
  })
327
- // dados.nome === valor de input[name="nome_solicitante"]
328
- // dados.email === valor de input[name="email_solicitante"]
429
+ // dados.nome === valor de input[name="nome_requisitante"]
430
+ // dados.email === valor de input[name="email_requisitante"]
329
431
  ```
330
432
 
331
433
  > **Regra:** `loadFields` **não faz parte de `IFormRepository`** — é um utilitário de compatibilidade para processos legados. Novos processos devem usar `repository.load(section)` exclusivamente.
@@ -346,59 +448,59 @@ import { defineWorkflowConfig } from 'jsegd-bpm'
346
448
  export const workflowConfig = defineWorkflowConfig({
347
449
  modules: [
348
450
  {
349
- moduleId: 'solicitante',
451
+ moduleId: 'areaInicial',
350
452
  label: 'Dados Iniciais',
351
453
  icon: 'file-text',
352
454
  order: 1,
353
455
  showInNavigation: true,
354
456
  renderContent: true,
355
- contentIncludePath: 'solicitante.html',
457
+ contentIncludePath: 'area-inicial.html',
356
458
  },
357
459
  {
358
- moduleId: 'juridico',
359
- label: 'Jurídico',
460
+ moduleId: 'areaA',
461
+ label: 'Área A',
360
462
  icon: 'gavel',
361
463
  order: 2,
362
464
  showInNavigation: true,
363
465
  renderContent: true,
364
- contentIncludePath: 'juridico.html',
466
+ contentIncludePath: 'area-a.html',
365
467
  },
366
468
  {
367
- moduleId: 'financeiro',
368
- label: 'Financeiro',
469
+ moduleId: 'areaB',
470
+ label: 'Área B',
369
471
  icon: 'dollar-sign',
370
472
  order: 3,
371
473
  showInNavigation: true,
372
474
  renderContent: true,
373
- contentIncludePath: 'financeiro.html',
475
+ contentIncludePath: 'area-b.html',
374
476
  },
375
477
  ],
376
478
  activities: [
377
479
  {
378
480
  sequence: 9,
379
- description: 'Solicitação inicial',
481
+ description: 'Etapa inicial',
380
482
  kind: 'human',
381
- stage: 'solicitacao',
382
- modules: { visible: ['solicitante'], editable: ['solicitante'], active: 'solicitante' },
483
+ stage: 'inicio',
484
+ modules: { visible: ['areaInicial'], editable: ['areaInicial'], active: 'areaInicial' },
383
485
  },
384
486
  {
385
487
  sequence: 53,
386
- description: 'Aprovação jurídica',
488
+ description: 'Análise da área A',
387
489
  kind: 'human',
388
- stage: 'juridico',
389
- modules: { visible: ['solicitante', 'juridico'], editable: ['juridico'], active: 'juridico' },
490
+ stage: 'analiseA',
491
+ modules: { visible: ['areaInicial', 'areaA'], editable: ['areaA'], active: 'areaA' },
390
492
  },
391
493
  {
392
494
  sequence: 61,
393
- description: 'Análise financeira',
495
+ description: 'Análise da área B',
394
496
  kind: 'human',
395
- stage: 'financeiro',
396
- modules: { visible: ['solicitante', 'juridico', 'financeiro'], editable: ['financeiro'] },
497
+ stage: 'analiseB',
498
+ modules: { visible: ['areaInicial', 'areaA', 'areaB'], editable: ['areaB'] },
397
499
  },
398
500
  { sequence: 88, description: 'Roteamento interno', kind: 'routing' },
399
501
  ],
400
502
  } as const)
401
- // Tipo de ModuleId inferido: 'solicitante' | 'juridico' | 'financeiro'
503
+ // Tipo de ModuleId inferido: 'areaInicial' | 'areaA' | 'areaB'
402
504
  ```
403
505
 
404
506
  **`ActivityKind`** — controla o comportamento na barra de progresso:
@@ -425,10 +527,10 @@ const currentSequence: number = parent.ECM.workflowView.processDefinition.cardIn
425
527
  const historyType: string | null = parent.ECM.workflowView.processDefinition.historyType ?? null
426
528
 
427
529
  const completedStages = extractCompletedStages(rawHistory, workflowConfig.activities)
428
- // Ex: ['solicitacao', 'juridico']
530
+ // Ex: ['inicio', 'analiseA']
429
531
 
430
532
  const currentStage = extractCurrentStage(currentSequence, historyType, workflowConfig.activities)
431
- // Ex: { stage: 'financeiro', status: 'current' }
533
+ // Ex: { stage: 'analiseB', status: 'current' }
432
534
 
433
535
  const processHistory: ProcessHistory = { completedStages, currentStage }
434
536
  ```
@@ -445,9 +547,9 @@ import { resolveWorkflowScreen } from 'jsegd-bpm'
445
547
  const screen = resolveWorkflowScreen(workflowConfig, currentSequence, processHistory)
446
548
 
447
549
  // Visibilidade e editabilidade
448
- screen.isVisible('juridico') // true
449
- screen.isEditable('financeiro') // false
450
- screen.isActive('juridico') // true
550
+ screen.isVisible('areaA') // true
551
+ screen.isEditable('areaB') // false
552
+ screen.isActive('areaA') // true
451
553
 
452
554
  // Estado da atividade
453
555
  screen.isAwaitingSystem() // true quando kind === 'system' ou status === 'waiting'
@@ -456,9 +558,9 @@ screen.isInSupport() // true para kind === 'support'
456
558
  // Barra de progresso
457
559
  const stages = screen.getProgressBarStages()
458
560
  // [
459
- // { stage: 'solicitacao', status: 'done' },
460
- // { stage: 'juridico', status: 'done' },
461
- // { stage: 'financeiro', status: 'current' },
561
+ // { stage: 'inicio', status: 'done' },
562
+ // { stage: 'analiseA', status: 'done' },
563
+ // { stage: 'analiseB', status: 'current' },
462
564
  // ]
463
565
 
464
566
  // Módulos
@@ -518,7 +620,7 @@ customElements.define('attachments-table', AttachmentsTable)
518
620
 
519
621
  // Alpine stores
520
622
  const stores = registerStores(Alpine, {
521
- solicitante: { nome: '', departamento: '' },
623
+ departamento: { nome: '', area: '' },
522
624
  ui: { carregando: false },
523
625
  })
524
626
 
@@ -539,8 +641,8 @@ await WorkflowViewPatcher.init()
539
641
  WorkflowViewPatcher.patchAll()
540
642
  WorkflowViewPatcher.addBeforeValidate(async () => {
541
643
  const repo = new BpmFormRepository()
542
- const dados = repo.load<{ nome: string }>('solicitante')
543
- if (!dados.nome) throw new Error('Informe o nome do solicitante')
644
+ const dados = repo.load<{ nome: string }>('departamento')
645
+ if (!dados.nome) throw new Error('Informe o nome')
544
646
  })
545
647
 
546
648
  Alpine.start()
@@ -550,4 +652,4 @@ Alpine.start()
550
652
 
551
653
  ## Licença
552
654
 
553
- Proprietária — EGD Tecnologia. Uso restrito a projetos autorizados.
655
+ Proprietária — uso restrito a projetos autorizados.
@@ -1076,7 +1076,12 @@ type StoreProxy<T extends StoreMap> = {
1076
1076
  */
1077
1077
  declare function registerStores<T extends StoreMap>(alpine: Pick<Alpine, 'store'>, storeMap: T): StoreProxy<T>;
1078
1078
 
1079
- type ValidationFn = (...args: unknown[]) => boolean;
1079
+ type ValidationFn = (...args: unknown[]) => boolean | Promise<boolean>;
1080
+ type ValidationRules = Record<string, ValidationFn>;
1081
+ type ValidatorHandle = {
1082
+ validate(field?: string): Promise<boolean>;
1083
+ hasError(): Promise<boolean>;
1084
+ };
1080
1085
  /**
1081
1086
  * Validador tipado com padrão singleton.
1082
1087
  * Permite registrar, remover e executar funções de validação associadas a códigos numéricos.
@@ -1097,24 +1102,50 @@ declare class Validator {
1097
1102
  */
1098
1103
  static getInstance(): Validator;
1099
1104
  /**
1100
- * Registra uma função de validação associada a um código numérico.
1101
- * Retorna uma função para cancelar o registro.
1105
+ * Cria um validador isolado para um conjunto de regras nomeadas.
1106
+ * Cada chamada retorna um handle independente, útil para instâncias locais de Alpine.data().
1107
+ * @example
1108
+ * const validadores = Validator.add({
1109
+ * taxa: () => this.possuiTaxa === '1' && !this.taxa,
1110
+ * campoExtra: () => this.possuiTaxa === '1' && this.campoExtra === 'invalido',
1111
+ * })
1112
+ */
1113
+ static add(rules: ValidationRules): ValidatorHandle;
1114
+ private addRule;
1115
+ private removeRule;
1116
+ private normalizeRules;
1117
+ private unregisterAll;
1118
+ /**
1119
+ * Registra uma validação associada a um código numérico.
1120
+ * Aceita uma única função ou um lote de regras nomeadas.
1121
+ * Retorna uma função para cancelar o registro do mesmo conjunto informado.
1102
1122
  * @example Validator.getInstance().register(100, () => value > 0)
1123
+ * @example Validator.getInstance().register(100, {
1124
+ * fieldA: () => valueA > 0,
1125
+ * fieldB: () => valueB !== '',
1126
+ * })
1103
1127
  */
1104
- register(code: number, fn: ValidationFn): () => void;
1128
+ register(code: number, rules: ValidationFn): () => void;
1129
+ register(code: number, rules: ValidationRules): () => void;
1105
1130
  /**
1106
- * Remove uma função de validação específica associada a um código numérico.
1131
+ * Remove uma validação associada a um código numérico.
1132
+ * Aceita uma única função ou o mesmo lote de regras nomeadas usado no registro.
1107
1133
  * @example Validator.getInstance().unregister(100, myFn)
1134
+ * @example Validator.getInstance().unregister(100, {
1135
+ * fieldA: () => valueA > 0,
1136
+ * fieldB: () => valueB !== '',
1137
+ * })
1108
1138
  */
1109
- unregister(code: number, fn: ValidationFn): void;
1139
+ unregister(code: number, rules: ValidationFn): void;
1140
+ unregister(code: number, rules: ValidationRules): void;
1110
1141
  /**
1111
1142
  * Executa todas as funções de validação registradas para o código informado.
1112
1143
  * Lança um erro se qualquer função retornar `false`.
1113
1144
  * Se não houver validações registradas para o código, retorna silenciosamente.
1114
- * @example Validator.getInstance().execute(100)
1145
+ * @example await Validator.getInstance().execute(100)
1115
1146
  * @throws {Error} Se alguma validação falhar.
1116
1147
  */
1117
- execute(code: number): void;
1148
+ execute(code: number): Promise<void>;
1118
1149
  /**
1119
1150
  * Remove todas as funções de validação de um código específico, ou limpa todos os registros se nenhum código for informado.
1120
1151
  * @example