@lexnode/legal-data-sdk 1.29.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.29.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",