jsegd-bpm 0.1.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,1045 @@
1
+ import { ICache } from 'jsegd';
2
+ import { Alpine } from 'alpinejs';
3
+
4
+ /**
5
+ * Resposta de sucesso retornada pelo endpoint `/dataset/api/v2/dataset-handle/search` (HTTP 200).
6
+ */
7
+ interface DatasetResponse {
8
+ /** Nomes dos campos retornados pelo dataset. */
9
+ columns: string[];
10
+ /** Linhas de dados retornadas pelo dataset. */
11
+ values: DatasetRow[];
12
+ }
13
+ /** Uma linha do dataset — chaves são os nomes dos campos retornados. */
14
+ type DatasetRow = Record<string, unknown>;
15
+ /**
16
+ * Resposta de erro retornada pela API Fluig (HTTP 400, 401, 500).
17
+ */
18
+ interface DatasetError {
19
+ /** Código de erro. */
20
+ code: string;
21
+ /** Mensagem resumida do erro. */
22
+ message: string;
23
+ /** Mensagem detalhada do erro. */
24
+ detailedMessage: string;
25
+ /** URL de ajuda, quando disponível. */
26
+ helpUrl?: string;
27
+ /** Detalhes adicionais do erro, quando presentes. */
28
+ details?: unknown[];
29
+ }
30
+
31
+ declare enum ConstraintsType {
32
+ MUST = "MUST",
33
+ MUST_NOT = "MUST_NOT",
34
+ SHOULD = "SHOULD"
35
+ }
36
+ interface SearchParams {
37
+ /** Código do dataset — obrigatório. */
38
+ datasetId: string;
39
+ /** Campos a retornar; omitir para retornar todos os campos. */
40
+ field?: string[];
41
+ /** Registros a ignorar — usado para paginação (padrão: 0). */
42
+ offset?: number;
43
+ /** Máximo de registros a retornar (padrão: 300; 0 = todos). */
44
+ limit?: number;
45
+ /** Nome do campo para ordenação, opcionalmente sufixado com _ASC ou _DESC. */
46
+ orderby?: string;
47
+ constraintsField?: string[];
48
+ constraintsInitialValue?: string[];
49
+ constraintsFinalValue?: string[];
50
+ constraintsType?: ConstraintsType[];
51
+ /** Quando verdadeiro, o curinga % é aceito no valor inicial/final correspondente. */
52
+ constraintsLikeSearch?: boolean[];
53
+ }
54
+
55
+ /**
56
+ * Promise cancelável retornada por {@link WorkerManager.query}.
57
+ */
58
+ type CancelablePromise<T> = {
59
+ /** Promise que resolve com o resultado da consulta. */
60
+ promise: Promise<T>;
61
+ /** Função para cancelar a requisição e liberar o worker. */
62
+ cancel: () => void;
63
+ };
64
+
65
+ type CacheOptions = {
66
+ storeName: string;
67
+ cacheExpirationMs: number;
68
+ };
69
+ interface WorkerManagerOptions {
70
+ poolSize?: number;
71
+ /** Injeta uma instância existente de ICache (compartilhada entre componentes). */
72
+ cache?: ICache;
73
+ /** Cria um LocalCache interno com as opções fornecidas. */
74
+ cacheOptions?: CacheOptions;
75
+ }
76
+ /**
77
+ * Gerencia um pool de Web Workers para executar consultas à API de Datasets do Fluig fora da thread principal.
78
+ * Suporta deduplicacão de requisições, cache em IndexedDB e cancelamento HTTP real via AbortController.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * import { WorkerManager, ConstraintsType } from 'jsegd-bpm'
83
+ *
84
+ * const manager = new WorkerManager({
85
+ * poolSize: 4,
86
+ * cacheOptions: { storeName: 'datasetCache', cacheExpirationMs: 24 * 60 * 60 * 1000 }
87
+ * })
88
+ *
89
+ * const { promise, cancel } = manager.query('https://tenant.fluig.com', {
90
+ * datasetId: 'dsColaboradores',
91
+ * field: ['nome', 'email'],
92
+ * constraintsField: ['ativo'],
93
+ * constraintsInitialValue: ['true'],
94
+ * constraintsType: [ConstraintsType.MUST],
95
+ * })
96
+ *
97
+ * // Cancelar se necessário:
98
+ * // cancel()
99
+ *
100
+ * const result = await promise
101
+ * console.log(result.columns) // ['nome', 'email']
102
+ * console.log(result.values) // [{ nome: 'João', email: 'joao@co.com' }, ...]
103
+ * ```
104
+ */
105
+ declare class WorkerManager {
106
+ private pool;
107
+ private workerMeta;
108
+ private taskQueue;
109
+ private inFlight;
110
+ private cache;
111
+ private nextRequestId;
112
+ constructor(options?: WorkerManagerOptions);
113
+ /**
114
+ * Consulta a API de Datasets do Fluig. Retorna uma CancelablePromise.
115
+ * Chame `cancel()` para abortar a requisição HTTP e liberar o worker imediatamente.
116
+ */
117
+ query(baseUrl: string, params: SearchParams): CancelablePromise<DatasetResponse>;
118
+ /**
119
+ * Encerra todos os workers do pool. Chame quando o gerenciador não for mais necessário
120
+ * para evitar vazamentos de memória e workers zumbis.
121
+ */
122
+ terminate(): void;
123
+ private deduplicateOrEnqueue;
124
+ private enqueueRequest;
125
+ private scheduleNext;
126
+ private abortRequest;
127
+ private handleResponse;
128
+ private buildUrl;
129
+ }
130
+
131
+ type UploadStatus = 'success' | 'error' | 'reset';
132
+ interface UploadEventDetail {
133
+ status: UploadStatus;
134
+ }
135
+ declare global {
136
+ interface WindowEventMap {
137
+ 'jsegd:upload:success': CustomEvent<UploadEventDetail>;
138
+ 'jsegd:upload:error': CustomEvent<UploadEventDetail>;
139
+ 'jsegd:upload:reset': CustomEvent<UploadEventDetail>;
140
+ 'jsegd:attachment:download': CustomEvent<{
141
+ documentId: number;
142
+ }>;
143
+ }
144
+ }
145
+
146
+ /** Origem do upload de um anexo */
147
+ type AttachmentSource = 'button' | 'toolbar' | 'drag-drop';
148
+ /**
149
+ * Metadados associados a um único documento anexado ao processo.
150
+ * Persiste informações que o ECM não armazena nativamente.
151
+ */
152
+ interface AttachmentRecord {
153
+ /** ID do documento no ECM */
154
+ documentId: number;
155
+ /** Mecanismo pelo qual o arquivo foi adicionado */
156
+ source: AttachmentSource;
157
+ /**
158
+ * Descrição base do `AttachButton` que originou o upload.
159
+ * Presente apenas quando `source === 'button'`.
160
+ */
161
+ buttonDescription?: string;
162
+ /** Filtro de tipos de arquivo ativo no momento do upload (`null` = qualquer tipo) */
163
+ accept: string | null;
164
+ /** Número de sequência da movimentação do processo em que foi anexado */
165
+ workflowSequence: number;
166
+ /** Data e hora do upload em ISO 8601 */
167
+ uploadedAt: string;
168
+ /**
169
+ * Metadados arbitrários adicionados pelo consumidor da biblioteca.
170
+ * Nunca interpretado internamente — apenas serializado/desserializado.
171
+ */
172
+ custom?: Record<string, unknown>;
173
+ }
174
+
175
+ /**
176
+ * @protected
177
+ */
178
+ declare class Attach {
179
+ private static instance;
180
+ /** Origem do último upload iniciado (atualizado por `add()` e `uploadBlob()`) */
181
+ static currentUploadSource: AttachmentSource;
182
+ /** Filtro de tipos do último upload iniciado */
183
+ static currentUploadAccept: string | null;
184
+ private constructor();
185
+ static getInstance(): Attach;
186
+ private interceptUploadEvents;
187
+ /**
188
+ * Abre o seletor de arquivos para adicionar um novo anexo ao processo.
189
+ * Aplica versionamento automático ao nome quando já existe um anexo com a mesma descrição.
190
+ *
191
+ * @param attachmentDescription Descrição (label) do anexo — usada como nome do arquivo no ECM
192
+ * @param accept Tipos de arquivo aceitos pelo seletor (ex: ".pdf,.docx"). `null` aceita qualquer tipo.
193
+ */
194
+ add(attachmentDescription: string, accept: string | null | undefined): void;
195
+ /**
196
+ * Abre o visualizador de documentos para o anexo informado.
197
+ * Quando há mais de um anexo com a mesma descrição, exibe um modal de seleção.
198
+ * Bloqueia ação em processos não iniciados e valida permissões de leitura.
199
+ *
200
+ * @param attachmentDescription Descrição do anexo a ser visualizado
201
+ */
202
+ view(attachmentDescription: string): void;
203
+ /**
204
+ * Remove um anexo do processo após confirmação via modal.
205
+ * Quando há mais de um anexo com a mesma descrição, exibe um modal de seleção.
206
+ * Valida permissões de exclusão antes de prosseguir.
207
+ *
208
+ * @param attachmentDescription Descrição do anexo a ser removido
209
+ */
210
+ remove(attachmentDescription: string): void;
211
+ /**
212
+ * Inicia o download de um anexo pelo seu identificador de documento.
213
+ * Bloqueia a ação em processos não iniciados.
214
+ *
215
+ * @param documentId Identificador do documento a ser baixado
216
+ */
217
+ static download(documentId: number): void;
218
+ /**
219
+ * Abre o painel de edição de conteúdo para o anexo informado.
220
+ * Filtra apenas anexos publicados que o usuário tem permissão de editar.
221
+ * Quando há mais de um anexo editável, exibe modal de seleção.
222
+ * Bloqueia a ação em processos não iniciados.
223
+ *
224
+ * @param attachmentDescription Descrição do anexo a ser editado
225
+ */
226
+ edit(attachmentDescription: string): void;
227
+ /**
228
+ * Retorna todos os anexos do processo atual.
229
+ * @returns Lista de todos os objetos `Attachment` presentes no processo
230
+ */
231
+ static getAllAttachments(): Attachment[];
232
+ /**
233
+ * Inicia o download de um Blob diretamente no navegador do usuário,
234
+ * sem interação com o ECM ou com o processo em execução.
235
+ *
236
+ * @param blob Conteúdo a ser baixado
237
+ * @param filename Nome do arquivo que será sugerido ao navegador
238
+ * @param type Tipo MIME do arquivo. Quando omitido, usa `blob.type`.
239
+ */
240
+ static downloadBlob(blob: Blob, filename: string, type?: string): void;
241
+ /**
242
+ * Faz upload programático de um Blob como anexo do processo,
243
+ * sem abrir o seletor de arquivos nativo. Sanitiza o nome antes do envio.
244
+ *
245
+ * @param blob Arquivo no formato `Blob` — deve ser não-vazio
246
+ * @param description Nome/descrição do arquivo que será exibido no ECM
247
+ * @param type Tipo MIME do arquivo. Quando omitido, usa `blob.type`.
248
+ * @throws {Error} Via toast quando o Blob é inválido, o MIME está ausente ou o contexto não está disponível
249
+ */
250
+ static uploadBlob(blob: Blob, description: string, type?: string): void;
251
+ }
252
+
253
+ /**
254
+ * Implementa um botão para gerenciar anexos
255
+ * @hideconstructor
256
+ * @example
257
+ * ```html
258
+ * <attachment-button description="CONTRATO"></attachment-button>
259
+ * ```
260
+ */
261
+ declare class AttachButton extends HTMLElement {
262
+ /**
263
+ * Descrição do tipo de anexo gerenciado pelo botão.
264
+ * Quando vazio, um modal é exibido para o usuário informar a descrição no momento do upload.
265
+ * @defaultValue `''`
266
+ */
267
+ description: string;
268
+ /**
269
+ * Filtro de tipos de arquivo aceitos pelo seletor nativo (ex: `".pdf,.docx"`).
270
+ * `null` aceita qualquer tipo de arquivo.
271
+ */
272
+ accept: string | null;
273
+ noaddbutton: string | null;
274
+ noviewbutton: string | null;
275
+ noeditbutton: string | null;
276
+ nodeletebutton: string | null;
277
+ private handleSuccess;
278
+ private handleError;
279
+ private handleDefault;
280
+ constructor();
281
+ static get observedAttributes(): string[];
282
+ attributeChangedCallback(name: string, _oldValue: string, newValue: string): void;
283
+ disconnectedCallback(): void;
284
+ /**
285
+ * @internal
286
+ */
287
+ connectedCallback(): void;
288
+ private displayButtons;
289
+ private addButton;
290
+ private viewButton;
291
+ private editButton;
292
+ private removeButton;
293
+ private showModal;
294
+ }
295
+
296
+ /**
297
+ * Modo de operação da tabela de anexos.
298
+ * - `buttons-only` — somente download por linha; uploads exclusivamente via `AttachButton` externos
299
+ * - `self-managed` — gerencia seu próprio ciclo de upload; exibe ações completas por linha;
300
+ * aceita `AttachButton` externos cujos atributos são herdados pela linha do anexo
301
+ */
302
+ type AttachmentsTableMode = 'buttons-only' | 'self-managed';
303
+ /** Opções de configuração de `AttachmentsTable` */
304
+ interface AttachmentsTableOptions {
305
+ /** Modo de operação. Obrigatório — sem valor padrão. */
306
+ mode: AttachmentsTableMode;
307
+ /**
308
+ * Tipos de arquivo aceitos nos uploads avulsos do modo `self-managed`.
309
+ * Ex: `".pdf,.docx"`. `null` aceita qualquer tipo.
310
+ */
311
+ accept?: string | null;
312
+ }
313
+ /**
314
+ * Registro de um `AttachButton` na `AttachmentsTable`.
315
+ * Armazenado para associar anexos existentes ao botão que os originou.
316
+ */
317
+ interface AttachButtonRegistration {
318
+ /** Descrição base usada pelo botão (sem sufixo `_V\d+`). */
319
+ description: string;
320
+ /** Filtro de tipos de arquivo definido no botão. */
321
+ accept: string | null;
322
+ }
323
+ /**
324
+ * Cria e gerencia uma tabela de anexos customizada no frame pai,
325
+ * mantendo a tabela nativa do Fluig oculta.
326
+ * @hideconstructor
327
+ */
328
+ declare class AttachmentsTable {
329
+ private static instance;
330
+ private static options;
331
+ private static attachInstance;
332
+ private static buttonRegistry;
333
+ private constructor();
334
+ /**
335
+ * Retorna a instância singleton da tabela de anexos.
336
+ * Deve ser chamado uma única vez durante a inicialização do form.
337
+ *
338
+ * @param options Configuração obrigatória de modo e accept
339
+ */
340
+ static getInstance(options: AttachmentsTableOptions): AttachmentsTable;
341
+ /**
342
+ * Registra um `AttachButton` para que seus metadados sejam associados
343
+ * às linhas de anexo originadas por aquele botão.
344
+ * Só tem efeito no modo `self-managed`.
345
+ * @internal Chamado por `AttachButton` durante sua inicialização.
346
+ */
347
+ static registerButton(registration: AttachButtonRegistration): void;
348
+ private static resolveButtonRegistration;
349
+ private static start;
350
+ private static render;
351
+ private static hydrateFromMetadata;
352
+ private static persistMetadata;
353
+ private static openNameInputModal;
354
+ private static getRows;
355
+ private static setOrder;
356
+ private static sortBy;
357
+ private static getCellValue;
358
+ }
359
+
360
+ /** Entrada de um arquivo para upload em lote via drag-and-drop */
361
+ type DragDropEntry = {
362
+ file: File;
363
+ name: string;
364
+ };
365
+
366
+ type FieldError = {
367
+ field?: HTMLElement | null;
368
+ errorMessage: string;
369
+ };
370
+ declare class BeforeSendValidate {
371
+ private static clearAllErrors;
372
+ static throwValidationError(fields: FieldError[]): never;
373
+ }
374
+
375
+ /**
376
+ * Override de `sendRequestEvent()` do widget de processo.
377
+ * Executa os hooks `beforeValidate` e `afterValidate` em sequência antes de enviar a solicitação.
378
+ * Reabilita os botões de ação em caso de erro ou quando a validação falha.
379
+ */
380
+ declare function sendRequestEvent(this: ECM_WKFView): Promise<void>;
381
+
382
+ /**
383
+ * Contrato dos hooks customizáveis do widget de processo.
384
+ * Estas funções são registradas pelo `WorkflowViewPatcher` e executadas em `send-request.ts`.
385
+ */
386
+ interface IWorkflowViewHooks {
387
+ /**
388
+ * Executado ANTES da validação principal do widget.
389
+ * Se lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
390
+ */
391
+ beforeValidate?: () => void | Promise<void>;
392
+ /**
393
+ * Executado APÓS `beforeSendValidate` retornar `true`, mas ANTES do envio efetivo.
394
+ * Se lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
395
+ */
396
+ afterValidate?: () => void | Promise<void>;
397
+ /**
398
+ * Executado quando a movimentação do processo é concluída com sucesso.
399
+ */
400
+ onMoveSuccess?: () => void | Promise<void>;
401
+ /**
402
+ * Executado quando ocorre erro na movimentação do processo.
403
+ */
404
+ onMoveError?: () => void | Promise<void>;
405
+ /**
406
+ * Executado para manipular os links exibidos na página de conclusão da movimentação.
407
+ *
408
+ * @param message - Objeto de mensagem de conclusão do processo.
409
+ */
410
+ onCompletionLinkAdd?: (message: ProcessCompletionMessage) => void | Promise<void>;
411
+ }
412
+ /**
413
+ * Shape do objeto de mensagem de conclusão do processo.
414
+ * Passado como parâmetro para o hook `onCompletionLinkAdd`.
415
+ */
416
+ interface ProcessCompletionMessage {
417
+ links: ProcessCompletionLink[];
418
+ [key: string]: unknown;
419
+ }
420
+ /**
421
+ * Shape de um link na página de conclusão da movimentação.
422
+ */
423
+ interface ProcessCompletionLink {
424
+ description: string;
425
+ href?: string;
426
+ bind?: string;
427
+ }
428
+
429
+ type HooksMap = {
430
+ beforeValidate: Array<() => void | Promise<void>>;
431
+ afterValidate: Array<() => void | Promise<void>>;
432
+ onMoveSuccess: Array<() => void | Promise<void>>;
433
+ onMoveError: Array<() => void | Promise<void>>;
434
+ onCompletionLinkAdd: Array<(message: ProcessCompletionMessage) => void | Promise<void>>;
435
+ };
436
+
437
+ /**
438
+ * Mapa de substituições que serão aplicadas ao widget nativo de processo.
439
+ */
440
+ declare const overrides: {
441
+ sendRequestEvent: typeof sendRequestEvent;
442
+ };
443
+ /**
444
+ * Tipo do mapa de substituições.
445
+ */
446
+ type OverrideMap = typeof overrides;
447
+ /**
448
+ * Classe utilitária para substituir métodos no widget nativo de processo.
449
+ *
450
+ * Preserva os métodos originais para permitir reversão via `restore()`.
451
+ *
452
+ * @example
453
+ * ```typescript
454
+ * // Aguardar inicialização do widget de processo
455
+ * await WorkflowViewPatcher.init()
456
+ *
457
+ * // Aplicar todos os patches registrados
458
+ * WorkflowViewPatcher.patchAll()
459
+ *
460
+ * // Registrar hooks
461
+ * WorkflowViewPatcher.addBeforeValidate(async () => {
462
+ * console.log('Antes da validação')
463
+ * })
464
+ *
465
+ * WorkflowViewPatcher.addAfterValidate(async () => {
466
+ * console.log('Após a validação')
467
+ * })
468
+ * ```
469
+ */
470
+ declare class WorkflowViewPatcher {
471
+ private static isInitialized;
472
+ private static isInitializing;
473
+ private static originalMethods;
474
+ /**
475
+ * Inicializa o patcher aguardando o carregamento do widget de processo no frame pai.
476
+ *
477
+ * Chamadas repetidas retornam imediatamente se já inicializado.
478
+ *
479
+ * @param timeout - Tempo máximo de espera em ms (padrão: 5000ms)
480
+ * @returns Promise<void>
481
+ *
482
+ * @throws {Error} Se outra chamada a `init()` já estiver em progresso
483
+ * @throws {Error} Se o widget `ECM_WKFView` não estiver disponível após o timeout
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * await WorkflowViewPatcher.init()
488
+ * WorkflowViewPatcher.patchAll()
489
+ * ```
490
+ */
491
+ static init(timeout?: number): Promise<void>;
492
+ /**
493
+ * Aplica o patch de um override específico no widget de processo.
494
+ *
495
+ * Salva o método original antes de sobrescrever, permitindo reversão via `restore()`.
496
+ *
497
+ * @param attr - Nome do método a ser substituído
498
+ * @throws {Error} Se `init()` não tiver sido chamado antes
499
+ * @throws {Error} Se o override não estiver registrado no mapa de substituições
500
+ */
501
+ static patch(attr: keyof OverrideMap): void;
502
+ /**
503
+ * Aplica patches para múltiplos métodos do widget de processo.
504
+ *
505
+ * @param attrs - Array com nomes dos métodos a serem substituídos
506
+ * @throws {Error} Se `init()` não tiver sido chamado antes
507
+ */
508
+ static patchMany(attrs: (keyof OverrideMap)[]): void;
509
+ /**
510
+ * Aplica todos os patches registrados no mapa de substituições.
511
+ * @throws {Error} Se `init()` não tiver sido chamado antes
512
+ */
513
+ static patchAll(): void;
514
+ /**
515
+ * Restaura todos os métodos do widget para as implementações originais.
516
+ *
517
+ * Deve ser chamado ao desmontar o componente em SPAs, para evitar que os patches
518
+ * persistam além do ciclo de vida do formulário. Também zera os flags de estado
519
+ * interno, permitindo reinicialização via `init()`.
520
+ *
521
+ * @example
522
+ * ```typescript
523
+ * // Ao desmontar o formulário
524
+ * WorkflowViewPatcher.restore()
525
+ * ```
526
+ */
527
+ static restore(): void;
528
+ /**
529
+ * Acessa a lista interna de hooks para um tipo específico.
530
+ * Usado por `sendRequestEvent` para executar os hooks em sequência.
531
+ *
532
+ * @internal
533
+ */
534
+ static getHooks<K extends keyof HooksMap>(key: K): HooksMap[K];
535
+ /**
536
+ * Registra uma função executada ANTES da validação principal do widget.
537
+ *
538
+ * Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
539
+ * Se o handler lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
540
+ *
541
+ * @param fn - Função a ser executada (pode ser async).
542
+ *
543
+ * @example
544
+ * ```typescript
545
+ * WorkflowViewPatcher.addBeforeValidate(async () => {
546
+ * const value = getValue('campo_obrigatorio')
547
+ * if (!value) {
548
+ * throw new Error('Campo obrigatório não preenchido')
549
+ * }
550
+ * })
551
+ * ```
552
+ */
553
+ static addBeforeValidate(fn: () => void | Promise<void>): void;
554
+ /**
555
+ * Registra uma função executada APÓS `beforeSendValidate` retornar `true`,
556
+ * mas ANTES do envio efetivo da solicitação.
557
+ *
558
+ * Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
559
+ * Se o handler lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
560
+ *
561
+ * @param fn - Função a ser executada (pode ser async).
562
+ *
563
+ * @example
564
+ * ```typescript
565
+ * WorkflowViewPatcher.addAfterValidate(async () => {
566
+ * console.log('Validação concluída, preparando envio...')
567
+ * await salvarDadosLocais()
568
+ * })
569
+ * ```
570
+ */
571
+ static addAfterValidate(fn: () => void | Promise<void>): void;
572
+ /**
573
+ * Registra uma função executada quando a movimentação do processo é concluída com sucesso.
574
+ *
575
+ * Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
576
+ *
577
+ * @param fn - Função callback executada em caso de sucesso (pode ser async).
578
+ *
579
+ * @example
580
+ * ```typescript
581
+ * WorkflowViewPatcher.addOnMoveSuccess(() => {
582
+ * console.log('Processo movimentado com sucesso')
583
+ * })
584
+ * ```
585
+ */
586
+ static addOnMoveSuccess(fn: () => void | Promise<void>): void;
587
+ /**
588
+ * Registra uma função executada quando ocorre erro na movimentação do processo.
589
+ *
590
+ * Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
591
+ *
592
+ * @param fn - Função callback executada em caso de erro (pode ser async).
593
+ *
594
+ * @example
595
+ * ```typescript
596
+ * WorkflowViewPatcher.addOnMoveError(() => {
597
+ * console.error('Erro ao movimentar processo')
598
+ * })
599
+ * ```
600
+ */
601
+ static addOnMoveError(fn: () => void | Promise<void>): void;
602
+ /**
603
+ * Registra uma função para manipular os links da página de conclusão da movimentação.
604
+ *
605
+ * Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
606
+ *
607
+ * @param fn - Função que recebe o objeto de conclusão e pode adicionar ou modificar links (pode ser async).
608
+ *
609
+ * @example
610
+ * ```typescript
611
+ * WorkflowViewPatcher.addOnCompletionLinkAdd((message: ProcessCompletionMessage) => {
612
+ * message.links.push({ description: 'Voltar ao início', href: '/inicio' })
613
+ * })
614
+ * ```
615
+ */
616
+ static addOnCompletionLinkAdd(fn: (message: ProcessCompletionMessage) => void | Promise<void>): void;
617
+ }
618
+
619
+ /**
620
+ * Contrato agnóstico ao EGD para acesso a dados do formulário e tabelas filhas.
621
+ * Implementado por `BpmFormRepository` (produção) e `MockFormRepository` (testes).
622
+ *
623
+ * **Convenção de nomenclatura:** campos do formulário devem seguir `{domínio}_{atributo_snake_case}`.
624
+ * `load` e `save` gerenciam a conversão entre nome DOM e atributo do modelo automaticamente.
625
+ */
626
+ interface IFormRepository {
627
+ /**
628
+ * Lê campos do formulário cujo `name` começa com `{section}_`.
629
+ *
630
+ * O prefixo `{section}_` é removido e o restante convertido de `snake_case` para `camelCase`
631
+ * antes de retornar — o modelo recebe atributos limpos, sem o prefixo de domínio.
632
+ *
633
+ * @param section Prefixo de domínio dos campos no formulário (ex: `'contrato'`, `'imovel'`)
634
+ * @returns Objeto parcial com os valores lidos, chaves em camelCase
635
+ *
636
+ * @example
637
+ * ```typescript
638
+ * // DOM: input[name="contrato_indice"], input[name="contrato_primeiro_pagamento"]
639
+ * const data = repository.load<Contrato>('contrato')
640
+ * // data.indice, data.primeiroPagamento
641
+ * ```
642
+ */
643
+ load<T>(section: string): Partial<T>;
644
+ /**
645
+ * Lê todas as linhas visíveis de uma tabela filha do formulário.
646
+ * Cada linha corresponde a um `<tr>` visível da tabela com o `tablename` informado.
647
+ *
648
+ * @param tableName Valor do atributo `tablename` na `<table>` do formulário BPM
649
+ * @returns Array de objetos com os valores dos campos de cada linha
650
+ */
651
+ loadTable<T>(tableName: string): T[];
652
+ /**
653
+ * Escreve valores no DOM do formulário para os campos do domínio informado.
654
+ *
655
+ * Converte cada chave camelCase do modelo para `{section}_{snake_case}` antes de
656
+ * escrever — espelha exatamente o que `load` desfaz.
657
+ *
658
+ * @param section Prefixo de domínio dos campos (ex: `'contrato'`, `'imovel'`)
659
+ * @param data Objeto com os valores a persistir (chaves em camelCase)
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * // Escreve input[name="contrato_indice"] e input[name="contrato_primeiro_pagamento"]
664
+ * repository.save<Contrato>('contrato', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
665
+ * ```
666
+ */
667
+ save<T>(section: string, data: Partial<T>): void;
668
+ /**
669
+ * Substitui as linhas de uma tabela filha, removendo as existentes e
670
+ * recriando via `wdkAddChild`. Encapsula toda a interação com o DOM.
671
+ *
672
+ * @param tableName Valor do atributo `tablename` na `<table>` do formulário BPM
673
+ * @param rows Array de objetos a persistir como linhas da tabela
674
+ */
675
+ saveTable<T>(tableName: string, rows: T[]): void;
676
+ }
677
+
678
+ /**
679
+ * Adapter de produção que isola o acesso ao DOM do formulário BPM e às
680
+ * funções globais `wdkAddChild`/`fnWdkRemoveChild` (definidas em `wdkdetail.js`).
681
+ *
682
+ * Segue o mesmo padrão de fronteira estabelecido por `process-context/` —
683
+ * este é o único arquivo autorizado a referenciar as globais do formulário BPM.
684
+ */
685
+ declare class BpmFormRepository implements IFormRepository {
686
+ load<T>(section: string): Partial<T>;
687
+ loadTable<T>(tableName: string): T[];
688
+ save<T>(section: string, data: Partial<T>): void;
689
+ saveTable<T>(tableName: string, rows: T[]): void;
690
+ }
691
+
692
+ /**
693
+ * Implementação em memória de `IFormRepository` para uso em testes unitários.
694
+ * Não depende de DOM, jQuery ou da plataforma — permite testar Presenters em isolamento.
695
+ *
696
+ * Aplica a mesma lógica de prefixo e conversão de `BpmFormRepository`: armazena
697
+ * internamente com o nome DOM completo (`{section}_{snake_case}`) e converte para
698
+ * camelCase ao retornar — garantindo que os testes reflitam o comportamento real.
699
+ *
700
+ * @example
701
+ * const repo = new MockFormRepository()
702
+ * repo.save('vigencia', { prazo: '12', tipoDePrazo: 'Meses' })
703
+ * const data = repo.load<Vigencia>('vigencia')
704
+ * // data.prazo === '12'
705
+ * // data.tipoDePrazo === 'Meses'
706
+ *
707
+ * @example
708
+ * const repo = new MockFormRepository()
709
+ * repo.save('imovel', { cep: '01310100', logradouro: 'Av. Paulista' })
710
+ * repo.save('contrato', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
711
+ * // imovel_cep e contrato_indice são domínios distintos — sem colisão
712
+ */
713
+ declare class MockFormRepository implements IFormRepository {
714
+ /** Armazena valores com chave no formato DOM completo: `{section}_{snake_case}`. */
715
+ private readonly store;
716
+ private readonly tables;
717
+ load<T>(section: string): Partial<T>;
718
+ loadTable<T>(tableName: string): T[];
719
+ save<T>(section: string, data: Partial<T>): void;
720
+ saveTable<T>(tableName: string, rows: T[]): void;
721
+ /**
722
+ * Limpa todo o estado interno — campos e tabelas.
723
+ * Ideal para uso em `beforeEach` nos testes.
724
+ */
725
+ reset(): void;
726
+ }
727
+
728
+ /**
729
+ * Lê campos do formulário por mapeamento explícito `{ propriedadeModelo: nomeDOM }`.
730
+ *
731
+ * Utilitário para **processos legados** cujos campos não seguem a convenção
732
+ * `{domínio}_{atributo}` — use quando o nome DOM não pode ser alterado sem
733
+ * migração de dados no banco EGD.
734
+ *
735
+ * Novos processos devem usar `IFormRepository.load(section)` diretamente.
736
+ *
737
+ * @param fieldMap Mapeamento de propriedade do modelo → nome do campo no DOM
738
+ * @returns Objeto parcial com os valores lidos, chaveado pelos atributos do modelo
739
+ *
740
+ * @example
741
+ * ```typescript
742
+ * // Processo legado: campos com sufixo em vez de prefixo
743
+ * import { loadFields } from 'jsegd-bpm'
744
+ *
745
+ * interface Solicitante {
746
+ * nome: string
747
+ * email: string
748
+ * }
749
+ *
750
+ * const dados = loadFields<Solicitante>({
751
+ * nome: 'nome_solicitante',
752
+ * email: 'email_solicitante',
753
+ * })
754
+ * // dados.nome === valor de input[name="nome_solicitante"]
755
+ * ```
756
+ */
757
+ declare function loadFields<T>(fieldMap: {
758
+ [K in keyof T]?: string;
759
+ }): Partial<T>;
760
+
761
+ /** Categoria de uma atividade — determina o comportamento na barra de progresso */
762
+ type ActivityKind =
763
+ /** Ação de usuário — estágio atual destacado na barra */
764
+ 'human'
765
+ /** Aguardando retorno externo (webhook) — exibe spinner no estágio atual */
766
+ | 'system'
767
+ /** Suporte transversal — sobrepõe banner de alerta; não avança a barra */
768
+ | 'support'
769
+ /** Roteamento interno do motor BPM — invisível na barra */
770
+ | 'routing';
771
+ /** Definição de um módulo (aba/seção) do formulário BPM */
772
+ interface WorkflowModuleDefinition {
773
+ /** Identificador único do módulo — usado como chave nas políticas de atividade */
774
+ moduleId: string;
775
+ /** Rótulo exibido na navegação */
776
+ label: string;
777
+ /** Nome do ícone exibido junto ao rótulo */
778
+ icon: string;
779
+ /** Posição na ordem de exibição — menor valor aparece primeiro */
780
+ order: number;
781
+ /** Exibe o módulo na barra de navegação lateral/superior */
782
+ showInNavigation: boolean;
783
+ /** Renderiza o conteúdo do módulo no DOM quando visível */
784
+ renderContent: boolean;
785
+ /** Caminho do arquivo HTML incluído como conteúdo do módulo */
786
+ contentIncludePath: string;
787
+ }
788
+ /**
789
+ * Políticas de visibilidade e editabilidade dos módulos para uma atividade.
790
+ * `TModuleId` é inferido automaticamente por `defineWorkflowConfig`.
791
+ */
792
+ interface ActivityModulePolicy<TModuleId extends string = string> {
793
+ /** Módulos visíveis nesta atividade */
794
+ visible: readonly TModuleId[];
795
+ /** Módulos editáveis nesta atividade (subconjunto de `visible`) */
796
+ editable: readonly TModuleId[];
797
+ /** Módulo ativo (tab selecionada) ao abrir o formulário nesta atividade */
798
+ active?: TModuleId;
799
+ }
800
+ /** Definição de uma atividade do workflow com suas políticas de módulo */
801
+ interface WorkflowActivityDefinition<TModuleId extends string = string> {
802
+ /** Número de sequência da atividade no motor BPM EGD */
803
+ sequence: number;
804
+ /** Descrição legível da atividade para fins de diagnóstico */
805
+ description: string;
806
+ /** Categoria da atividade — controla comportamento na barra de progresso */
807
+ kind: ActivityKind;
808
+ /**
809
+ * Estágio de negócio representado por esta atividade na barra de progresso.
810
+ * Obrigatório para `'human'` e `'system'`. Omitido para `'routing'`.
811
+ * Para `'support'`: identifica o estágio que está sendo interrompido.
812
+ */
813
+ stage?: string;
814
+ /** Políticas de visibilidade e editabilidade dos módulos */
815
+ modules?: ActivityModulePolicy<TModuleId>;
816
+ }
817
+ /**
818
+ * Configuração tipada de um workflow BPM — retornada por `defineWorkflowConfig`.
819
+ * `TModuleId` é inferido automaticamente do array de módulos.
820
+ */
821
+ interface WorkflowConfig<TModules extends readonly WorkflowModuleDefinition[], TModuleId extends string = TModules[number]['moduleId']> {
822
+ readonly modules: TModules;
823
+ readonly activities: readonly WorkflowActivityDefinition<TModuleId>[];
824
+ }
825
+
826
+ /**
827
+ * Define a configuração de workflow de um projeto BPM a partir de uma
828
+ * declaração única de módulos e atividades. O tipo `ModuleId` é inferido
829
+ * automaticamente do array de módulos — nenhum type alias manual é necessário.
830
+ *
831
+ * @param config Objeto com `modules` (definições de módulo) e `activities` (políticas por atividade)
832
+ * @returns Configuração tipada pronta para uso em `resolveWorkflowScreen` e `extractCompletedStages`
833
+ *
834
+ * @example
835
+ * const workflowConfig = defineWorkflowConfig({
836
+ * modules: [
837
+ * { moduleId: 'solicitante', label: 'Dados Iniciais', icon: 'file', order: 1,
838
+ * showInNavigation: true, renderContent: true, contentIncludePath: 'solicitante.html' },
839
+ * { moduleId: 'juridico', label: 'Jurídico', icon: 'gavel', order: 2,
840
+ * showInNavigation: true, renderContent: true, contentIncludePath: 'juridico.html' },
841
+ * ],
842
+ * activities: [
843
+ * { sequence: 9, description: 'Solicitação inicial', kind: 'human', stage: 'solicitacao',
844
+ * modules: { visible: ['solicitante'], editable: ['solicitante'], active: 'solicitante' } },
845
+ * { sequence: 88, description: 'Roteamento', kind: 'routing' },
846
+ * ]
847
+ * } as const)
848
+ * // Tipo de ModuleId inferido automaticamente: 'solicitante' | 'juridico'
849
+ */
850
+ declare function defineWorkflowConfig<const M extends readonly (WorkflowModuleDefinition & {
851
+ moduleId: string;
852
+ })[]>(config: {
853
+ modules: M;
854
+ activities: readonly WorkflowActivityDefinition<M[number]['moduleId']>[];
855
+ }): WorkflowConfig<M, M[number]['moduleId']>;
856
+
857
+ /**
858
+ * Entrada do histórico do processo BPM retornada por
859
+ * `parent.ECM.workflowView.processDefinition.urlHistory`.
860
+ * As chaves do objeto pai são arbitrárias — usar apenas `movementDate` e
861
+ * `movementHour` para determinar a ordem cronológica real.
862
+ */
863
+ interface BpmHistoryEntry {
864
+ /** `null` = ação de usuário; `'SYSTEM'` = tarefa de sistema; `'OBSERVATION'`/`'ATTACHMENT'` = ignorar */
865
+ historyType: 'SYSTEM' | 'OBSERVATION' | 'ATTACHMENT' | null;
866
+ /** Equivalente a `WorkflowActivityDefinition.sequence` */
867
+ stateSequence: number;
868
+ /** `0` = atividade de usuário/sistema | `1` = gateway/decisão automática */
869
+ stateType: number;
870
+ /** Timestamp numérico para ordenação — `null` em sub-registros sem posição cronológica */
871
+ movementDate: number | null;
872
+ /** Hora no formato `"HH:mm:ss"` — desempate na ordenação quando `movementDate` é igual */
873
+ movementHour: string | null;
874
+ /** Rótulo da atividade no motor BPM */
875
+ labelActivity: string | null;
876
+ }
877
+ /** Mapa bruto retornado por `urlHistory` — chaves são arbitrárias, ignorar na ordenação */
878
+ type BpmHistoryMap = Record<string, BpmHistoryEntry>;
879
+ /** Histórico processado — alimenta `ScreenContext` para construir a barra de progresso */
880
+ interface ProcessHistory {
881
+ /** Estágios concluídos em ordem cronológica real; deduplica estágios repetidos */
882
+ completedStages: string[];
883
+ /** Estágio atual com seu status; `null` se a atividade atual não tiver stage mapeado */
884
+ currentStage: {
885
+ stage: string;
886
+ status: 'current' | 'waiting';
887
+ } | null;
888
+ }
889
+ /**
890
+ * Extrai os estágios concluídos do histórico BPM na ordem cronológica real.
891
+ * Ignora gateways (`stateType === 1`), entradas `SYSTEM`, `OBSERVATION` e `ATTACHMENT`,
892
+ * e sub-registros sem `movementDate`. Deduplica estágios — a primeira ocorrência
893
+ * cronológica define a posição na barra de progresso.
894
+ *
895
+ * @param history Mapa bruto retornado por `urlHistory` do processo BPM
896
+ * @param activities Array de definições de atividade do `WorkflowConfig`
897
+ * @returns Array de stage IDs na ordem em que ocorreram no processo
898
+ */
899
+ declare function extractCompletedStages(history: BpmHistoryMap, activities: readonly WorkflowActivityDefinition[]): string[];
900
+ /**
901
+ * Determina o estágio atual e seu status (`'current'` ou `'waiting'`).
902
+ * Retorna `null` se a sequência atual não tiver um `stage` mapeado na configuração.
903
+ *
904
+ * @param currentSequence Número de sequência da atividade atual do processo
905
+ * @param currentHistoryType `historyType` da entrada atual — `null` para ação humana, `'SYSTEM'` para espera
906
+ * @param activities Array de definições de atividade do `WorkflowConfig`
907
+ * @returns Objeto com `stage` e `status`, ou `null`
908
+ */
909
+ declare function extractCurrentStage(currentSequence: number, currentHistoryType: 'SYSTEM' | null, activities: readonly WorkflowActivityDefinition[]): {
910
+ stage: string;
911
+ status: 'current' | 'waiting';
912
+ } | null;
913
+
914
+ /** Módulo com políticas de visibilidade e editabilidade resolvidas para a atividade atual */
915
+ interface ResolvedModule {
916
+ moduleId: string;
917
+ label: string;
918
+ icon: string;
919
+ order: number;
920
+ showInNavigation: boolean;
921
+ renderContent: boolean;
922
+ contentIncludePath: string;
923
+ isVisible: boolean;
924
+ isEditable: boolean;
925
+ isActive: boolean;
926
+ }
927
+ /**
928
+ * Contexto de tela para uma atividade de workflow.
929
+ * Consultado por Presenters para decidir visibilidade/editabilidade
930
+ * sem conhecer números de sequência.
931
+ *
932
+ * @hideconstructor
933
+ */
934
+ declare class ScreenContext {
935
+ private readonly activity;
936
+ private readonly resolvedModules;
937
+ private readonly history;
938
+ constructor(activity: WorkflowActivityDefinition, resolvedModules: readonly ResolvedModule[], history: ProcessHistory);
939
+ /**
940
+ * Retorna `true` se o módulo é visível na atividade atual.
941
+ *
942
+ * @param moduleId Identificador do módulo
943
+ */
944
+ isVisible(moduleId: string): boolean;
945
+ /**
946
+ * Retorna `true` se o módulo é editável na atividade atual.
947
+ *
948
+ * @param moduleId Identificador do módulo
949
+ */
950
+ isEditable(moduleId: string): boolean;
951
+ /**
952
+ * Retorna `true` se o módulo é o ativo (tab selecionada) na atividade atual.
953
+ *
954
+ * @param moduleId Identificador do módulo
955
+ */
956
+ isActive(moduleId: string): boolean;
957
+ /**
958
+ * Retorna o número de sequência da atividade atual no motor BPM EGD.
959
+ *
960
+ * Equivalente a `WorkflowActivityDefinition.sequence`. Exposto para presenters
961
+ * que precisam do valor em regras de domínio baseadas em sequências específicas
962
+ * (ex: listas de sequences especiais para exibir/ocultar campos).
963
+ */
964
+ getSequence(): number;
965
+ /**
966
+ * Retorna `true` se a atividade atual está aguardando um sistema externo
967
+ * (`kind === 'system'` ou `currentStage.status === 'waiting'`).
968
+ */
969
+ isAwaitingSystem(): boolean;
970
+ /**
971
+ * Retorna `true` se a atividade atual é uma atividade de suporte transversal.
972
+ */
973
+ isInSupport(): boolean;
974
+ /**
975
+ * Retorna os estágios para renderizar na barra de progresso.
976
+ * Inclui os estágios concluídos do histórico (`'done'`) e o estágio atual
977
+ * (`'current'` ou `'waiting'`), sem duplicar.
978
+ */
979
+ getProgressBarStages(): Array<{
980
+ stage: string;
981
+ status: 'done' | 'current' | 'waiting';
982
+ }>;
983
+ /**
984
+ * Retorna todos os módulos resolvidos, incluindo os não-visíveis.
985
+ */
986
+ getModules(): readonly ResolvedModule[];
987
+ /**
988
+ * Retorna apenas os módulos visíveis, ordenados por `order` ascendente.
989
+ */
990
+ getVisibleModules(): readonly ResolvedModule[];
991
+ /**
992
+ * Retorna os módulos que aparecem na navegação (`showInNavigation && isVisible`),
993
+ * ordenados por `order` ascendente.
994
+ */
995
+ getNavigationModules(): readonly ResolvedModule[];
996
+ }
997
+
998
+ /**
999
+ * Resolve a tela para a sequência informada, cruzando a configuração do workflow
1000
+ * com o histórico do processo para produzir um `ScreenContext`.
1001
+ *
1002
+ * @param config Configuração gerada por `defineWorkflowConfig`
1003
+ * @param sequence Número de sequência da atividade atual no processo BPM
1004
+ * @param history Histórico processado via `extractCompletedStages` e `extractCurrentStage`
1005
+ * @returns `ScreenContext` pronto para consulta pelos Presenters
1006
+ *
1007
+ * @throws {Error} Se a sequência não estiver mapeada na configuração
1008
+ *
1009
+ * @example
1010
+ * const screen = resolveWorkflowScreen(workflowConfig, 53, processHistory)
1011
+ * screen.isVisible('juridico') // true
1012
+ * screen.isEditable('juridico') // true
1013
+ * screen.isInSupport() // false
1014
+ */
1015
+ declare function resolveWorkflowScreen(config: WorkflowConfig<readonly WorkflowModuleDefinition[]>, sequence: number, history: ProcessHistory): ScreenContext;
1016
+
1017
+ /** Mapa de stores: chave = nome do store, valor = objeto do store */
1018
+ type StoreMap = Record<string, object>;
1019
+ /**
1020
+ * Tipo utilitário que gera um proxy com getters tipados para cada store registrado.
1021
+ * Permite `stores.contador` ao invés de `Alpine.store('contador') as ContadorStore`.
1022
+ */
1023
+ type StoreProxy<T extends StoreMap> = {
1024
+ readonly [K in keyof T]: T[K];
1025
+ };
1026
+ /**
1027
+ * Registra múltiplos Alpine stores e retorna um proxy tipado para acesso direto.
1028
+ * Deve ser chamado no ponto de inicialização da aplicação, antes de `Alpine.start()`.
1029
+ *
1030
+ * @param alpine Instância Alpine — aceita `Pick<Alpine, 'store'>` para facilitar mock em testes
1031
+ * @param storeMap Objeto com pares `{ nomeDoStore: objetoInicial }`
1032
+ * @returns Proxy tipado para leitura dos stores sem casting manual
1033
+ *
1034
+ * @example
1035
+ * const stores = registerStores(Alpine, {
1036
+ * usuario: { nome: '', perfil: '' as PerfilId },
1037
+ * ui: { carregando: false, erro: null as string | null }
1038
+ * })
1039
+ * // stores.usuario.nome está tipado como string
1040
+ * // Internamente: Alpine.store('usuario', { nome: '', perfil: '' })
1041
+ */
1042
+ declare function registerStores<T extends StoreMap>(alpine: Pick<Alpine, 'store'>, storeMap: T): StoreProxy<T>;
1043
+
1044
+ export { Attach, AttachButton, AttachmentsTable, BeforeSendValidate, BpmFormRepository, ConstraintsType, MockFormRepository, ScreenContext, WorkerManager, WorkflowViewPatcher, defineWorkflowConfig, extractCompletedStages, extractCurrentStage, loadFields, registerStores, resolveWorkflowScreen, sendRequestEvent };
1045
+ export type { ActivityKind, ActivityModulePolicy, AttachButtonRegistration, AttachmentRecord, AttachmentSource, AttachmentsTableMode, AttachmentsTableOptions, BpmHistoryEntry, BpmHistoryMap, CacheOptions, CancelablePromise, DatasetError, DatasetResponse, DatasetRow, DragDropEntry, FieldError, IFormRepository, IWorkflowViewHooks, ProcessCompletionLink, ProcessCompletionMessage, ProcessHistory, ResolvedModule, SearchParams, StoreMap, StoreProxy, WorkerManagerOptions, WorkflowActivityDefinition, WorkflowConfig, WorkflowModuleDefinition };