@lexnode/legal-data-sdk 1.28.0 → 1.30.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 CHANGED
@@ -495,6 +495,39 @@ em segundo plano em vez de virar erro:
495
495
  - qualquer outra recusa é a da leitura direta: 404 quando a fonte diz não ter o
496
496
  processo, 403 no segredo de justiça, 402 sem saldo.
497
497
 
498
+ Para uma integração que precisa continuar mesmo quando a fonte demora, use
499
+ `readProcessWithRecovery`. A aceitação da cópia antiga é explícita; a espera
500
+ total é limitada. O fim da espera devolve `pending`, com a mesma consulta e
501
+ a próxima leitura útil, sem cancelar nem abrir outra compra:
502
+
503
+ ```ts
504
+ import { readProcessWithRecovery } from "@lexnode/legal-data-sdk";
505
+
506
+ const leitura = await readProcessWithRecovery(lexnode, {
507
+ tribunalAlias: "api_publica_tjsp",
508
+ processNumber: numeroDoProcesso,
509
+ view: "PROCESS",
510
+ waitSeconds: 5,
511
+ staleOnFailure: true, // aceita cópia anterior à falha: confira sourceFetchedAt
512
+ }, { completionBudgetMs: 30_000 });
513
+
514
+ if (leitura.kind === "ready") {
515
+ usarProcesso(leitura.data, leitura.meta.sourceFetchedAt);
516
+ } else if (leitura.kind === "pending") {
517
+ guardarConsulta(leitura.lookup.lookupId, leitura.nextReadAt);
518
+ // leitura.stale, quando presente, conserva a data da cópia.
519
+ // Continue pelo pollUrl ou pelo webhook PROCESS_LOOKUP_COMPLETED.
520
+ } else {
521
+ registrarDesfecho(leitura.kind, leitura.lookup.error);
522
+ // failed, canceled ou expired; nenhum deles afirma que o processo não existe.
523
+ }
524
+ ```
525
+
526
+ Sem `completionBudgetMs`, o helper entrega o 200 ou o 202 imediatamente após
527
+ a abertura. O orçamento adicional cobre somente o acompanhamento: cada chamada
528
+ mantém seu próprio timeout. Abortar a espera local não cancela a consulta no motor.
529
+ O custo, o gate de confidencialidade e a cobrança única são os do endpoint existente.
530
+
498
531
  `lookupProcess` diz, no tipo, qual dos dois desfechos aconteceu, e
499
532
  `waitForProcessLookup` espera a consulta terminar:
500
533
 
