@lexnode/legal-data-sdk 1.30.0 → 1.31.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/dist/errors.d.ts CHANGED
@@ -1,29 +1,38 @@
1
1
  import type { RateLimitSnapshot } from "./types.js";
2
2
  /**
3
- * Os códigos de recusa que o contrato declara, mais os que este cliente cunha
4
- * para falhas locais.
3
+ * Os códigos de erro conhecidos: os que a API responde e os que este pacote
4
+ * cria para falhas locais (prazo, rede, pedido que não se monta, resposta fora
5
+ * do formato, orçamento de espera e limite de páginas).
5
6
  *
6
- * Existe para o `switch` do consumidor ter autocompletar e para o erro de
7
- * digitação virar erro de compilação: o motor responde 404 tanto para
8
- * `PROCESS_NOT_FOUND` quanto para `MOVEMENTS_NOT_AVAILABLE`, e quem distingue
9
- * os dois por literal redigitado descobre o engano em produção. A lista é
10
- * fechada para o que se conhece e aberta para o que vier (ver `LexNodeError`).
7
+ * Use no `switch` sobre `LexNodeError.code`: o autocompletar mostra a lista, e
8
+ * um código digitado errado não compila. A API pode passar a responder códigos
9
+ * novos; trate o desconhecido no `default`.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * switch (error.code) {
14
+ * case "PROCESS_NOT_FOUND":
15
+ * return "o processo não existe na fonte";
16
+ * case "MOVEMENTS_NOT_AVAILABLE":
17
+ * return "o processo existe, mas as movimentações não vieram";
18
+ * default:
19
+ * throw error;
20
+ * }
21
+ * ```
11
22
  */
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"];
23
+ 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", "SOURCE_MAINTENANCE", "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
24
  /**
14
- * Um código conhecido — ou qualquer outro.
15
- *
16
- * O `string & {}` mantém o autocompletar da lista sem fechar a porta: um código
17
- * novo do motor continua chegando ao `catch` em vez de quebrar a compilação de
18
- * quem já integrou.
25
+ * Um código de `LEXNODE_ERROR_CODES` ou qualquer outro texto. Os conhecidos
26
+ * aparecem no autocompletar, e um código novo da API continua compilando.
19
27
  */
20
28
  export type LexNodeErrorCode = (typeof LEXNODE_ERROR_CODES)[number] | (string & {});
21
29
  /**
22
- * A classificação que o motor carimba em toda recusa: `RETRYABLE` é condição
23
- * passageira (prazo, 5xx, teto de vazão), `TERMINAL` é o que repetir não cura
24
- * (validação, autorização, cota, alvo inexistente).
30
+ * A classe do erro: `RETRYABLE` é uma condição passageira (prazo, falha
31
+ * temporária, limite de vazão), que pode dar certo ao repetir; `TERMINAL` não
32
+ * melhora com a repetição (validação, autorização, saldo, recurso inexistente).
25
33
  */
26
34
  export type LexNodeErrorClass = "RETRYABLE" | "TERMINAL";
