@lexnode/legal-data-sdk 1.26.0 → 1.28.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/README.md +194 -24
- package/dist/client.d.ts +16 -2
- package/dist/client.js +38 -9
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +2 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1 -0
- package/dist/lookup.d.ts +79 -0
- package/dist/lookup.js +158 -0
- package/dist/webhooks.d.ts +144 -4
- package/dist/webhooks.js +2 -0
- package/package.json +1 -1
- package/schema.d.ts +3263 -19
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@ await lexnode.publications.list({ oabNumber: "123456", oabState: "SP" });
|
|
|
73
73
|
await lexnode.monitors.create({ type: "OAB", oabNumber: "123456", oabState: "SP" });
|
|
74
74
|
await lexnode.subscriptions.create({ tribunalAlias, processNumber, externalRef });
|
|
75
75
|
await lexnode.searchJobs.get(jobId);
|
|
76
|
+
await lexnode.processLookups.get(lookupId);
|
|
76
77
|
await lexnode.events.list({ limit: 50 });
|
|
77
78
|
await lexnode.webhooks.endpoints.list();
|
|
78
79
|
await lexnode.webhooks.unsubscribedEventTypes();
|
|
@@ -194,12 +195,24 @@ switch (resultado.event.type) {
|
|
|
194
195
|
break;
|
|
195
196
|
case "PROCESS_MOVEMENT_CREATED":
|
|
196
197
|
resultado.event.payload.externalRef;
|
|
198
|
+
resultado.event.payload.degree; // o grau do movimento mais recente
|
|
199
|
+
break;
|
|
200
|
+
case "PROCESS_INSTANCE_DISCOVERED":
|
|
201
|
+
// Outro grau do processo apareceu na fonte; o histórico dele está no
|
|
202
|
+
// retrato, em `instances`. O processo retido vem sem o grau.
|
|
203
|
+
if (!resultado.event.payload.contentWithheld) {
|
|
204
|
+
resultado.event.payload.degree;
|
|
205
|
+
}
|
|
197
206
|
break;
|
|
198
207
|
case "SEARCH_JOB_COMPLETED":
|
|
199
208
|
if (resultado.event.payload.status === "FAILED") {
|
|
200
209
|
resultado.event.payload.error.code;
|
|
201
210
|
}
|
|
202
211
|
break;
|
|
212
|
+
case "PROCESS_LOOKUP_COMPLETED":
|
|
213
|
+
// Um ponteiro: o processo se lê em payload.pollUrl, sem nova cobrança.
|
|
214
|
+
resultado.event.payload.lookupId;
|
|
215
|
+
break;
|
|
203
216
|
case "WEBHOOK_TEST":
|
|
204
217
|
// A entrega de teste do console. Chega a qualquer endpoint, não se assina
|
|
205
218
|
// e não se recusa — é ela que valida o receptor antes do primeiro evento.
|
|
@@ -256,6 +269,94 @@ if (desfecho.kind === "sync") {
|
|
|
256
269
|
}
|
|
257
270
|
```
|
|
258
271
|
|
|
272
|
+
## Um número, várias instâncias
|
|
273
|
+
|
|
274
|
+
A fonte processual guarda um documento por instância do processo — 1º grau, 2º
|
|
275
|
+
grau, turma recursal… —, às vezes dois do mesmo grau, e o motor guarda cada um
|
|
276
|
+
na sua instância.
|
|
277
|
+
|
|
278
|
+
**O topo não troca.** O topo da ficha (`data`) e do retrato (`data.process` e
|
|
279
|
+
`data.movements`) é sempre a instância principal do número, com o grau em
|
|
280
|
+
`degree`: a mesma de uma leitura para a outra, qualquer que seja a ordem em que
|
|
281
|
+
a fonte devolve os documentos. Ela só muda quando uma resposta completa da
|
|
282
|
+
fonte pelo número deixa de trazê-la. Quem compara movimentos pela chave não vê
|
|
283
|
+
o histórico de outro grau aparecer como novo no topo — e o topo pode não ser o
|
|
284
|
+
grau que anda: o 2º grau guardado primeiro continua no topo enquanto o 1º se
|
|
285
|
+
move.
|
|
286
|
+
|
|
287
|
+
**Todos os graus em `instances`.** A ficha e o retrato listam em `instances`
|
|
288
|
+
todos os documentos que o motor guarda do número, a principal primeiro
|
|
289
|
+
(`primary: true`). Cada um diz de onde veio nesta resposta (`origin`: `SOURCE`
|
|
290
|
+
quando a fonte o trouxe, `LAKE` quando saiu do acervo), quando foi buscado
|
|
291
|
+
(`fetchedAt`) e desde quando a resposta completa da fonte vem sem ele
|
|
292
|
+
(`absentSince`). No retrato, cada instância traz os movimentos da última captura
|
|
293
|
+
dela, do mais recente ao mais antigo e sem o payload bruto da fonte; a que o
|
|
294
|
+
motor nunca capturou vem com `movementsCaptured: false` e `movements` nulo, nunca
|
|
295
|
+
com lista vazia, que diria que o grau não andou. Todos os documentos levam a
|
|
296
|
+
classificação do número inteiro — basta um em segredo de justiça para todos
|
|
297
|
+
saírem marcados —, e a ficha retida pelo controle de confidencialidade sai sem a
|
|
298
|
+
lista.
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
const { data } = await lexnode.processes.snapshot(numero, { tribunalAlias });
|
|
302
|
+
|
|
303
|
+
for (const instancia of data.instances) {
|
|
304
|
+
instancia.degree; // "G1", "G2", "TR"…
|
|
305
|
+
instancia.primary; // true só na do topo
|
|
306
|
+
instancia.movements ?? "movimentos nunca capturados";
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
No lote (`processes.snapshotBatch`), `instances` traz só o cabeçalho de cada
|
|
311
|
+
documento; os movimentos de cada instância vêm no retrato de um processo. A
|
|
312
|
+
busca por número completo servida do acervo devolve um item por documento que a
|
|
313
|
+
fonte ainda traz do número, a principal primeiro; quando eles não cabem em
|
|
314
|
+
`limit`, a busca vai à fonte, que pagina.
|
|
315
|
+
|
|
316
|
+
**Recorte por grau.** A lista de movimentações aceita `degree` e devolve só os
|
|
317
|
+
movimentos que o documento daquele grau trouxe na última captura; cada item diz
|
|
318
|
+
em `degrees` o grau — ou os graus, quando o mesmo ato está nos dois documentos
|
|
319
|
+
— que o trouxe, e vem vazio no movimento que nenhuma captura atual traz.
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
const { data } = await lexnode.processes.movements(numero, {
|
|
323
|
+
tribunalAlias,
|
|
324
|
+
degree: "G1",
|
|
325
|
+
});
|
|
326
|
+
data.items; // só o que o 1º grau trouxe
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**O grau novo chega num evento só.** Quando outro grau de um processo assinado
|
|
330
|
+
aparece na fonte, o histórico dele entra no acervo sem virar
|
|
331
|
+
`PROCESS_MOVEMENT_CREATED` movimento a movimento: chega um
|
|
332
|
+
`PROCESS_INSTANCE_DISCOVERED`, com o grau, o órgão julgador e as contagens —
|
|
333
|
+
`historyMovementCount` entrou sem aviso próprio, `announcedMovementCount` saiu
|
|
334
|
+
também como movimento novo. O `PROCESS_MOVEMENT_CREATED` diz o grau do
|
|
335
|
+
movimento mais recente (`degree`, `instanceSourceId`) e quantos movimentos novos
|
|
336
|
+
vieram de cada grau (`instances`). Assine os dois: quem assina só o movimento
|
|
337
|
+
não fica sabendo do grau que apareceu.
|
|
338
|
+
|
|
339
|
+
**`meta.otherInstances`: o resumo do que veio.** Quando a resposta da fonte traz
|
|
340
|
+
outros documentos do número além da principal, `meta.otherInstances` resume cada
|
|
341
|
+
um com o grau (`grau`), a data em que a fonte o atualizou (`updatedAt`) e o
|
|
342
|
+
órgão julgador (`courtBody`, quando vem). A lista não sai para processo restrito
|
|
343
|
+
e não inclui documento que o motor classificaria como segredo de justiça; os
|
|
344
|
+
documentos inteiros estão em `instances`.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
for (const outra of meta.otherInstances ?? []) {
|
|
348
|
+
// Ex.: { grau: "G1", updatedAt: "2026-04-15T12:00:00.000Z" }
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Continuação.** Na API nada é cortado: o retrato traz os movimentos guardados
|
|
353
|
+
de cada instância, e a lista de movimentações lê do acervo, grau a grau, sem ir
|
|
354
|
+
à fonte. No canal para agentes (MCP), `consultar_processo` cabe no teto de uma
|
|
355
|
+
resposta: de cada grau vêm os movimentos mais recentes, o grau que se moveu por
|
|
356
|
+
último primeiro, e a mesma tool com `grau` e `pagina` traz os seguintes do que o
|
|
357
|
+
motor guardou, por 1 crédito e sem ir à fonte — só para quem já leu o processo
|
|
358
|
+
ou o acompanha.
|
|
359
|
+
|
|
259
360
|
## Ler um processo quando a fonte está lenta
|
|
260
361
|
|
|
261
362
|
A ficha (`processes.get`) vai à fonte processual quando o acervo não tem o
|
|
@@ -290,15 +391,15 @@ ou a vigília do processo (`watchProcess`), que consulta em segundo plano.
|
|
|
290
391
|
responde com só parte do índice e o processo estava na parte que respondeu, ele
|
|
291
392
|
é servido, e `meta.partialIndex` diz quantas partes falharam (`shardsFailed`),
|
|
292
393
|
de quantas (`shardsTotal`, nulo quando a fonte não as contou) e se o prazo
|
|
293
|
-
interno dela estourou (`timedOut`). O
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
394
|
+
interno dela estourou (`timedOut`). O documento que o acervo já guardava e não
|
|
395
|
+
veio sai em `instances` do acervo (`origin: "LAKE"`), com a data dele, e outro
|
|
396
|
+
grau que o acervo não conhece, se existir, pode estar na parte que não
|
|
397
|
+
respondeu. A resposta parcial sem o processo é 502 `UPSTREAM_UNAVAILABLE`
|
|
297
398
|
retentável, nunca 404.
|
|
298
399
|
|
|
299
400
|
```ts
|
|
300
401
|
if (meta.partialIndex) {
|
|
301
|
-
// Outro grau deste número
|
|
402
|
+
// Outro grau deste número que o acervo não conhece pode não ter vindo.
|
|
302
403
|
}
|
|
303
404
|
```
|
|
304
405
|
|
|
@@ -306,21 +407,6 @@ Antes de recusar a resposta parcial que veio sem o processo porque partes do
|
|
|
306
407
|
índice ficaram fora, o motor consulta a fonte de novo — até duas vezes, com uma
|
|
307
408
|
pausa curta, enquanto a espera couber.
|
|
308
409
|
|
|
309
|
-
**`meta.otherInstances`: o número tem outro documento na fonte.** A fonte pode
|
|
310
|
-
guardar mais de um documento por número — em geral um por instância (1º grau,
|
|
311
|
-
2º grau, turma recursal…), às vezes dois no mesmo grau —, e o motor serve e
|
|
312
|
-
guarda um só: o de `data`, cujo grau está em `degree`. Quando a resposta da
|
|
313
|
-
fonte trouxe outros, `meta.otherInstances` lista cada um com o grau (`grau`), a
|
|
314
|
-
data em que a fonte o atualizou (`updatedAt`) e o órgão julgador (`courtBody`,
|
|
315
|
-
quando vem). A lista não sai para processo restrito e não inclui documento que o
|
|
316
|
-
motor classificaria como segredo de justiça.
|
|
317
|
-
|
|
318
|
-
```ts
|
|
319
|
-
for (const outra of meta.otherInstances ?? []) {
|
|
320
|
-
// Ex.: { grau: "G1", updatedAt: "2026-04-15T12:00:00.000Z" }
|
|
321
|
-
}
|
|
322
|
-
```
|
|
323
|
-
|
|
324
410
|
**Agentes têm a espera deles.** No canal para agentes (MCP), as tools
|
|
325
411
|
`ler_processo` e `consultar_processo` escolhem a espera em `maxWaitSeconds`, na
|
|
326
412
|
mesma faixa e com padrão de 120 s; esse canal não passa pelo SDK.
|
|
@@ -345,10 +431,13 @@ vez do erro. A resposta diz que é cópia, e de quando:
|
|
|
345
431
|
|
|
346
432
|
A cópia custa 1 crédito, na ficha e no retrato. O retrato confere o saldo pelo
|
|
347
433
|
preço cheio, 8, antes de ir à fonte; a ficha confere pelo preço do que
|
|
348
|
-
entregou, depois da leitura. No retrato guardado,
|
|
349
|
-
última vez que o motor buscou
|
|
350
|
-
|
|
351
|
-
|
|
434
|
+
entregou, depois da leitura. No retrato guardado, cada instância traz os
|
|
435
|
+
movimentos da última vez que o motor a buscou, com a data em
|
|
436
|
+
`instances[].fetchedAt`, e `sourcePayload` é nulo: o que andou depois dessas
|
|
437
|
+
datas não está na resposta. O número que a resposta completa mais recente da
|
|
438
|
+
fonte já não trazia em documento nenhum não é socorrido. Na ficha guardada, a
|
|
439
|
+
data vale para os dados do processo, e o resumo das publicações (`djen`) é
|
|
440
|
+
relido na hora.
|
|
352
441
|
|
|
353
442
|
**Até que idade.** Sem pedir nada, só a cópia de até 24 h socorre a leitura —
|
|
354
443
|
nessas duas rotas, uma resposta de sucesso já podia ser cópia do acervo dentro
|
|
@@ -387,6 +476,87 @@ ativa —, e os demais recebem a falha da fonte, como se não houvesse cópia.
|
|
|
387
476
|
item socorrido traz `lakeRescue` com a causa e a data, e custa 1 crédito em vez
|
|
388
477
|
de 8.
|
|
389
478
|
|
|
479
|
+
## Leitura que não coube na espera
|
|
480
|
+
|
|
481
|
+
Quando a fonte processual não entrega dentro de `waitSeconds`, a ficha e o
|
|
482
|
+
retrato respondem com o erro dela (ou com a cópia guardada, seção anterior).
|
|
483
|
+
`processLookups.create` faz a MESMA leitura, e o que não coube na espera segue
|
|
484
|
+
em segundo plano em vez de virar erro:
|
|
485
|
+
|
|
486
|
+
- **200**: a leitura coube. `data` é uma consulta `SUCCEEDED` sem consulta
|
|
487
|
+
aberta (`lookupId` nulo) que traz o processo em `process` (visão
|
|
488
|
+
`PROCESS`) ou `snapshot` (visão `SNAPSHOT`), com as instâncias do número em
|
|
489
|
+
`instances`, o mesmo `meta` e o mesmo preço da leitura direta;
|
|
490
|
+
- **202**: a fonte falhou — não respondeu a tempo, ficou indisponível ou pediu
|
|
491
|
+
para esperar —, e o motor abriu uma consulta que tenta sozinha, até 60 s por
|
|
492
|
+
tentativa, por até 6 h (`giveUpAt`). Nada é cobrado na hora: o preço da
|
|
493
|
+
leitura fica retido em `creditsReserved`, o máximo que a entrega cobra, e
|
|
494
|
+
só é cobrado se o processo vier. Se não vier, a retenção volta;
|
|
495
|
+
- qualquer outra recusa é a da leitura direta: 404 quando a fonte diz não ter o
|
|
496
|
+
processo, 403 no segredo de justiça, 402 sem saldo.
|
|
497
|
+
|
|
498
|
+
`lookupProcess` diz, no tipo, qual dos dois desfechos aconteceu, e
|
|
499
|
+
`waitForProcessLookup` espera a consulta terminar:
|
|
500
|
+
|
|
501
|
+
```ts
|
|
502
|
+
import { lookupProcess, waitForProcessLookup } from "@lexnode/legal-data-sdk";
|
|
503
|
+
|
|
504
|
+
const desfecho = await lookupProcess(lexnode, {
|
|
505
|
+
tribunalAlias: "api_publica_tjsp",
|
|
506
|
+
processNumber: numero,
|
|
507
|
+
view: "SNAPSHOT",
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
if (desfecho.kind === "ready") {
|
|
511
|
+
desfecho.data.movements; // o retrato, como processes.snapshot o devolveria
|
|
512
|
+
} else {
|
|
513
|
+
// O orçamento é explícito. A leitura seguinte só acontece na hora da
|
|
514
|
+
// próxima tentativa (nextAttemptAt): antes dela, o estado não muda. Com
|
|
515
|
+
// uma tentativa em curso, a consulta é lida de novo a cada 10 s.
|
|
516
|
+
const consulta = await waitForProcessLookup(
|
|
517
|
+
lexnode,
|
|
518
|
+
desfecho.lookup.lookupId!,
|
|
519
|
+
{ budgetMs: 10 * 60_000 },
|
|
520
|
+
);
|
|
521
|
+
if (consulta.status === "SUCCEEDED" && consulta.snapshot) {
|
|
522
|
+
consulta.snapshot.movements;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
**Repetir é seguro.** A mesma leitura pedida de novo — mesma conta,
|
|
528
|
+
escritório, processo e visão — devolve a mesma consulta (`deduped: true`), sem
|
|
529
|
+
nova retenção; por isso `processLookups.create` entra na política de
|
|
530
|
+
retentativa como uma leitura. Quando a próxima tentativa agendada está longe, a
|
|
531
|
+
chamada repetida tenta a fonte na hora, dentro da espera dela. O tempo
|
|
532
|
+
esgotado da fonte continua sem repetição automática.
|
|
533
|
+
|
|
534
|
+
**A consulta se lê de graça, por 24 h.** `processLookups.get(lookupId)` custa 0
|
|
535
|
+
e, depois da entrega, traz o processo por 24 h (`resultExpiresAt`), relido do
|
|
536
|
+
acervo e passado de novo pelo controle de confidencialidade: o processo que
|
|
537
|
+
passou a segredo de justiça depois responde 403. O retrato lido da consulta
|
|
538
|
+
traz a instância principal no topo e cada instância com os movimentos da
|
|
539
|
+
última captura dela, e `sourcePayload` é nulo. `processLookups.list` e `processLookups.cancel`
|
|
540
|
+
completam a superfície; o cancelamento devolve a retenção e não gera evento.
|
|
541
|
+
|
|
542
|
+
**Por webhook, sem esperar nada.** O fim sai em `PROCESS_LOOKUP_COMPLETED`, um
|
|
543
|
+
ponteiro para a consulta que nunca traz o processo; o movimento novo que a
|
|
544
|
+
entrega trouxer chega no `PROCESS_MOVEMENT_CREATED` de sempre.
|
|
545
|
+
|
|
546
|
+
**A cópia guardada e a atualização, uma compra só.** Com `staleOnFailure: true`,
|
|
547
|
+
o 202 traz em `stale` a cópia que o acervo guarda, com a data e a causa, por 1
|
|
548
|
+
crédito, e a consulta segue buscando a versão atual. A entrega cobra só o resto
|
|
549
|
+
do preço (`alreadyCharged` diz quanto já foi): as duas juntas custam o mesmo que
|
|
550
|
+
a leitura direta, e a atualização que não vier não cobra mais nada.
|
|
551
|
+
|
|
552
|
+
**A leitura direta fecha a consulta.** A ficha ou o retrato do mesmo processo
|
|
553
|
+
lidos com sucesso por `processes.get` ou `processes.snapshot` fecham a consulta
|
|
554
|
+
aberta sem cobrar — a leitura já cobrou.
|
|
555
|
+
|
|
556
|
+
**Tetos.** Até 5 consultas abertas por chave e 20 por conta; além disso, a
|
|
557
|
+
falha da fonte volta como a leitura direta a daria. A chave de teste nunca abre
|
|
558
|
+
consulta.
|
|
559
|
+
|
|
390
560
|
## Frescor: o `total: 0` qualificado
|
|
391
561
|
|
|
392
562
|
Um resultado vazio não distingue sozinho "não existe" de "a fonte ainda não
|
package/dist/client.d.ts
CHANGED
|
@@ -12,8 +12,9 @@ export interface LexNodeClientOptions {
|
|
|
12
12
|
officeId?: string;
|
|
13
13
|
/**
|
|
14
14
|
* Prazo de cada chamada, em ms. Padrão: 30 s. A ficha e o retrato de um
|
|
15
|
-
* processo
|
|
16
|
-
* `waitSeconds`, ou o padrão de 20 s
|
|
15
|
+
* processo, e a leitura que segue em segundo plano, levam o maior entre este
|
|
16
|
+
* prazo e a espera pela fonte mais 15 s — `waitSeconds`, ou o padrão de 20 s
|
|
17
|
+
* da API quando ele falta.
|
|
17
18
|
*/
|
|
18
19
|
timeoutMs?: number;
|
|
19
20
|
/** Transporte alternativo — o `fetch` global é o padrão. */
|
|
@@ -71,6 +72,19 @@ export declare function createLexNodeClient(options: LexNodeClientOptions): {
|
|
|
71
72
|
list: (query?: Query<"/v1/subscriptions", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/subscriptions", "get">>;
|
|
72
73
|
delete: (body: Body<"/v1/subscriptions", "delete">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/subscriptions", "delete">>;
|
|
73
74
|
};
|
|
75
|
+
processLookups: {
|
|
76
|
+
/**
|
|
77
|
+
* A leitura de UM processo que segue em segundo plano quando a fonte não
|
|
78
|
+
* entrega dentro de `waitSeconds`: 200 com o processo, ou 202 com a
|
|
79
|
+
* consulta aberta. Repetir é seguro — o motor devolve a consulta já
|
|
80
|
+
* aberta da mesma leitura em vez de abrir outra —, então a retentativa
|
|
81
|
+
* vale para ela como para uma leitura.
|
|
82
|
+
*/
|
|
83
|
+
create: (body: Body<"/v1/processes/lookups", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups", "post">>;
|
|
84
|
+
get: (lookupId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups/{lookupId}", "get">>;
|
|
85
|
+
list: (query?: Query<"/v1/processes/lookups", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups", "get">>;
|
|
86
|
+
cancel: (lookupId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups/{lookupId}/cancel", "post">>;
|
|
87
|
+
};
|
|
74
88
|
searchJobs: {
|
|
75
89
|
get: (jobId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/search-jobs/{jobId}", "get">>;
|
|
76
90
|
list: (query?: Query<"/v1/search-jobs", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/search-jobs", "get">>;
|
package/dist/client.js
CHANGED
|
@@ -18,12 +18,14 @@ const REQUEST_ID_IDEMPOTENT_WRITES = new Set([
|
|
|
18
18
|
"post /v1/publications/text-searches",
|
|
19
19
|
]);
|
|
20
20
|
/**
|
|
21
|
-
* As
|
|
22
|
-
*
|
|
21
|
+
* As chamadas em que quem chama escolhe, em `waitSeconds`, quanto o motor
|
|
22
|
+
* espera pela fonte processual, e onde a espera viaja: na consulta das duas
|
|
23
|
+
* leituras de UM processo, no corpo da leitura que segue em segundo plano.
|
|
23
24
|
*/
|
|
24
|
-
const SOURCE_WAIT_ROUTES = new
|
|
25
|
-
"get /v1/processes/{processNumber}",
|
|
26
|
-
"get /v1/processes/{processNumber}/snapshot",
|
|
25
|
+
const SOURCE_WAIT_ROUTES = new Map([
|
|
26
|
+
["get /v1/processes/{processNumber}", "query"],
|
|
27
|
+
["get /v1/processes/{processNumber}/snapshot", "query"],
|
|
28
|
+
["post /v1/processes/lookups", "body"],
|
|
27
29
|
]);
|
|
28
30
|
/**
|
|
29
31
|
* A espera que o motor aplica a essas leituras quando a chamada não traz
|
|
@@ -117,10 +119,14 @@ function appendQuery(url, query) {
|
|
|
117
119
|
* prazo cobre essa espera mais a margem e nunca fica abaixo do prazo do
|
|
118
120
|
* cliente. Nas outras rotas, vale o prazo do cliente.
|
|
119
121
|
*/
|
|
120
|
-
function defaultCallTimeoutMs(method, path,
|
|
121
|
-
|
|
122
|
+
function defaultCallTimeoutMs(method, path, carriers, clientTimeoutMs) {
|
|
123
|
+
const carrier = SOURCE_WAIT_ROUTES.get(`${method} ${path}`);
|
|
124
|
+
if (!carrier)
|
|
122
125
|
return clientTimeoutMs;
|
|
123
|
-
const
|
|
126
|
+
const source = carriers[carrier];
|
|
127
|
+
const requested = Number(source && typeof source === "object"
|
|
128
|
+
? source.waitSeconds
|
|
129
|
+
: undefined);
|
|
124
130
|
const waitSeconds = Number.isFinite(requested) && requested > 0
|
|
125
131
|
? requested
|
|
126
132
|
: SOURCE_WAIT_API_DEFAULT_SECONDS;
|
|
@@ -261,7 +267,7 @@ export function createLexNodeClient(options) {
|
|
|
261
267
|
throw LexNodeError.invalidRequest("O corpo da chamada não é serializável em JSON.", error);
|
|
262
268
|
}
|
|
263
269
|
const timeoutMs = args.timeoutMs ??
|
|
264
|
-
defaultCallTimeoutMs(String(method), String(path), bag.params?.query, defaultTimeoutMs);
|
|
270
|
+
defaultCallTimeoutMs(String(method), String(path), { query: bag.params?.query, body: bag.body }, defaultTimeoutMs);
|
|
265
271
|
const link = linkAbort(timeoutMs, args.signal);
|
|
266
272
|
let response;
|
|
267
273
|
let raw;
|
|
@@ -423,6 +429,29 @@ export function createLexNodeClient(options) {
|
|
|
423
429
|
list: (query, opts = {}) => request("/v1/subscriptions", "get", { params: { query }, ...opts }),
|
|
424
430
|
delete: (body, opts = {}) => request("/v1/subscriptions", "delete", { body, ...opts }),
|
|
425
431
|
},
|
|
432
|
+
processLookups: {
|
|
433
|
+
/**
|
|
434
|
+
* A leitura de UM processo que segue em segundo plano quando a fonte não
|
|
435
|
+
* entrega dentro de `waitSeconds`: 200 com o processo, ou 202 com a
|
|
436
|
+
* consulta aberta. Repetir é seguro — o motor devolve a consulta já
|
|
437
|
+
* aberta da mesma leitura em vez de abrir outra —, então a retentativa
|
|
438
|
+
* vale para ela como para uma leitura.
|
|
439
|
+
*/
|
|
440
|
+
create: (body, opts = {}) => request("/v1/processes/lookups", "post", {
|
|
441
|
+
body,
|
|
442
|
+
idempotent: true,
|
|
443
|
+
...opts,
|
|
444
|
+
}),
|
|
445
|
+
get: (lookupId, opts = {}) => request("/v1/processes/lookups/{lookupId}", "get", {
|
|
446
|
+
params: { path: { lookupId } },
|
|
447
|
+
...opts,
|
|
448
|
+
}),
|
|
449
|
+
list: (query, opts = {}) => request("/v1/processes/lookups", "get", { params: { query }, ...opts }),
|
|
450
|
+
cancel: (lookupId, opts = {}) => request("/v1/processes/lookups/{lookupId}/cancel", "post", {
|
|
451
|
+
params: { path: { lookupId } },
|
|
452
|
+
...opts,
|
|
453
|
+
}),
|
|
454
|
+
},
|
|
426
455
|
searchJobs: {
|
|
427
456
|
get: (jobId, opts = {}) => request("/v1/search-jobs/{jobId}", "get", {
|
|
428
457
|
params: { path: { jobId } },
|
package/dist/errors.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { RateLimitSnapshot } from "./types.js";
|
|
|
9
9
|
* os dois por literal redigitado descobre o engano em produção. A lista é
|
|
10
10
|
* fechada para o que se conhece e aberta para o que vier (ver `LexNodeError`).
|
|
11
11
|
*/
|
|
12
|
-
export declare const LEXNODE_ERROR_CODES: readonly ["INVALID_MONITOR", "TRIBUNAL_NOT_SUPPORTED", "PERSONAL_DOCUMENT_QUERY_NOT_ALLOWED", "VALIDATION_ERROR", "UNAUTHORIZED", "QUOTA_EXCEEDED", "INSUFFICIENT_SCOPE", "LGPD_FORBIDDEN", "PLAN_FEATURE_NOT_INCLUDED", "SUB_TENANT_LIMIT_EXCEEDED", "SANDBOX_UPSTREAM_DISABLED", "MOVEMENTS_NOT_AVAILABLE", "PRECEDENT_NOT_FOUND", "PROCESS_NOT_FOUND", "RESOURCE_NOT_FOUND", "RESOURCE_CONFLICT", "QUERY_TOO_BROAD", "RATE_LIMITED", "UPSTREAM_RATE_LIMITED", "INTERNAL_ERROR", "UPSTREAM_UNAVAILABLE", "DATABASE_TIMEOUT", "DATABASE_UNAVAILABLE", "SYNC_ABANDONED", "UPSTREAM_TIMEOUT", "ACCOUNT_SUSPENDED", "ENTITLEMENT_EXPIRED", "PROJECT_DISABLED", "SUBSCRIPTION_INACTIVE", "MONITOR_ALREADY_EXISTS", "MONITOR_NOT_FOUND", "SEARCH_JOB_NOT_FOUND", "PUBLICATION_NOT_FOUND", "EVENT_NOT_FOUND", "TEXT_ALERT_NOT_FOUND", "TEXT_SEARCH_NOT_FOUND", "CLIENT_TIMEOUT", "CLIENT_NETWORK_ERROR", "CLIENT_INVALID_REQUEST", "CLIENT_MISSING_PATH_PARAM", "INVALID_RESPONSE", "SEARCH_JOB_BUDGET_EXCEEDED", "PAGINATION_LIMIT_REACHED"];
|
|
12
|
+
export declare const LEXNODE_ERROR_CODES: readonly ["INVALID_MONITOR", "TRIBUNAL_NOT_SUPPORTED", "PERSONAL_DOCUMENT_QUERY_NOT_ALLOWED", "VALIDATION_ERROR", "UNAUTHORIZED", "QUOTA_EXCEEDED", "INSUFFICIENT_SCOPE", "LGPD_FORBIDDEN", "PLAN_FEATURE_NOT_INCLUDED", "SUB_TENANT_LIMIT_EXCEEDED", "SANDBOX_UPSTREAM_DISABLED", "MOVEMENTS_NOT_AVAILABLE", "PRECEDENT_NOT_FOUND", "PROCESS_NOT_FOUND", "RESOURCE_NOT_FOUND", "RESOURCE_CONFLICT", "QUERY_TOO_BROAD", "RATE_LIMITED", "UPSTREAM_RATE_LIMITED", "INTERNAL_ERROR", "UPSTREAM_UNAVAILABLE", "DATABASE_TIMEOUT", "DATABASE_UNAVAILABLE", "SYNC_ABANDONED", "UPSTREAM_TIMEOUT", "ACCOUNT_SUSPENDED", "ENTITLEMENT_EXPIRED", "PROJECT_DISABLED", "SUBSCRIPTION_INACTIVE", "MONITOR_ALREADY_EXISTS", "MONITOR_NOT_FOUND", "SEARCH_JOB_NOT_FOUND", "PROCESS_LOOKUP_NOT_FOUND", "PUBLICATION_NOT_FOUND", "EVENT_NOT_FOUND", "TEXT_ALERT_NOT_FOUND", "TEXT_SEARCH_NOT_FOUND", "CLIENT_TIMEOUT", "CLIENT_NETWORK_ERROR", "CLIENT_INVALID_REQUEST", "CLIENT_MISSING_PATH_PARAM", "INVALID_RESPONSE", "SEARCH_JOB_BUDGET_EXCEEDED", "PROCESS_LOOKUP_BUDGET_EXCEEDED", "PAGINATION_LIMIT_REACHED"];
|
|
13
13
|
/**
|
|
14
14
|
* Um código conhecido — ou qualquer outro.
|
|
15
15
|
*
|
package/dist/errors.js
CHANGED
|
@@ -43,6 +43,7 @@ export const LEXNODE_ERROR_CODES = [
|
|
|
43
43
|
"MONITOR_ALREADY_EXISTS",
|
|
44
44
|
"MONITOR_NOT_FOUND",
|
|
45
45
|
"SEARCH_JOB_NOT_FOUND",
|
|
46
|
+
"PROCESS_LOOKUP_NOT_FOUND",
|
|
46
47
|
"PUBLICATION_NOT_FOUND",
|
|
47
48
|
"EVENT_NOT_FOUND",
|
|
48
49
|
"TEXT_ALERT_NOT_FOUND",
|
|
@@ -54,6 +55,7 @@ export const LEXNODE_ERROR_CODES = [
|
|
|
54
55
|
"CLIENT_MISSING_PATH_PARAM",
|
|
55
56
|
"INVALID_RESPONSE",
|
|
56
57
|
"SEARCH_JOB_BUDGET_EXCEEDED",
|
|
58
|
+
"PROCESS_LOOKUP_BUDGET_EXCEEDED",
|
|
57
59
|
"PAGINATION_LIMIT_REACHED",
|
|
58
60
|
];
|
|
59
61
|
const RAW_MESSAGE_MAX_CHARS = 500;
|
package/dist/index.d.ts
CHANGED
|
@@ -15,9 +15,11 @@ export { LEXNODE_ERROR_CODES, LexNodeError, isLexNodeError } from "./errors.js";
|
|
|
15
15
|
export type { LexNodeErrorClass, LexNodeErrorCode, LexNodeErrorInit, } from "./errors.js";
|
|
16
16
|
export type { Body, CallOptions, Data, HttpMethod, LexNodeResult, Meta, MetaExtras, MethodOf, Operation, PathParams, Query, RateLimitSnapshot, RequestArgs, RetryPolicy, } from "./types.js";
|
|
17
17
|
export { DEFAULT_WEBHOOK_TOLERANCE_SECONDS, LEXNODE_WEBHOOK_HEADERS, WEBHOOK_EVENT_TYPES, WEBHOOK_TEST_EVENT_TYPE, isKnownWebhookEventType, isReceiverFault, isWebhookTest, parseWebhookEvent, verifyWebhookSignature, webhookRejectionStatus, } from "./webhooks.js";
|
|
18
|
-
export type { MonitorSyncFailedPayload, MonitorSyncSucceededPayload, PeriodEndingPayload, ProcessMovementCreatedPayload, ProcessSourceIndex, PublicationCreatedPayload, PublicationHarvestCompletedPayload, PublicationTextAlertMatch, PublicationTextAlertMatchedPayload, QuotaLowPayload, SubscribableWebhookEventType, SearchJobFailedPayload, SearchJobSucceededPayload, SubscriptionPastDuePayload, SuspensionSignal, UnknownWebhookEvent, VerifyWebhookOptions, WebhookEvent, WebhookEventEnvelope, WebhookEventType, WebhookHeaders, WebhookParseRejection, WebhookParseResult, WebhookRawBody, WebhookRejection, WebhookTestPayload, WebhookVerification, } from "./webhooks.js";
|
|
18
|
+
export type { MonitorSyncFailedPayload, MonitorSyncInstance, MonitorSyncSucceededPayload, PeriodEndingPayload, ProcessInstanceDiscoveredPayload, ProcessInstanceDiscoveredWithheldPayload, ProcessLookupFailedPayload, ProcessLookupSucceededPayload, ProcessMovementCreatedPayload, ProcessMovementInstanceCount, ProcessSourceIndex, PublicationCreatedPayload, PublicationHarvestCompletedPayload, PublicationTextAlertMatch, PublicationTextAlertMatchedPayload, QuotaLowPayload, SubscribableWebhookEventType, SearchJobFailedPayload, SearchJobSucceededPayload, SubscriptionPastDuePayload, SuspensionSignal, UnknownWebhookEvent, VerifyWebhookOptions, WebhookEvent, WebhookEventEnvelope, WebhookEventType, WebhookHeaders, WebhookParseRejection, WebhookParseResult, WebhookRawBody, WebhookRejection, WebhookTestPayload, WebhookVerification, } from "./webhooks.js";
|
|
19
19
|
export { paginate } from "./paginate.js";
|
|
20
20
|
export type { PaginateOptions } from "./paginate.js";
|
|
21
|
+
export { lookupProcess, waitForProcessLookup } from "./lookup.js";
|
|
22
|
+
export type { ProcessLookup, ProcessLookupInput, ProcessLookupOutcome, ProcessLookupRead, ProcessLookupState, ProcessLookupView, StaleProcessCopy, WaitForProcessLookupOptions, } from "./lookup.js";
|
|
21
23
|
export { searchProcesses, waitForSearchJob } from "./search.js";
|
|
22
24
|
export type { ProcessSearchOutcome, ProcessSearchResult, QueuedSearchJob, SearchJob, SearchJobState, WaitForSearchJobOptions, } from "./search.js";
|
|
23
25
|
export { describeFreshness, freshnessOf, isNotYetIndexed, lakeRescueOf, readThrough, sourceFetchedAtOf, } from "./freshness.js";
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { createLexNodeClient } from "./client.js";
|
|
|
12
12
|
export { LEXNODE_ERROR_CODES, LexNodeError, isLexNodeError } from "./errors.js";
|
|
13
13
|
export { DEFAULT_WEBHOOK_TOLERANCE_SECONDS, LEXNODE_WEBHOOK_HEADERS, WEBHOOK_EVENT_TYPES, WEBHOOK_TEST_EVENT_TYPE, isKnownWebhookEventType, isReceiverFault, isWebhookTest, parseWebhookEvent, verifyWebhookSignature, webhookRejectionStatus, } from "./webhooks.js";
|
|
14
14
|
export { paginate } from "./paginate.js";
|
|
15
|
+
export { lookupProcess, waitForProcessLookup } from "./lookup.js";
|
|
15
16
|
export { searchProcesses, waitForSearchJob } from "./search.js";
|
|
16
17
|
export { describeFreshness, freshnessOf, isNotYetIndexed, lakeRescueOf, readThrough, sourceFetchedAtOf, } from "./freshness.js";
|
|
17
18
|
export { isFirstAppearance, resubscribeOnFirstAppearance, unwatchProcess, watchProcess, } from "./watch.js";
|
package/dist/lookup.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { LexNodeClient } from "./client.js";
|
|
2
|
+
import type { Body, CallOptions, Data, Meta, MetaExtras } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* A leitura de UM processo que segue em segundo plano responde de dois jeitos
|
|
5
|
+
* na MESMA operação: 200 com o processo, quando ele coube na espera, ou 202
|
|
6
|
+
* com a consulta que segue tentando a fonte sozinha. O discriminador é o
|
|
7
|
+
* código HTTP, como na busca: a consulta aberta também tem `status`, mas quem
|
|
8
|
+
* afirma o desfecho da chamada é o 200 ou o 202.
|
|
9
|
+
*/
|
|
10
|
+
type CreateData = Data<"/v1/processes/lookups", "post">;
|
|
11
|
+
type CreateMeta = Meta<"/v1/processes/lookups", "post"> & MetaExtras;
|
|
12
|
+
/** A consulta como a leitura dela a devolve. */
|
|
13
|
+
export type ProcessLookup = Data<"/v1/processes/lookups/{lookupId}", "get">;
|
|
14
|
+
export type ProcessLookupState = ProcessLookup["status"];
|
|
15
|
+
export type ProcessLookupView = ProcessLookup["view"];
|
|
16
|
+
/** O que se pede: tribunal, número, visão, espera e a cópia na falha. */
|
|
17
|
+
export type ProcessLookupInput = Body<"/v1/processes/lookups", "post">;
|
|
18
|
+
/** A cópia guardada que o 202 entrega enquanto a consulta segue. */
|
|
19
|
+
export type StaleProcessCopy = NonNullable<CreateData["stale"]>;
|
|
20
|
+
/** O processo entregue na visão pedida: a ficha ou o retrato. */
|
|
21
|
+
export type ProcessLookupRead<V extends ProcessLookupView> = V extends "SNAPSHOT" ? NonNullable<CreateData["snapshot"]> : NonNullable<CreateData["process"]>;
|
|
22
|
+
export type ProcessLookupOutcome<V extends ProcessLookupView = ProcessLookupView> = {
|
|
23
|
+
kind: "ready";
|
|
24
|
+
/** A ficha ou o retrato, como a leitura direta os devolveria. */
|
|
25
|
+
data: ProcessLookupRead<V>;
|
|
26
|
+
lookup: CreateData;
|
|
27
|
+
meta: CreateMeta;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "pending";
|
|
30
|
+
/** A consulta aberta, a ser acompanhada por `waitForProcessLookup`. */
|
|
31
|
+
lookup: CreateData;
|
|
32
|
+
/** A cópia guardada, com a data, quando pedida em `staleOnFailure`. */
|
|
33
|
+
stale: StaleProcessCopy | null;
|
|
34
|
+
meta: CreateMeta;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Lê um processo e diz, no tipo, qual dos dois desfechos aconteceu.
|
|
38
|
+
*
|
|
39
|
+
* Sem isto, o consumidor lê `data.process` num corpo que é uma consulta
|
|
40
|
+
* aberta e chama de "sem dados" o que é "ainda estou buscando". A mesma
|
|
41
|
+
* leitura pedida de novo devolve a mesma consulta — repetir é seguro, e o
|
|
42
|
+
* cliente repete sozinho quando a política de retentativa estiver ligada.
|
|
43
|
+
*/
|
|
44
|
+
export declare function lookupProcess<V extends ProcessLookupView>(client: LexNodeClient, input: ProcessLookupInput & {
|
|
45
|
+
view: V;
|
|
46
|
+
}, opts?: CallOptions): Promise<ProcessLookupOutcome<V>>;
|
|
47
|
+
export interface WaitForProcessLookupOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Teto de espera total, em ms, incluindo as leituras e suas retentativas.
|
|
50
|
+
* EXPLÍCITO de propósito, como na busca: a consulta
|
|
51
|
+
* tenta por horas, e um laço sem orçamento gasta a requisição inteira de um
|
|
52
|
+
* ambiente serverless esperando uma fonte fora do ar.
|
|
53
|
+
*/
|
|
54
|
+
budgetMs?: number;
|
|
55
|
+
signal?: AbortSignal;
|
|
56
|
+
/** Chamado a cada leitura da consulta, para a UI acompanhar. */
|
|
57
|
+
onState?: (state: ProcessLookupState, lookup: ProcessLookup) => void;
|
|
58
|
+
officeId?: string | null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Espera a consulta terminar, dentro do orçamento.
|
|
62
|
+
*
|
|
63
|
+
* Lê a consulta de novo só quando há o que mudar: na hora da próxima tentativa
|
|
64
|
+
* (`nextAttemptAt`) — antes dela, a leitura devolve o mesmo estado —, a cada
|
|
65
|
+
* 10 s enquanto uma tentativa está em curso ou espera a vez na fila, e depois
|
|
66
|
+
* do `Retry-After` quando a própria leitura é recusada por vazão. Leitura não
|
|
67
|
+
* cobra, mas conta no teto por minuto da chave.
|
|
68
|
+
*
|
|
69
|
+
* O estouro do orçamento é um erro PRÓPRIO e retentável
|
|
70
|
+
* (`PROCESS_LOOKUP_BUDGET_EXCEEDED`): a consulta continua no motor, e quem
|
|
71
|
+
* espera pode voltar a lê-la depois — `details.nextReadAt` diz quando vale a
|
|
72
|
+
* pena — ou receber o `PROCESS_LOOKUP_COMPLETED` por webhook e não esperar
|
|
73
|
+
* nada. Quando a próxima leitura útil cai depois do orçamento, o erro sai na
|
|
74
|
+
* hora: esperar até o fim dele não mudaria nada. Devolve a consulta
|
|
75
|
+
* terminada: `SUCCEEDED`, com o processo enquanto o resultado vale; `FAILED`,
|
|
76
|
+
* com `error`; ou `CANCELED`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function waitForProcessLookup(client: LexNodeClient, lookupId: string, options?: WaitForProcessLookupOptions): Promise<ProcessLookup>;
|
|
79
|
+
export {};
|