package/dist/index.d.ts CHANGED
@@ -18,8 +18,8 @@ export { DEFAULT_WEBHOOK_TOLERANCE_SECONDS, LEXNODE_WEBHOOK_HEADERS, WEBHOOK_EVE
18
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
+ export { lookupProcess, waitForProcessLookup, readProcessWithRecovery, } from "./lookup.js";
22
+ export type { ProcessLookup, ProcessLookupInput, ProcessLookupOutcome, ProcessLookupRead, ProcessLookupState, ProcessLookupView, ProcessRecoveryOutcome, StaleProcessCopy, WaitForProcessLookupOptions, } from "./lookup.js";
23
23
  export { searchProcesses, waitForSearchJob } from "./search.js";
24
24
  export type { ProcessSearchOutcome, ProcessSearchResult, QueuedSearchJob, SearchJob, SearchJobState, WaitForSearchJobOptions, } from "./search.js";
25
25
  export { describeFreshness, freshnessOf, isNotYetIndexed, lakeRescueOf, readThrough, sourceFetchedAtOf, } from "./freshness.js";
package/dist/index.js CHANGED
@@ -12,7 +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
+ export { lookupProcess, waitForProcessLookup, readProcessWithRecovery, } from "./lookup.js";
16
16
  export { searchProcesses, waitForSearchJob } from "./search.js";
17
17
  export { describeFreshness, freshnessOf, isNotYetIndexed, lakeRescueOf, readThrough, sourceFetchedAtOf, } from "./freshness.js";
18
18
  export { isFirstAppearance, resubscribeOnFirstAppearance, unwatchProcess, watchProcess, } from "./watch.js";
package/dist/lookup.d.ts CHANGED
@@ -54,7 +54,7 @@ export interface WaitForProcessLookupOptions {
54
54
  budgetMs?: number;
55
55
  signal?: AbortSignal;
56
56
  /** Chamado a cada leitura da consulta, para a UI acompanhar. */
57
- onState?: (state: ProcessLookupState, lookup: ProcessLookup) => void;
57
+ onState?: (state: ProcessLookupState, lookup: ProcessLookup, meta: Meta<"/v1/processes/lookups/{lookupId}", "get"> & MetaExtras) => void;
58
58
  officeId?: string | null;
59
59
  }
60
60
  /**
@@ -76,4 +76,31 @@ export interface WaitForProcessLookupOptions {
76
76
  * com `error`; ou `CANCELED`.
77
77
  */
78
78
  export declare function waitForProcessLookup(client: LexNodeClient, lookupId: string, options?: WaitForProcessLookupOptions): Promise<ProcessLookup>;
79
+ type ProcessRecoveryMeta = CreateMeta | (Meta<"/v1/processes/lookups/{lookupId}", "get"> & MetaExtras);
80
+ export type ProcessRecoveryOutcome<V extends ProcessLookupView> = {
81
+ kind: "ready";
82
+ data: ProcessLookupRead<V>;
83
+ lookup: CreateData | ProcessLookup;
84
+ meta: ProcessRecoveryMeta;
85
+ } | {
86
+ kind: "pending";
87
+ lookup: CreateData | ProcessLookup;
88
+ stale: StaleProcessCopy | null;
89
+ nextReadAt: string | null;
90
+ } | {
91
+ kind: "failed" | "canceled" | "expired";
92
+ lookup: ProcessLookup;
93
+ };
94
+ /**
95
+ * Abre uma consulta recuperável e acompanha somente dentro do orçamento.
96
+ * A aceitação de cópia antiga é explícita. Ao esgotar a espera, devolve a
97
+ * consulta pendente, sem novo POST nem cancelamento do trabalho no motor.
98
+ */
99
+ export declare function readProcessWithRecovery<V extends ProcessLookupView>(client: LexNodeClient, input: ProcessLookupInput & {
100
+ view: V;
101
+ staleOnFailure: boolean;
102
+ }, options?: CallOptions & {
103
+ completionBudgetMs?: number;
104
+ onState?: WaitForProcessLookupOptions["onState"];
105
+ }): Promise<ProcessRecoveryOutcome<V>>;
79
106
  export {};
package/dist/lookup.js CHANGED
@@ -115,7 +115,7 @@ export async function waitForProcessLookup(client, lookupId, options = {}) {
115
115
  }
116
116
  let nextReadAt;
117
117
  try {
118
- const { data } = await client.processLookups.get(lookupId, {
118
+ const { data, meta } = await client.processLookups.get(lookupId, {
119
119
  signal,
120
120
  officeId: options.officeId,
121
121
  });
@@ -124,7 +124,7 @@ export async function waitForProcessLookup(client, lookupId, options = {}) {
124
124
  throw budgetExceeded(lookupId, budgetMs, lastState, Date.now());
125
125
  }
126
126
  lastState = data.status;
127
- options.onState?.(data.status, data);
127
+ options.onState?.(data.status, data, meta);
128
128
  if (TERMINAL_STATES.has(data.status))
129
129
  return data;
130
130
  const nextAttemptAt = data.nextAttemptAt
@@ -156,3 +156,69 @@ export async function waitForProcessLookup(client, lookupId, options = {}) {
156
156
  options.signal?.removeEventListener("abort", onCallerAbort);
157
157
  }
158
158
  }
159
+ /**
160
+ * Abre uma consulta recuperável e acompanha somente dentro do orçamento.
161
+ * A aceitação de cópia antiga é explícita. Ao esgotar a espera, devolve a
162
+ * consulta pendente, sem novo POST nem cancelamento do trabalho no motor.
163
+ */
164
+ export async function readProcessWithRecovery(client, input, options = {}) {
165
+ const budgetMs = options.completionBudgetMs ?? 0;
166
+ options.signal?.throwIfAborted();
167
+ if (!Number.isFinite(budgetMs) || budgetMs < 0)
168
+ throw new RangeError("completionBudgetMs deve ser finito e não negativo.");
169
+ const initial = await lookupProcess(client, input, options);
170
+ options.signal?.throwIfAborted();
171
+ if (initial.kind === "ready")
172
+ return initial;
173
+ const pending = {
174
+ kind: "pending",
175
+ lookup: initial.lookup,
176
+ stale: initial.stale,
177
+ nextReadAt: initial.lookup.nextAttemptAt ?? null,
178
+ };
179
+ if (budgetMs === 0)
180
+ return pending;
181
+ let latest = initial.lookup;
182
+ let latestMeta = initial.meta;
183
+ try {
184
+ const lookup = await waitForProcessLookup(client, initial.lookup.lookupId, {
185
+ budgetMs,
186
+ signal: options.signal,
187
+ officeId: options.officeId,
188
+ onState: (state, currentLookup, meta) => {
189
+ latest = currentLookup;
190
+ latestMeta = meta;
191
+ options.onState?.(state, currentLookup, meta);
192
+ },
193
+ });
194
+ if (lookup.status === "FAILED")
195
+ return { kind: "failed", lookup };
196
+ if (lookup.status === "CANCELED")
197
+ return { kind: "canceled", lookup };
198
+ if (lookup.resultExpired)
199
+ return { kind: "expired", lookup };
200
+ const data = readOf(lookup, input.view);
201
+ if (!data)
202
+ throw new LexNodeError({
203
+ code: "INVALID_RESPONSE",
204
+ message: "Consulta concluída sem o resultado da visão pedida.",
205
+ status: 502,
206
+ retryable: true,
207
+ errorClass: "RETRYABLE",
208
+ });
209
+ return { kind: "ready", data, lookup, meta: latestMeta };
210
+ }
211
+ catch (error) {
212
+ if (options.signal?.aborted)
213
+ throw options.signal.reason;
214
+ if (!isLexNodeError(error) ||
215
+ error.code !== "PROCESS_LOOKUP_BUDGET_EXCEEDED")
216
+ throw error;
217
+ const details = error.details;
218
+ return {
219
+ ...pending,
220
+ lookup: latest,
221
+ nextReadAt: details?.nextReadAt ?? latest.nextAttemptAt ?? null,
222
+ };
223
+ }
224
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lexnode/legal-data-sdk",
3
- "version": "1.28.0",
3
+ "version": "1.30.0",
4
4
  "description": "Cliente TypeScript do LexNode, o motor de dados jur\u00eddicos do Brasil: transporte tipado, erros classificados, verifica\u00e7\u00e3o de webhook e os tipos gerados do contrato OpenAPI.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.lexnode.com.br/docs",
package/schema.d.ts CHANGED
@@ -641,7 +641,7 @@ export interface paths {
641
641
  };
642
642
  /**
643
643
  * Consultar a cobertura do corpus indexado
644
- * @description Cobertura agregada do corpus de jurisprudência indexado localmente: documentos indexáveis por fonte × tribunal × mês (a mesma agregação congelada no snapshot de cobertura de cada busca textual), combinada com o estado das fatias de colheita do diário oficial — grupo com fatia pendente reporta `PARTIAL` (o conjunto indexado ainda pode crescer), grupo totalmente colhido/indexado reporta `INDEXED`, e `NONE` significa nada indexado nem colheita solicitada. Inclui totais por fonte com as datas da publicação indexada mais antiga e mais recente, e a cobertura por matéria em `areas` — cada área do direito com estado, contagens e tribunais indexados, inclusive as matérias fora do acervo (`covered: false`), para que resultado vazio nunca se confunda com matéria não coberta. As fontes são reportadas separadamente — um corpus estruturado espelhado do tribunal e menções no diário oficial são ativos diferentes. Leitura local, zero créditos.
644
+ * @description Cobertura agregada do corpus de jurisprudência indexado localmente: documentos indexáveis por fonte × tribunal × mês (a mesma agregação que cada busca textual congela no snapshot de cobertura — lá marcado `UNAVAILABLE`, sem grupos, quando ela não coube no prazo da busca), combinada com o estado das fatias de colheita do diário oficial — grupo com fatia pendente reporta `PARTIAL` (o conjunto indexado ainda pode crescer), grupo totalmente colhido/indexado reporta `INDEXED`, e `NONE` significa nada indexado nem colheita solicitada. Inclui totais por fonte com as datas da publicação indexada mais antiga e mais recente, e a cobertura por matéria em `areas` — cada área do direito com estado, contagens e tribunais indexados, inclusive as matérias fora do acervo (`covered: false`), para que resultado vazio nunca se confunda com matéria não coberta. As fontes são reportadas separadamente — um corpus estruturado espelhado do tribunal e menções no diário oficial são ativos diferentes. Leitura local, zero créditos.
645
645
  *
646
646
  * **Escopo exigido na chave de API:** `PUBLICATIONS_READ`
647
647
  */
@@ -11136,10 +11136,10 @@ export interface operations {
11136
11136
  }[];
11137
11137
  coverage: {
11138
11138
  /**
11139
- * @description NONE = nada indexado nem colheita registrada; PARTIAL = há fatia de colheita pendente (o indexado pode crescer); INDEXED = há documento pesquisável indexado e nenhuma colheita pendente.
11139
+ * @description NONE = nada indexado nem colheita registrada; PARTIAL = há fatia de colheita pendente (o indexado pode crescer); INDEXED = há documento pesquisável indexado e nenhuma colheita pendente. UNAVAILABLE = a cobertura do recorte não coube no prazo da busca: `byTribunalMonth` vem vazio, o ranking vem inteiro e a busca custa o preço de sempre. O valor congelado não muda depois; a cobertura do mesmo recorte sai em GET /v1/publications/corpus/coverage, a 0 crédito, com os tribunais da busca num só `tribunalCodes`, separados por vírgula (`tribunalCodes=STJ,TJSP`), e a janela dela em `from` e `to`.
11140
11140
  * @enum {string}
11141
11141
  */
11142
- overallState: "NONE" | "PARTIAL" | "INDEXED";
11142
+ overallState: "NONE" | "PARTIAL" | "INDEXED" | "UNAVAILABLE";
11143
11143
  byTribunalMonth: {
11144
11144
  source?: string;
11145
11145
  tribunalSigla: string;
@@ -11396,10 +11396,10 @@ export interface operations {
11396
11396
  corpusWatermark: string | null;
11397
11397
  coverage: {
11398
11398
  /**
11399
- * @description NONE = nada indexado nem colheita registrada; PARTIAL = há fatia de colheita pendente (o indexado pode crescer); INDEXED = há documento pesquisável indexado e nenhuma colheita pendente.
11399
+ * @description NONE = nada indexado nem colheita registrada; PARTIAL = há fatia de colheita pendente (o indexado pode crescer); INDEXED = há documento pesquisável indexado e nenhuma colheita pendente. UNAVAILABLE = a cobertura do recorte não coube no prazo da busca: `byTribunalMonth` vem vazio, o ranking vem inteiro e a busca custa o preço de sempre. O valor congelado não muda depois; a cobertura do mesmo recorte sai em GET /v1/publications/corpus/coverage, a 0 crédito, com os tribunais da busca num só `tribunalCodes`, separados por vírgula (`tribunalCodes=STJ,TJSP`), e a janela dela em `from` e `to`.
11400
11400
  * @enum {string}
11401
11401
  */
11402
- overallState: "NONE" | "PARTIAL" | "INDEXED";
11402
+ overallState: "NONE" | "PARTIAL" | "INDEXED" | "UNAVAILABLE";
11403
11403
  byTribunalMonth: {
11404
11404
  source?: string;
11405
11405
  tribunalSigla: string;
@@ -11723,6 +11723,7 @@ export interface operations {
11723
11723
  getPublicationCorpusCoverage: {
11724
11724
  parameters: {
11725
11725
  query?: {
11726
+ /** @description Tribunais do recorte num só valor, separados por vírgula (`tribunalCodes=STJ,TJSP`), pela sigla ou pelo apelido da fonte. Sem ele, a cobertura é a de todos os tribunais do acervo. */
11726
11727
  tribunalCodes?: string;
11727
11728
  from?: string;
11728
11729
  to?: string;