35
+ /** Os campos com que se cria um `LexNodeError`, por exemplo num teste. */
27
36
  export interface LexNodeErrorInit {
28
37
  code: LexNodeErrorCode;
29
38
  message: string;
@@ -39,56 +48,92 @@ export interface LexNodeErrorInit {
39
48
  cause?: unknown;
40
49
  }
41
50
  /**
42
- * Toda falha que o cliente produz — do motor, da rede ou do prazo — chega como
43
- * esta classe.
51
+ * O erro que toda chamada deste pacote lança: recusa da API, falha de rede,
52
+ * prazo esgotado, pedido que não se monta e resposta fora do formato da API.
53
+ *
54
+ * Decida pelo `code` e pelo `retryable`, nunca pela mensagem. Ao registrar a
55
+ * falha, guarde o `requestId`: é por ele que o suporte encontra a chamada.
44
56
  *
45
- * Um único tipo para o `catch` do consumidor: ele decide por `retryable` e
46
- * `code`, não por farejar a forma do que caiu. `requestId` vem junto porque é
47
- * o que o suporte pede; perdê-lo transforma um incidente rastreável num relato.
57
+ * @example
58
+ * ```ts
59
+ * try {
60
+ * await lexnode.processes.get(numero, { tribunalAlias: "TJSP" });
61
+ * } catch (error) {
62
+ * if (isLexNodeError(error) && error.code === "PROCESS_NOT_FOUND") {
63
+ * // o processo não existe na fonte
64
+ * }
65
+ * throw error;
66
+ * }
67
+ * ```
48
68
  */
49
69
  export declare class LexNodeError extends Error {
50
70
  readonly name = "LexNodeError";
51
- /** O código do contrato (`RATE_LIMITED`, `PROCESS_NOT_FOUND`, …). */
71
+ /** O código do erro (`RATE_LIMITED`, `PROCESS_NOT_FOUND`, …). */
52
72
  readonly code: LexNodeErrorCode;
53
- /** Status HTTP da recusa — ou o que o cliente atribuiu à falha local. */
73
+ /**
74
+ * O status HTTP da recusa, ou o atribuído à falha local: 504 no prazo
75
+ * esgotado, 502 na falha de rede e na resposta fora do formato, 400 no
76
+ * pedido que não se monta.
77
+ */
54
78
  readonly status: number;
79
+ /** `RETRYABLE` ou `TERMINAL`. */
55
80
  readonly class: LexNodeErrorClass;
81
+ /** Se repetir a chamada pode dar certo. */
56
82
  readonly retryable: boolean;
57
- /** Status real da fonte a montante, quando o motor o preservou. */
83
+ /**
84
+ * O status HTTP que a fonte respondeu, quando a API o informa; na resposta
85
+ * fora do formato, o status recebido.
86
+ */
58
87
  readonly upstreamStatus: number | null;
88
+ /** O `X-Request-Id` da chamada recusada, quando a API o devolveu. */
59
89
  readonly requestId: string | null;
60
- /** Erros por campo de uma recusa de validação. */
90
+ /** As mensagens por campo de uma recusa de validação. */
61
91
  readonly fieldErrors: Record<string, string[]> | null;
92
+ /**
93
+ * Os detalhes da recusa, como o `monitorId` do monitor existente em
94
+ * `MONITOR_ALREADY_EXISTS`.
95
+ */
62
96
  readonly details: Record<string, unknown> | null;
97
+ /**
98
+ * Quantos segundos esperar antes de repetir, quando a recusa ou o cabeçalho
99
+ * `Retry-After` dizem.
100
+ */
63
101
  readonly retryAfterSeconds: number | null;
102
+ /** Os cabeçalhos de limite de vazão da resposta recusada, quando vieram. */
64
103
  readonly rateLimit: RateLimitSnapshot | null;
65
104
  constructor(init: LexNodeErrorInit);
66
105
  /**
67
- * A recusa como o motor a descreveu. A classe e o `retryable` saem do corpo
68
- * quando ele os traz; o status é o da resposta, que é o que de fato chegou.
106
+ * Cria o erro a partir do corpo de erro da API, ou devolve `null` quando o
107
+ * corpo não traz `error.code`. A classe e o `retryable` vêm do corpo; o
108
+ * status, da resposta.
69
109
  */
70
110
  static fromEnvelope(envelope: unknown, status: number, rateLimit: RateLimitSnapshot | null): LexNodeError | null;
71
- /** Prazo esgotado antes de a resposta chegar: nada foi decidido, repetir cabe. */
111
+ /**
112
+ * O prazo da chamada esgotou antes da resposta: `CLIENT_TIMEOUT`, 504,
113
+ * retentável.
114
+ */
72
115
  static timeout(timeoutMs: number, cause?: unknown): LexNodeError;
73
- /** A requisição não alcançou o motor: DNS, conexão, TLS, socket derrubado. */
116
+ /**
117
+ * A chamada não chegou à API — DNS, conexão, TLS ou conexão interrompida:
118
+ * `CLIENT_NETWORK_ERROR`, 502, retentável.
119
+ */
74
120
  static network(cause: unknown): LexNodeError;
75
121
  /**
76
- * Respondeu, mas não no envelope do contrato — proxy, página de erro, HTML.
77
- *
78
- * 502 porque o que quebrou está no caminho, não no pedido; o status real
79
- * sobrevive em `upstreamStatus`, e a mensagem carrega o corpo cru truncado,
80
- * que é a única pista de quem respondeu.
122
+ * A resposta não veio no formato da API, como a página de erro de um proxy:
123
+ * `INVALID_RESPONSE`, 502, retentável. O status recebido fica em
124
+ * `upstreamStatus`, e o início do corpo, na mensagem.
81
125
  */
82
126
  static invalidResponse(status: number, raw: string, rateLimit: RateLimitSnapshot | null): LexNodeError;
83
127
  /**
84
- * O pedido não chegou a sair: cabeçalho que o `fetch` recusa montar, corpo
85
- * que não serializa.
86
- *
87
- * TERMINAL de propósito. Repetir o que o transporte barrou antes de abrir o
88
- * socket não tem como dar certo, e classificá-lo como falha de rede manda o
89
- * consumidor gastar as tentativas num defeito do próprio código.
128
+ * O pedido não foi enviado porque não se monta — cabeçalho com quebra de
129
+ * linha ou caractere nulo, corpo que não vira JSON, `baseUrl` inválida ou
130
+ * sem https: `CLIENT_INVALID_REQUEST`, 400, não retentável. Corrija a
131
+ * chamada.
90
132
  */
91
133
  static invalidRequest(message: string, cause?: unknown): LexNodeError;
92
134
  }
93
- /** Guarda de tipo para o `catch`, sem depender do `instanceof` cruzar realms. */
135
+ /**
136
+ * Diz se o valor é um `LexNodeError`, inclusive quando ele vem de outra cópia
137
+ * do pacote instalada no projeto, em que o `instanceof` falha.
138
+ */
94
139
  export declare function isLexNodeError(value: unknown): value is LexNodeError;
package/dist/errors.js CHANGED
@@ -1,13 +1,3 @@
1
- /**
2
- * Os códigos de recusa que o contrato declara, mais os que este cliente cunha
3
- * para falhas locais.
4
- *
5
- * Existe para o `switch` do consumidor ter autocompletar e para o erro de
6
- * digitação virar erro de compilação: o motor responde 404 tanto para
7
- * `PROCESS_NOT_FOUND` quanto para `MOVEMENTS_NOT_AVAILABLE`, e quem distingue
8
- * os dois por literal redigitado descobre o engano em produção. A lista é
9
- * fechada para o que se conhece e aberta para o que vier (ver `LexNodeError`).
10
- */
11
1
  export const LEXNODE_ERROR_CODES = [
12
2
  "INVALID_MONITOR",
13
3
  "TRIBUNAL_NOT_SUPPORTED",
@@ -32,10 +22,9 @@ export const LEXNODE_ERROR_CODES = [
32
22
  "UPSTREAM_UNAVAILABLE",
33
23
  "DATABASE_TIMEOUT",
34
24
  "DATABASE_UNAVAILABLE",
25
+ "SOURCE_MAINTENANCE",
35
26
  "SYNC_ABANDONED",
36
27
  "UPSTREAM_TIMEOUT",
37
- // Fora da tabela pública, mas na porta do tenant: a credencial recusada pela
38
- // própria conta, e o alvo nomeado que não existe (ou já existe).
39
28
  "ACCOUNT_SUSPENDED",
40
29
  "ENTITLEMENT_EXPIRED",
41
30
  "PROJECT_DISABLED",
@@ -48,7 +37,6 @@ export const LEXNODE_ERROR_CODES = [
48
37
  "EVENT_NOT_FOUND",
49
38
  "TEXT_ALERT_NOT_FOUND",
50
39
  "TEXT_SEARCH_NOT_FOUND",
51
- // Cunhados aqui: nunca vêm do motor.
52
40
  "CLIENT_TIMEOUT",
53
41
  "CLIENT_NETWORK_ERROR",
54
42
  "CLIENT_INVALID_REQUEST",
@@ -81,26 +69,14 @@ function readFieldErrors(details) {
81
69
  }
82
70
  return out;
83
71
  }
84
- /**
85
- * Toda falha que o cliente produz — do motor, da rede ou do prazo — chega como
86
- * esta classe.
87
- *
88
- * Um único tipo para o `catch` do consumidor: ele decide por `retryable` e
89
- * `code`, não por farejar a forma do que caiu. `requestId` vem junto porque é
90
- * o que o suporte pede; perdê-lo transforma um incidente rastreável num relato.
91
- */
92
72
  export class LexNodeError extends Error {
93
73
  name = "LexNodeError";
94
- /** O código do contrato (`RATE_LIMITED`, `PROCESS_NOT_FOUND`, …). */
95
74
  code;
96
- /** Status HTTP da recusa — ou o que o cliente atribuiu à falha local. */
97
75
  status;
98
76
  class;
99
77
  retryable;
100
- /** Status real da fonte a montante, quando o motor o preservou. */
101
78
  upstreamStatus;
102
79
  requestId;
103
- /** Erros por campo de uma recusa de validação. */
104
80
  fieldErrors;
105
81
  details;
106
82
  retryAfterSeconds;
@@ -118,10 +94,6 @@ export class LexNodeError extends Error {
118
94
  this.retryAfterSeconds = init.retryAfterSeconds ?? null;
119
95
  this.rateLimit = init.rateLimit ?? null;
120
96
  }
121
- /**
122
- * A recusa como o motor a descreveu. A classe e o `retryable` saem do corpo
123
- * quando ele os traz; o status é o da resposta, que é o que de fato chegou.
124
- */
125
97
  static fromEnvelope(envelope, status, rateLimit) {
126
98
  const body = asRecord(envelope);
127
99
  const error = asRecord(body?.error);
@@ -149,7 +121,6 @@ export class LexNodeError extends Error {
149
121
  rateLimit,
150
122
  });
151
123
  }
152
- /** Prazo esgotado antes de a resposta chegar: nada foi decidido, repetir cabe. */
153
124
  static timeout(timeoutMs, cause) {
154
125
  return new LexNodeError({
155
126
  code: "CLIENT_TIMEOUT",
@@ -160,7 +131,6 @@ export class LexNodeError extends Error {
160
131
  cause,
161
132
  });
162
133
  }
163
- /** A requisição não alcançou o motor: DNS, conexão, TLS, socket derrubado. */
164
134
  static network(cause) {
165
135
  const detail = cause instanceof Error ? cause.message : String(cause);
166
136
  return new LexNodeError({
@@ -172,13 +142,6 @@ export class LexNodeError extends Error {
172
142
  cause,
173
143
  });
174
144
  }
175
- /**
176
- * Respondeu, mas não no envelope do contrato — proxy, página de erro, HTML.
177
- *
178
- * 502 porque o que quebrou está no caminho, não no pedido; o status real
179
- * sobrevive em `upstreamStatus`, e a mensagem carrega o corpo cru truncado,
180
- * que é a única pista de quem respondeu.
181
- */
182
145
  static invalidResponse(status, raw, rateLimit) {
183
146
  return new LexNodeError({
184
147
  code: "INVALID_RESPONSE",
@@ -187,20 +150,10 @@ export class LexNodeError extends Error {
187
150
  errorClass: "RETRYABLE",
188
151
  retryable: true,
189
152
  upstreamStatus: status,
190
- // O 429 de uma borda ou de um proxy não vem no envelope, mas traz o
191
- // `Retry-After` do mesmo jeito — e é por este campo que o recuo decide.
192
153
  retryAfterSeconds: rateLimit?.retryAfterSeconds ?? null,
193
154
  rateLimit,
194
155
  });
195
156
  }
196
- /**
197
- * O pedido não chegou a sair: cabeçalho que o `fetch` recusa montar, corpo
198
- * que não serializa.
199
- *
200
- * TERMINAL de propósito. Repetir o que o transporte barrou antes de abrir o
201
- * socket não tem como dar certo, e classificá-lo como falha de rede manda o
202
- * consumidor gastar as tentativas num defeito do próprio código.
203
- */
204
157
  static invalidRequest(message, cause) {
205
158
  return new LexNodeError({
206
159
  code: "CLIENT_INVALID_REQUEST",
@@ -212,7 +165,6 @@ export class LexNodeError extends Error {
212
165
  });
213
166
  }
214
167
  }
215
- /** Guarda de tipo para o `catch`, sem depender do `instanceof` cruzar realms. */
216
168
  export function isLexNodeError(value) {
217
169
  return (value instanceof LexNodeError ||
218
170
  (value instanceof Error && value.name === "LexNodeError"));
@@ -1,87 +1,134 @@
1
1
  /**
2
- * Até onde a fonte foi lida — o que qualifica um resultado vazio.
3
- *
4
- * Um `total: 0` sozinho não distingue "não existe" de "a fonte ainda não
5
- * indexou". Quem confunde os dois diz ao usuário que o processo não existe e
6
- * repete a busca, pagando de novo por uma resposta que não pode mudar. O motor
7
- * publica a data-limite do índice em dois eixos — `updatedThrough` na busca de
8
- * processo, `lastEditionDate` na leitura do diário — e este módulo é a leitura
9
- * dos dois pelo mesmo nome.
10
- *
11
- * A leitura de UM processo diz também de quando são os dados servidos
12
- * (`meta.sourceFetchedAt`) e, quando a fonte falhou e o acervo socorreu, que a
13
- * resposta é a cópia guardada (`meta.lakeRescue`).
2
+ * O eixo da data-limite: `PROCESS`, da busca de processos
3
+ * (`sourceIndex.updatedThrough`), ou `PUBLICATION`, das publicações do diário
4
+ * (`sourceIndex.lastEditionDate`).
14
5
  */
15
6
  export type FreshnessAxis = "PROCESS" | "PUBLICATION";
7
+ /** Se a resposta declara até quando a fonte foi lida. */
16
8
  export type FreshnessState =
17
- /** A fonte declarou até quando leu. */
9
+ /** A resposta declara a data-limite. */
18
10
  "KNOWN"
19
- /** A fonte não respondeu à sondagem, ou a resposta não traz o campo. */
11
+ /** A resposta não traz a data-limite. */
20
12
  | "INDETERMINATE";
13
+ /** O frescor de uma resposta, como `freshnessOf` o lê. */
21
14
  export interface Freshness {
15
+ /** Se a data-limite é conhecida. */
22
16
  state: FreshnessState;
17
+ /** O eixo da data-limite; `null` quando a resposta não traz `sourceIndex`. */
23
18
  axis: FreshnessAxis | null;
24
19
  /** A data-limite do índice da fonte, quando declarada. */
25
20
  readThrough: Date | null;
26
- /** Quando a resposta montou essa data-limite. */
21
+ /** Quando a API conferiu a data-limite. */
27
22
  checkedAt: Date | null;
23
+ /** O tribunal a que a data-limite se refere. */
28
24
  tribunalAlias: string | null;
29
25
  }
30
- /** O retrato completo do frescor de uma resposta. */
26
+ /**
27
+ * Lê até quando a fonte foi lida, numa resposta de busca de processos ou de
28
+ * publicações.
29
+ *
30
+ * Aceita o envelope inteiro (`{ data, meta }`) ou só o `data`. Devolve o
31
+ * estado `INDETERMINATE`, sem lançar, quando a resposta não traz a
32
+ * data-limite.
33
+ */
31
34
  export declare function freshnessOf(result: unknown): Freshness;
32
- /** A data-limite do índice da fonte, ou `null` quando ela não a declarou. */
35
+ /**
36
+ * A data-limite do índice da fonte na resposta, ou `null` quando a resposta
37
+ * não a declara.
38
+ */
33
39
  export declare function readThrough(result: unknown): Date | null;
40
+ /** As opções de `isNotYetIndexed`. */
34
41
  export interface NotYetIndexedOptions {
35
42
  /**
36
- * A data a partir da qual o alvo existiria — a distribuição do processo, o
37
- * dia da publicação. Com ela, a resposta deixa de ser um palpite: a fonte
38
- * lida só até antes dessa data não pode ter visto o alvo.
43
+ * A data a partir da qual o alvo existe, como a distribuição do processo ou
44
+ * o dia da publicação (`Date` ou AAAA-MM-DD). Uma fonte lida só até antes
45
+ * dela não pode ter visto o alvo.
39
46
  */
40
47
  since?: Date | string;
41
48
  }
42
49
  /**
43
- * Se o vazio desta resposta NÃO prova ausência.
50
+ * Diz se o vazio desta resposta pode ser só atraso da fonte, e não ausência.
44
51
  *
45
- * Verdadeiro quando a fonte não declarou até onde leu (o estado indeterminado
46
- * — ausência de campo é estado, nunca erro) ou quando ela leu até antes de
47
- * `since`. Falso quando há resultado, e falso quando a fonte declarou uma
48
- * data-limite que cobre o que se perguntou: aí o vazio é resposta.
52
+ * Devolve `true` quando a resposta vem sem resultados e a fonte não declarou
53
+ * até onde leu, ou leu só até antes de `since`. Devolve `false` quando há
54
+ * resultados, ou quando a data-limite declarada alcança `since` ou não há
55
+ * `since`: aí o vazio é a resposta. Confira isto antes de dizer que um
56
+ * processo ou uma publicação não existe.
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const busca = await lexnode.processes.search({
61
+ * tribunalAlias: "TJSP",
62
+ * number,
63
+ * });
64
+ * if (isNotYetIndexed(busca, { since: "2026-09-15" })) {
65
+ * mostrar(describeFreshness(busca)); // "fonte lida até 10/09/2026"
66
+ * }
67
+ * ```
49
68
  */
50
69
  export declare function isNotYetIndexed(result: unknown, options?: NotYetIndexedOptions): boolean;
51
- /** Por que a fonte não entregou o processo que o acervo socorreu. */
70
+ /**
71
+ * Por que a fonte processual não entregou o processo, na leitura respondida
72
+ * com a cópia guardada.
73
+ */
52
74
  export type LakeRescueCause = "UPSTREAM_TIMEOUT" | "UPSTREAM_UNAVAILABLE" | "UPSTREAM_RATE_LIMITED";
53
75
  /**
54
- * A leitura de UM processo cuja fonte falhou e que o motor serviu com a cópia
55
- * que o acervo guarda.
76
+ * A leitura de um processo que, na falha da fonte processual, foi respondida
77
+ * com a cópia guardada. O que andou no processo depois de `sourceFetchedAt`
78
+ * não está na resposta.
56
79
  */
57
80
  export interface LakeRescue {
58
81
  /**
59
- * A causa, pelo código público da taxonomia. Valor novo pode entrar no
60
- * contrato; trate o desconhecido como "a fonte falhou".
82
+ * A causa, pelo código de erro da API. A lista pode crescer; trate um valor
83
+ * desconhecido como falha da fonte.
61
84
  */
62
85
  cause: LakeRescueCause | (string & {});
63
86
  /**
64
- * Quando a cópia servida foi buscada na fonte; nulo na ficha que o controle
65
- * de confidencialidade entrega retida, que sai sem a data.
87
+ * Quando a cópia foi buscada na fonte; `null` na ficha que o controle de
88
+ * confidencialidade entrega retida, sem a data.
66
89
  */
67
90
  sourceFetchedAt: Date | null;
68
- /** A espera que a fonte pediu, na recusa por volume. */
91
+ /** Quantos segundos a fonte pediu para esperar, na recusa por volume. */
69
92
  retryAfterSeconds: number | null;
70
93
  }
71
94
  /**
72
- * O socorro pelo acervo, ou `null` quando a resposta veio da fonte ou do
73
- * acervo em dia. Aceita o envelope inteiro (`{ data, meta }`) ou o item do
74
- * lote de retratos; só o `data` não traz a marca.
95
+ * Diz se a resposta é a cópia guardada servida na falha da fonte e devolve a
96
+ * causa e a data dela; `null` quando não é.
97
+ *
98
+ * Aceita o envelope inteiro (`{ data, meta }`) de `processes.get` e
99
+ * `processes.snapshot`, ou um item de `processes.snapshotBatch`. Só o `data`
100
+ * não traz a marca.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * const retrato = await lexnode.processes.snapshot(numero, {
105
+ * tribunalAlias: "TJSP",
106
+ * staleOnFailure: true,
107
+ * });
108
+ * const copia = lakeRescueOf(retrato);
109
+ * if (copia) {
110
+ * // o que andou depois de copia.sourceFetchedAt não está na resposta
111
+ * }
112
+ * ```
75
113
  */
76
114
  export declare function lakeRescueOf(result: unknown): LakeRescue | null;
77
115
  /**
78
- * Quando os dados servidos foram buscados na fonte: `meta.sourceFetchedAt` das
79
- * leituras de um processo, ou a data do item socorrido do lote.
116
+ * Quando os dados servidos foram buscados na fonte: `meta.sourceFetchedAt` da
117
+ * ficha e do retrato, ou a data da cópia guardada num item do lote. `null`
118
+ * quando a resposta não traz a data.
80
119
  */
81
120
  export declare function sourceFetchedAtOf(result: unknown): Date | null;
82
121
  /**
83
- * Uma frase em pt-BR sobre o frescor da resposta, pronta para a tela: a cópia
84
- * guardada e o porquê, quando o acervo socorreu a fonte; senão, até onde a
85
- * fonte foi lida.
122
+ * Devolve uma frase em português sobre o frescor da resposta, pronta para
123
+ * mostrar: a data da cópia guardada e o motivo, quando a fonte falhou; senão,
124
+ * até quando a fonte foi lida.
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * describeFreshness(retrato);
129
+ * // "cópia guardada em 26/09/2026, servida porque a fonte não respondeu a tempo"
130
+ * describeFreshness(busca);
131
+ * // "fonte lida até 10/09/2026"
132
+ * ```
86
133
  */
87
134
  export declare function describeFreshness(result: unknown): string;
package/dist/freshness.js CHANGED
@@ -1,23 +1,8 @@
1
- /**
2
- * Até onde a fonte foi lida — o que qualifica um resultado vazio.
3
- *
4
- * Um `total: 0` sozinho não distingue "não existe" de "a fonte ainda não
5
- * indexou". Quem confunde os dois diz ao usuário que o processo não existe e
6
- * repete a busca, pagando de novo por uma resposta que não pode mudar. O motor
7
- * publica a data-limite do índice em dois eixos — `updatedThrough` na busca de
8
- * processo, `lastEditionDate` na leitura do diário — e este módulo é a leitura
9
- * dos dois pelo mesmo nome.
10
- *
11
- * A leitura de UM processo diz também de quando são os dados servidos
12
- * (`meta.sourceFetchedAt`) e, quando a fonte falhou e o acervo socorreu, que a
13
- * resposta é a cópia guardada (`meta.lakeRescue`).
14
- */
15
1
  function asRecord(value) {
16
2
  return value && typeof value === "object" && !Array.isArray(value)
17
3
  ? value
18
4
  : null;
19
5
  }
20
- /** Aceita o envelope inteiro ou só o `data` — o consumidor tem os dois à mão. */
21
6
  function payloadOf(value) {
22
7
  const record = asRecord(value);
23
8
  if (!record)
@@ -27,15 +12,12 @@ function payloadOf(value) {
27
12
  function toDate(value) {
28
13
  if (typeof value !== "string" || !value)
29
14
  return null;
30
- // A data do diário vem como AAAA-MM-DD; lê-la sem fuso a jogaria para o dia
31
- // anterior em qualquer máquina a oeste de Greenwich.
32
15
  const iso = /^\d{4}-\d{2}-\d{2}$/u.test(value)
33
16
  ? `${value}T00:00:00.000Z`
34
17
  : value;
35
18
  const parsed = new Date(iso);
36
19
  return Number.isNaN(parsed.getTime()) ? null : parsed;
37
20
  }
38
- /** O retrato completo do frescor de uma resposta. */
39
21
  export function freshnessOf(result) {
40
22
  const payload = payloadOf(result);
41
23
  const sourceIndex = asRecord(payload?.sourceIndex);
@@ -62,7 +44,6 @@ export function freshnessOf(result) {
62
44
  : null,
63
45
  };
64
46
  }
65
- /** A data-limite do índice da fonte, ou `null` quando ela não a declarou. */
66
47
  export function readThrough(result) {
67
48
  return freshnessOf(result).readThrough;
68
49
  }
@@ -73,14 +54,6 @@ function hasResults(payload) {
73
54
  return true;
74
55
  return typeof payload.total === "number" && payload.total > 0;
75
56
  }
76
- /**
77
- * Se o vazio desta resposta NÃO prova ausência.
78
- *
79
- * Verdadeiro quando a fonte não declarou até onde leu (o estado indeterminado
80
- * — ausência de campo é estado, nunca erro) ou quando ela leu até antes de
81
- * `since`. Falso quando há resultado, e falso quando a fonte declarou uma
82
- * data-limite que cobre o que se perguntou: aí o vazio é resposta.
83
- */
84
57
  export function isNotYetIndexed(result, options = {}) {
85
58
  const payload = payloadOf(result);
86
59
  if (hasResults(payload))
@@ -106,11 +79,6 @@ function toInstant(value) {
106
79
  }
107
80
  return toDate(value);
108
81
  }
109
- /**
110
- * A marca do socorro e a data da cópia, onde quer que elas venham: no `meta`
111
- * do envelope das leituras de um processo, ou no item do lote de retratos,
112
- * que leva as duas em `lakeRescue`.
113
- */
114
82
  function rescueFieldsOf(result) {
115
83
  const record = asRecord(result);
116
84
  const meta = asRecord(record?.meta);
@@ -123,11 +91,6 @@ function rescueFieldsOf(result) {
123
91
  const itemRescue = asRecord(record?.lakeRescue);
124
92
  return { rescue: itemRescue, fetchedAt: itemRescue?.sourceFetchedAt };
125
93
  }
126
- /**
127
- * O socorro pelo acervo, ou `null` quando a resposta veio da fonte ou do
128
- * acervo em dia. Aceita o envelope inteiro (`{ data, meta }`) ou o item do
129
- * lote de retratos; só o `data` não traz a marca.
130
- */
131
94
  export function lakeRescueOf(result) {
132
95
  const { rescue, fetchedAt } = rescueFieldsOf(result);
133
96
  if (!rescue || typeof rescue.cause !== "string")
@@ -140,10 +103,6 @@ export function lakeRescueOf(result) {
140
103
  : null,
141
104
  };
142
105
  }
143
- /**
144
- * Quando os dados servidos foram buscados na fonte: `meta.sourceFetchedAt` das
145
- * leituras de um processo, ou a data do item socorrido do lote.
146
- */
147
106
  export function sourceFetchedAtOf(result) {
148
107
  return toInstant(rescueFieldsOf(result).fetchedAt);
149
108
  }
@@ -153,7 +112,6 @@ const BRASILIA_DATE = new Intl.DateTimeFormat("pt-BR", {
153
112
  year: "numeric",
154
113
  timeZone: "America/Sao_Paulo",
155
114
  });
156
- /** O dia de um instante no horário de Brasília, montado pelas partes. */
157
115
  function ddmmaaaaBrasilia(date) {
158
116
  const parts = Object.fromEntries(BRASILIA_DATE.formatToParts(date).map((part) => [part.type, part.value]));
159
117
  return `${parts.day}/${parts.month}/${parts.year}`;
@@ -168,11 +126,6 @@ function rescueReason(cause) {
168
126
  ? RESCUE_REASON[cause]
169
127
  : "falhou";
170
128
  }
171
- /**
172
- * Uma frase em pt-BR sobre o frescor da resposta, pronta para a tela: a cópia
173
- * guardada e o porquê, quando o acervo socorreu a fonte; senão, até onde a
174
- * fonte foi lida.
175
- */
176
129
  export function describeFreshness(result) {
177
130
  const rescue = lakeRescueOf(result);
178
131
  if (rescue) {
package/dist/index.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  /**
2
- * Cliente de runtime e tipos do contrato do motor de dados jurídicos.
2
+ * Cliente TypeScript da API do LexNode: chamadas tipadas pelo contrato
3
+ * OpenAPI, erros classificados, verificação de webhook e funções para busca,
4
+ * leitura de processo, paginação, frescor e vigília.
3
5
  *
4
- * **Servidor apenas.** A credencial é uma chave de CONTA: no browser ela está
5
- * publicada. Um app com usuários finais fala com o próprio backend, e é o
6
- * backend que fala com o motor, atribuindo cada chamada ao seu sub-tenant por
7
- * `X-Office-Id`.
6
+ * Use só no servidor. A chave de API é da conta inteira, e no browser ela
7
+ * fica exposta. Um app com usuários finais chama o próprio backend, e o
8
+ * backend chama a API, atribuindo cada chamada ao sub-tenant dela (um
9
+ * escritório, um usuário final) com `officeId` (cabeçalho `X-Office-Id`).
8
10
  *
9
- * Sem dependências de runtime: `fetch` global e `node:crypto`, Node >= 20.
11
+ * Requer Node 20 ou superior e não tem dependências de runtime.
12
+ *
13
+ * @packageDocumentation
10
14
  */
11
15
  export type * from "../schema.js";
12
16
  export { createLexNodeClient } from "./client.js";
package/dist/index.js CHANGED
@@ -1,13 +1,3 @@
1
- /**
2
- * Cliente de runtime e tipos do contrato do motor de dados jurídicos.
3
- *
4
- * **Servidor apenas.** A credencial é uma chave de CONTA: no browser ela está
5
- * publicada. Um app com usuários finais fala com o próprio backend, e é o
6
- * backend que fala com o motor, atribuindo cada chamada ao seu sub-tenant por
7
- * `X-Office-Id`.
8
- *
9
- * Sem dependências de runtime: `fetch` global e `node:crypto`, Node >= 20.
10
- */
11
1
  export { createLexNodeClient } from "./client.js";
12
2
  export { LEXNODE_ERROR_CODES, LexNodeError, isLexNodeError } from "./errors.js";
13
3
  export { DEFAULT_WEBHOOK_TOLERANCE_SECONDS, LEXNODE_WEBHOOK_HEADERS, WEBHOOK_EVENT_TYPES, WEBHOOK_TEST_EVENT_TYPE, isKnownWebhookEventType, isReceiverFault, isWebhookTest, parseWebhookEvent, verifyWebhookSignature, webhookRejectionStatus, } from "./webhooks.js";