@lexnode/legal-data-sdk 1.30.0 → 1.32.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/client.d.ts CHANGED
@@ -1,114 +1,307 @@
1
1
  import type { paths } from "../schema.js";
2
2
  import type { Body, CallOptions, LexNodeResult, MethodOf, Query, RequestArgs, RetryPolicy } from "./types.js";
3
+ /** As opções de `createLexNodeClient`. */
3
4
  export interface LexNodeClientOptions {
4
- /** Base da API, por exemplo `https://api.lexnode.com.br`. */
5
+ /**
6
+ * Endereço da API, por exemplo `https://api.lexnode.com.br`. Precisa usar
7
+ * https, exceto no host local (`localhost`, `127.0.0.1` ou `::1`).
8
+ */
5
9
  baseUrl: string;
6
10
  /**
7
- * Chave de CONTA (`Authorization: Bearer`). É credencial de servidor: ver o
8
- * aviso de `createLexNodeClient`.
11
+ * Chave de API da conta, enviada como `Authorization: Bearer`. Guarde-a só
12
+ * no servidor.
9
13
  */
10
14
  apiKey: string;
11
- /** Sub-tenant padrão (`X-Office-Id`). Cada chamada pode trocá-lo ou omiti-lo. */
15
+ /**
16
+ * Escritório (sub-tenant) atribuído a toda chamada, no cabeçalho
17
+ * `X-Office-Id`. Cada chamada pode trocá-lo ou omiti-lo em
18
+ * `CallOptions.officeId`.
19
+ */
12
20
  officeId?: string;
13
21
  /**
14
- * Prazo de cada chamada, em ms. Padrão: 30 s. A ficha e o retrato de um
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.
22
+ * Prazo de cada chamada, em ms. Padrão: 30 000. Na ficha e no retrato de um
23
+ * processo e em `processLookups.create`, o prazo é o maior entre este valor
24
+ * e a espera pela fonte mais 15 s — `waitSeconds` ou, sem ele, os 20 s
25
+ * padrão da API.
18
26
  */
19
27
  timeoutMs?: number;
20
- /** Transporte alternativo — o `fetch` global é o padrão. */
28
+ /** O `fetch` a usar no lugar do global, por exemplo num teste. */
21
29
  fetch?: typeof globalThis.fetch;
22
- /** Identifica a sua integração no `User-Agent`. */
30
+ /** Identifica a sua integração no cabeçalho `User-Agent`. */
23
31
  userAgent?: string;
24
- /** Política de retentativa padrão. Ausente = desligada. */
32
+ /** Política de retentativa de toda chamada. Sem ela, nada é repetido. */
25
33
  retry?: RetryPolicy;
26
34
  }
27
35
  /**
28
- * O cliente de runtime do motor de dados jurídicos.
36
+ * Cria o cliente da API do LexNode.
29
37
  *
30
- * **Servidor apenas, e só por TLS.** A credencial é de CONTA: uma chave no
31
- * browser é uma chave publicada, e uma chave em `http://` é uma chave lida por
32
- * quem estiver no caminho — `baseUrl` sem https é recusada aqui, exceto em
33
- * host local. Um app com usuários finais fala com o próprio backend, e é o
34
- * backend que fala com o motor — atribuindo cada chamada ao seu sub-tenant por
35
- * `X-Office-Id`.
38
+ * Toda chamada envia `Authorization: Bearer`, `X-Request-Id`, `X-Trace-Id` e,
39
+ * quando houver, `X-Office-Id`, e devolve `{ data, meta }` tipados pela rota.
40
+ * O `meta` traz, além do que o contrato declara, o código HTTP (`status`) e os
41
+ * cabeçalhos de limite de vazão (`rateLimit`). Toda recusa da API e toda falha
42
+ * de rede ou de prazo é lançada como `LexNodeError`.
36
43
  *
37
- * Sem dependências de runtime: `fetch` global e `node:crypto`.
44
+ * Use só no servidor: a chave é da conta inteira. Um app com usuários finais
45
+ * chama o próprio backend, e o backend chama a API.
46
+ *
47
+ * Lança `LexNodeError` (`CLIENT_INVALID_REQUEST`) quando `baseUrl` não é uma
48
+ * URL válida ou não usa https fora do host local.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const lexnode = createLexNodeClient({
53
+ * baseUrl: "https://api.lexnode.com.br",
54
+ * apiKey: process.env.LEXNODE_API_KEY!,
55
+ * });
56
+ *
57
+ * const { data, meta } = await lexnode.processes.get("00012345620268260100", {
58
+ * tribunalAlias: "TJSP",
59
+ * });
60
+ * ```
38
61
  */
39
62
  export declare function createLexNodeClient(options: LexNodeClientOptions): {
63
+ /**
64
+ * Chama qualquer rota do contrato, tipada pelo caminho e pelo método.
65
+ *
66
+ * Use para as rotas sem método nomeado neste cliente. Recebe os parâmetros
67
+ * de caminho e de consulta em `params`, o corpo em `body` e as opções de
68
+ * `CallOptions`; devolve `{ data, meta }` e lança `LexNodeError` como os
69
+ * métodos nomeados.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * const { data } = await lexnode.request("/v1/precedents", "get", {
74
+ * params: { query: { query: "dano moral", limit: 20 } },
75
+ * });
76
+ * ```
77
+ */
40
78
  request: <P extends keyof paths, M extends MethodOf<P>>(path: P, method: M, args: RequestArgs<P, M>) => Promise<LexNodeResult<P, M>>;
41
79
  tribunals: {
80
+ /**
81
+ * Lista os tribunais aceitos (`GET /v1/tribunals`). As demais rotas
82
+ * aceitam o tribunal pela sigla (`code`) que vem daqui.
83
+ */
42
84
  list: (query?: Query<"/v1/tribunals", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/tribunals", "get">>;
43
85
  };
44
86
  processes: {
87
+ /**
88
+ * Busca processos num tribunal (`POST /v1/processes/search`): 200 com o
89
+ * resultado ou 202 com a busca enfileirada. `searchProcesses` diz no
90
+ * tipo qual dos dois chegou.
91
+ */
45
92
  search: (body: Body<"/v1/processes/search", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/search", "post">>;
93
+ /**
94
+ * Lê a ficha de um processo (`GET /v1/processes/{processNumber}`).
95
+ * `waitSeconds` define quanto a API espera pela fonte processual; sem
96
+ * `timeoutMs`, o prazo da chamada acompanha essa espera.
97
+ */
46
98
  get: (processNumber: string, query: Query<"/v1/processes/{processNumber}", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/{processNumber}", "get">>;
99
+ /**
100
+ * Lista as movimentações guardadas de um processo, sem consultar a fonte
101
+ * (`GET /v1/processes/{processNumber}/movements`). `degree` recorta a
102
+ * lista por grau.
103
+ */
47
104
  movements: (processNumber: string, query: Query<"/v1/processes/{processNumber}/movements", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/{processNumber}/movements", "get">>;
105
+ /**
106
+ * Lê o retrato de um processo na fonte processual — o processo, as
107
+ * movimentações e as instâncias do número
108
+ * (`GET /v1/processes/{processNumber}/snapshot`). Como em `get`, o prazo
109
+ * da chamada acompanha `waitSeconds`.
110
+ */
48
111
  snapshot: (processNumber: string, query: Query<"/v1/processes/{processNumber}/snapshot", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/{processNumber}/snapshot", "get">>;
112
+ /**
113
+ * Lista processos relacionados ao consultado: o mesmo número em outro
114
+ * tribunal e números citados nas movimentações
115
+ * (`GET /v1/processes/{processNumber}/related`).
116
+ */
49
117
  related: (processNumber: string, query: Query<"/v1/processes/{processNumber}/related", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/{processNumber}/related", "get">>;
118
+ /**
119
+ * Lê o retrato de vários processos numa chamada
120
+ * (`POST /v1/processes/snapshot-batch`). Cada item traz o próprio
121
+ * resultado ou erro, e só os itens concluídos são cobrados.
122
+ */
50
123
  snapshotBatch: (body: Body<"/v1/processes/snapshot-batch", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/snapshot-batch", "post">>;
51
124
  };
52
125
  publications: {
126
+ /**
127
+ * Lista as publicações do diário que casam com os filtros
128
+ * (`GET /v1/publications`).
129
+ */
53
130
  list: (query?: Query<"/v1/publications", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications", "get">>;
131
+ /**
132
+ * Lê uma publicação completa pela chave que uma busca devolveu
133
+ * (`GET /v1/publications/{publicationKey}`), sem custo.
134
+ */
54
135
  read: (publicationKey: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications/{publicationKey}", "get">>;
136
+ /**
137
+ * Pesquisa jurisprudência por texto e guarda o resultado
138
+ * (`POST /v1/publications/text-searches`). Reenviar com o mesmo
139
+ * `requestId` devolve a busca já feita, sem nova cobrança.
140
+ */
55
141
  textSearch: (body: Body<"/v1/publications/text-searches", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications/text-searches", "post">>;
56
142
  textAlerts: {
143
+ /**
144
+ * Salva uma vigília de texto (`POST /v1/publications/text-alerts`),
145
+ * que avisa por `PUBLICATION_TEXT_ALERT_MATCHED` quando publicações
146
+ * novas casam com a consulta.
147
+ */
57
148
  create: (body: Body<"/v1/publications/text-alerts", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications/text-alerts", "post">>;
149
+ /**
150
+ * Lista as vigílias de texto da conta
151
+ * (`GET /v1/publications/text-alerts`).
152
+ */
58
153
  list: (query?: Query<"/v1/publications/text-alerts", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications/text-alerts", "get">>;
154
+ /**
155
+ * Remove uma vigília de texto
156
+ * (`DELETE /v1/publications/text-alerts/{alertId}`).
157
+ */
59
158
  delete: (alertId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/publications/text-alerts/{alertId}", "delete">>;
60
159
  };
61
160
  };
62
161
  monitors: {
162
+ /**
163
+ * Cria um monitor (`POST /v1/monitors`). Um alvo já vigiado é recusado
164
+ * com 409 `MONITOR_ALREADY_EXISTS`, e `error.details.monitorId` traz o
165
+ * id do monitor existente.
166
+ */
63
167
  create: (body: Body<"/v1/monitors", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors", "post">>;
168
+ /**
169
+ * Lista os monitores da conta (`GET /v1/monitors`); use `paginate` para
170
+ * percorrer as páginas.
171
+ */
64
172
  list: (query?: Query<"/v1/monitors", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors", "get">>;
173
+ /** Lê um monitor (`GET /v1/monitors/{monitorId}`). */
65
174
  get: (monitorId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors/{monitorId}", "get">>;
175
+ /**
176
+ * Muda o status de um monitor — `ACTIVE`, `PAUSED` ou `DISABLED`
177
+ * (`PATCH /v1/monitors/{monitorId}`).
178
+ */
66
179
  update: (monitorId: string, body: Body<"/v1/monitors/{monitorId}", "patch">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors/{monitorId}", "patch">>;
180
+ /** Exclui um monitor (`DELETE /v1/monitors/{monitorId}`). */
67
181
  delete: (monitorId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors/{monitorId}", "delete">>;
182
+ /**
183
+ * Pede uma varredura do monitor sem esperar a agenda
184
+ * (`POST /v1/monitors/{monitorId}/sync`). O resultado chega em
185
+ * `MONITOR_SYNC_SUCCEEDED` ou `MONITOR_SYNC_FAILED`.
186
+ */
68
187
  sync: (monitorId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/monitors/{monitorId}/sync", "post">>;
69
188
  };
70
189
  subscriptions: {
190
+ /**
191
+ * Declara interesse num processo (`POST /v1/subscriptions`). A conta
192
+ * passa a receber `PROCESS_MOVEMENT_CREATED`, com o `externalRef`
193
+ * informado, e `PROCESS_INSTANCE_DISCOVERED`. Repetir com o mesmo
194
+ * `reason` e `externalRef` devolve a mesma assinatura.
195
+ */
71
196
  create: (body: Body<"/v1/subscriptions", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/subscriptions", "post">>;
197
+ /** Lista as assinaturas da conta (`GET /v1/subscriptions`). */
72
198
  list: (query?: Query<"/v1/subscriptions", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/subscriptions", "get">>;
199
+ /**
200
+ * Desativa as assinaturas da conta e do escritório da chamada que têm o
201
+ * `reason` e o `externalRef` informados (`DELETE /v1/subscriptions`).
202
+ */
73
203
  delete: (body: Body<"/v1/subscriptions", "delete">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/subscriptions", "delete">>;
74
204
  };
75
205
  processLookups: {
76
206
  /**
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.
207
+ * Lê um processo e segue em segundo plano quando a fonte não entrega
208
+ * dentro de `waitSeconds` (`POST /v1/processes/lookups`): 200 com o
209
+ * processo, ou 202 com a consulta aberta. Pedir a mesma leitura de novo
210
+ * devolve a mesma consulta, então a retentativa vale para esta chamada
211
+ * como para uma leitura. `lookupProcess` diz no tipo qual dos dois
212
+ * desfechos chegou.
82
213
  */
83
214
  create: (body: Body<"/v1/processes/lookups", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups", "post">>;
215
+ /**
216
+ * Lê uma consulta em segundo plano, sem custo
217
+ * (`GET /v1/processes/lookups/{lookupId}`).
218
+ */
84
219
  get: (lookupId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups/{lookupId}", "get">>;
220
+ /** Lista as consultas em segundo plano (`GET /v1/processes/lookups`). */
85
221
  list: (query?: Query<"/v1/processes/lookups", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups", "get">>;
222
+ /**
223
+ * Cancela uma consulta aberta e devolve os créditos retidos
224
+ * (`POST /v1/processes/lookups/{lookupId}/cancel`).
225
+ */
86
226
  cancel: (lookupId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/processes/lookups/{lookupId}/cancel", "post">>;
87
227
  };
88
228
  searchJobs: {
229
+ /** Lê uma busca enfileirada (`GET /v1/search-jobs/{jobId}`). */
89
230
  get: (jobId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/search-jobs/{jobId}", "get">>;
231
+ /** Lista as buscas enfileiradas (`GET /v1/search-jobs`). */
90
232
  list: (query?: Query<"/v1/search-jobs", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/search-jobs", "get">>;
233
+ /**
234
+ * Cancela uma busca que ainda não terminou e devolve os créditos
235
+ * retidos (`POST /v1/search-jobs/{jobId}/cancel`).
236
+ */
91
237
  cancel: (jobId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/search-jobs/{jobId}/cancel", "post">>;
92
238
  };
93
239
  events: {
240
+ /**
241
+ * Lista os eventos da conta, do mais recente ao mais antigo, com o
242
+ * estado de entrega de cada um (`GET /v1/events`).
243
+ */
94
244
  list: (query?: Query<"/v1/events", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/events", "get">>;
245
+ /** Lê um evento (`GET /v1/events/{eventId}`). */
95
246
  get: (eventId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/events/{eventId}", "get">>;
96
247
  };
97
248
  usage: {
249
+ /**
250
+ * Lê o uso do período: créditos usados e restantes, e o consumo por
251
+ * escritório (`GET /v1/usage`).
252
+ */
98
253
  get: (query?: Query<"/v1/usage", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/usage", "get">>;
99
254
  };
100
255
  webhooks: {
101
256
  endpoints: {
257
+ /** Lista os endpoints de webhook (`GET /v1/webhooks/endpoints`). */
102
258
  list: (query?: Query<"/v1/webhooks/endpoints", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints", "get">>;
259
+ /**
260
+ * Cadastra um endpoint de webhook (`POST /v1/webhooks/endpoints`). O
261
+ * segredo de assinatura vem só nesta resposta, em `signingSecret`:
262
+ * guarde-o.
263
+ */
103
264
  create: (body: Body<"/v1/webhooks/endpoints", "post">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints", "post">>;
265
+ /**
266
+ * Altera um endpoint, como a URL ou os eventos assinados
267
+ * (`PATCH /v1/webhooks/endpoints/{endpointId}`).
268
+ */
104
269
  update: (endpointId: string, body: Body<"/v1/webhooks/endpoints/{endpointId}", "patch">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints/{endpointId}", "patch">>;
270
+ /**
271
+ * Exclui um endpoint
272
+ * (`DELETE /v1/webhooks/endpoints/{endpointId}`).
273
+ */
105
274
  delete: (endpointId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints/{endpointId}", "delete">>;
275
+ /**
276
+ * Envia na hora uma entrega de teste (`WEBHOOK_TEST`) ao endpoint e
277
+ * devolve o resultado
278
+ * (`POST /v1/webhooks/endpoints/{endpointId}/test`).
279
+ */
106
280
  test: (endpointId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints/{endpointId}/test", "post">>;
281
+ /**
282
+ * Gera um novo segredo de assinatura e invalida o anterior na hora
283
+ * (`POST /v1/webhooks/endpoints/{endpointId}/rotate-secret`). Atualize
284
+ * o seu receptor com o segredo novo, que vem só nesta resposta.
285
+ */
107
286
  rotateSecret: (endpointId: string, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/endpoints/{endpointId}/rotate-secret", "post">>;
108
287
  };
288
+ /**
289
+ * Lista as entregas de webhook da conta
290
+ * (`GET /v1/webhooks/deliveries`).
291
+ */
109
292
  deliveries: (query?: Query<"/v1/webhooks/deliveries", "get">, opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/deliveries", "get">>;
293
+ /**
294
+ * Lê a fila e as entregas e falhas das últimas 24 h de cada endpoint
295
+ * (`GET /v1/webhooks/health`).
296
+ */
110
297
  health: (opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/health", "get">>;
298
+ /**
299
+ * Lista os tipos de evento que a conta produziu nos últimos 30 dias e
300
+ * que nenhum endpoint ativo assina
301
+ * (`GET /v1/webhooks/unsubscribed-event-types`).
302
+ */
111
303
  unsubscribedEventTypes: (opts?: CallOptions) => Promise<LexNodeResult<"/v1/webhooks/unsubscribed-event-types", "get">>;
112
304
  };
113
305
  };
306
+ /** O cliente que `createLexNodeClient` devolve. */
114
307
  export type LexNodeClient = ReturnType<typeof createLexNodeClient>;
package/dist/client.js CHANGED
@@ -3,49 +3,19 @@ import { LexNodeError } from "./errors.js";
3
3
  const DEFAULT_TIMEOUT_MS = 30_000;
4
4
  const DEFAULT_RETRY_BASE_DELAY_MS = 500;
5
5
  const DEFAULT_RETRY_MAX_DELAY_MS = 8_000;
6
- /** Métodos cuja repetição não cria nada de novo, por definição do HTTP. */
7
6
  const IDEMPOTENT_METHODS = new Set(["get", "delete"]);
8
- /**
9
- * As escritas cuja repetição o CONTRATO declara segura, com o `X-Request-Id`
10
- * fixado pelo chamador.
11
- *
12
- * Só uma rota trata esse cabeçalho como chave de replay; nas demais ele é
13
- * rastreio, e repetir cria um segundo recurso — dois endpoints de webhook para
14
- * a mesma URL entregam cada evento em dobro, e o segredo do primeiro fica
15
- * órfão. Por isso a decisão é pela ROTA, nunca pela presença de um id.
16
- */
17
7
  const REQUEST_ID_IDEMPOTENT_WRITES = new Set([
18
8
  "post /v1/publications/text-searches",
19
9
  ]);
20
- /**
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.
24
- */
25
10
  const SOURCE_WAIT_ROUTES = new Map([
26
11
  ["get /v1/processes/{processNumber}", "query"],
27
12
  ["get /v1/processes/{processNumber}/snapshot", "query"],
28
13
  ["post /v1/processes/lookups", "body"],
29
14
  ]);
30
- /**
31
- * A espera que o motor aplica a essas leituras quando a chamada não traz
32
- * `waitSeconds`: o padrão do parâmetro no contrato.
33
- */
34
15
  const SOURCE_WAIT_API_DEFAULT_SECONDS = 20;
35
- /**
36
- * O que a chamada espera além da espera do motor: na ficha, até 10 s de
37
- * enriquecimento depois da fonte, e a rede.
38
- */
39
16
  const SOURCE_WAIT_MARGIN_MS = 15_000;
40
- /** O que um valor de cabeçalho não pode conter: `fetch` recusa montá-lo. */
41
17
  const FORBIDDEN_HEADER_CHARS = /[\r\n\0]/u;
42
- /** Hosts em que falar claro é desenvolvimento, não credencial exposta. */
43
18
  const LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "[::1]", "::1"]);
44
- /**
45
- * A chave é de CONTA e viaja em todo pedido: sem TLS ela vai em texto claro
46
- * para quem estiver no caminho. É a mesma recusa que o motor aplica à própria
47
- * URL de produção — só o host local fica de fora, porque ali não há caminho.
48
- */
49
19
  function requireSecureBaseUrl(baseUrl) {
50
20
  let parsed;
51
21
  try {
@@ -65,12 +35,6 @@ function readHeaderNumber(headers, name) {
65
35
  const parsed = Number(raw);
66
36
  return Number.isFinite(parsed) ? parsed : null;
67
37
  }
68
- /**
69
- * O teto por minuto sai em TODA resposta autenticada, não só na recusa. Lê-lo
70
- * no sucesso é o que permite ao consumidor desacelerar ANTES de bater no 429.
71
- * O `Retry-After` só conta na recusa: no sucesso ele é a espera que a fonte
72
- * pediu a uma leitura socorrida pelo acervo, e sai em `meta.lakeRescue`.
73
- */
74
38
  function readRateLimit(headers, succeeded) {
75
39
  const limit = readHeaderNumber(headers, "RateLimit-Limit");
76
40
  const remaining = readHeaderNumber(headers, "RateLimit-Remaining");
@@ -111,14 +75,6 @@ function appendQuery(url, query) {
111
75
  }
112
76
  }
113
77
  }
114
- /**
115
- * O prazo da chamada que não trouxe `timeoutMs` próprio.
116
- *
117
- * Numa leitura que espera pela fonte, o motor pode levar a espera inteira
118
- * antes de responder — a de `waitSeconds` ou, sem ele, a padrão da API: o
119
- * prazo cobre essa espera mais a margem e nunca fica abaixo do prazo do
120
- * cliente. Nas outras rotas, vale o prazo do cliente.
121
- */
122
78
  function defaultCallTimeoutMs(method, path, carriers, clientTimeoutMs) {
123
79
  const carrier = SOURCE_WAIT_ROUTES.get(`${method} ${path}`);
124
80
  if (!carrier)
@@ -132,15 +88,6 @@ function defaultCallTimeoutMs(method, path, carriers, clientTimeoutMs) {
132
88
  : SOURCE_WAIT_API_DEFAULT_SECONDS;
133
89
  return Math.max(clientTimeoutMs, waitSeconds * 1_000 + SOURCE_WAIT_MARGIN_MS);
134
90
  }
135
- /**
136
- * Junta o prazo do cliente ao `signal` de quem chamou.
137
- *
138
- * Os dois abortam a mesma requisição, e trocar um pelo outro perde metade do
139
- * controle: sem o prazo, uma chamada sem resposta fica pendurada; sem o sinal
140
- * de quem chamou, o cancelamento da requisição de cima não alcança a de baixo.
141
- * O motivo do aborto é preservado para o prazo virar 504 e o cancelamento de
142
- * fora continuar sendo cancelamento.
143
- */
144
91
  function linkAbort(timeoutMs, caller) {
145
92
  const controller = new AbortController();
146
93
  let timedOut = false;
@@ -184,19 +131,6 @@ function sleep(ms, signal) {
184
131
  signal?.addEventListener("abort", onAbort, { once: true });
185
132
  });
186
133
  }
187
- /**
188
- * Se vale repetir esta chamada.
189
- *
190
- * A classe do erro diz se a condição passa sozinha; o método e a ROTA dizem se
191
- * repetir é seguro. Uma escrita fora da lista só é repetida quando quem chama
192
- * declara `idempotent: true` — quem conhece o próprio uso pode afirmar o que o
193
- * contrato não afirma, mas a afirmação é dele, e explícita.
194
- *
195
- * O tempo esgotado da fonte (`UPSTREAM_TIMEOUT`) numa leitura que espera por
196
- * ela não se repete: o motor já esperou tudo o que a chamada pediu, e repetir
197
- * na hora dobra a espera diante da mesma fonte lenta. As demais recusas
198
- * retentáveis dessas leituras seguem a política.
199
- */
200
134
  function mayRetry(error, method, path, options) {
201
135
  if (!(error instanceof LexNodeError) || !error.retryable)
202
136
  return false;
@@ -213,22 +147,11 @@ function mayRetry(error, method, path, options) {
213
147
  }
214
148
  function retryDelayMs(policy, attempt, error) {
215
149
  if (error.retryAfterSeconds !== null && error.retryAfterSeconds >= 0) {
216
- return Math.min(error.retryAfterSeconds * 1_000, policy.maxDelayMs);
150
+ const asked = error.retryAfterSeconds * 1_000;
151
+ return asked > policy.maxDelayMs ? null : asked;
217
152
  }
218
153
  return Math.min(policy.baseDelayMs * 2 ** (attempt - 1), policy.maxDelayMs);
219
154
  }
220
- /**
221
- * O cliente de runtime do motor de dados jurídicos.
222
- *
223
- * **Servidor apenas, e só por TLS.** A credencial é de CONTA: uma chave no
224
- * browser é uma chave publicada, e uma chave em `http://` é uma chave lida por
225
- * quem estiver no caminho — `baseUrl` sem https é recusada aqui, exceto em
226
- * host local. Um app com usuários finais fala com o próprio backend, e é o
227
- * backend que fala com o motor — atribuindo cada chamada ao seu sub-tenant por
228
- * `X-Office-Id`.
229
- *
230
- * Sem dependências de runtime: `fetch` global e `node:crypto`.
231
- */
232
155
  export function createLexNodeClient(options) {
233
156
  requireSecureBaseUrl(options.baseUrl);
234
157
  const baseUrl = options.baseUrl.replace(/\/+$/u, "");
@@ -251,9 +174,6 @@ export function createLexNodeClient(options) {
251
174
  headers["user-agent"] = options.userAgent;
252
175
  if (bag.body !== undefined)
253
176
  headers["content-type"] = "application/json";
254
- // Cabeçalho e corpo são montados ANTES de abrir o socket: o que o
255
- // transporte recusa montar é defeito do pedido, não falha passageira de
256
- // rede, e repetir o que nunca saiu só gasta as tentativas.
257
177
  for (const [name, value] of Object.entries(headers)) {
258
178
  if (FORBIDDEN_HEADER_CHARS.test(value)) {
259
179
  throw LexNodeError.invalidRequest(`O cabeçalho ${name} tem quebra de linha ou caractere nulo.`);
@@ -278,20 +198,14 @@ export function createLexNodeClient(options) {
278
198
  headers,
279
199
  body: payload,
280
200
  signal: link.signal,
281
- // O contrato não redireciona; seguir um 30x entregaria ao consumidor o
282
- // corpo de outro host como se fosse a resposta do motor.
283
201
  redirect: "error",
284
202
  });
285
203
  rateLimit = readRateLimit(response.headers, response.ok);
286
- // A leitura do corpo fica DENTRO do prazo: um corpo que trava depois dos
287
- // cabeçalhos pendura a chamada por tempo indefinido se o vínculo já tiver
288
- // sido desfeito aqui.
289
204
  raw = await response.text();
290
205
  }
291
206
  catch (error) {
292
207
  if (link.timedOut)
293
208
  throw LexNodeError.timeout(timeoutMs, error);
294
- // Cancelamento de quem chamou não é falha da API: sobe como veio.
295
209
  if (args.signal?.aborted)
296
210
  throw error;
297
211
  throw LexNodeError.network(error);
@@ -324,13 +238,6 @@ export function createLexNodeClient(options) {
324
238
  },
325
239
  };
326
240
  }
327
- /**
328
- * A chamada genérica, tipada pela rota e pelo método do contrato.
329
- *
330
- * Uma função cobre a superfície inteira: rota nova ou campo novo no
331
- * `openapi.json` chega tipado sem uma linha a mais aqui. Os métodos nomeados
332
- * abaixo só dão nome ao que um consumidor usa todo dia.
333
- */
334
241
  async function request(path, method, args) {
335
242
  const requestId = args.requestId ?? `req_${randomUUID()}`;
336
243
  const traceId = args.traceId ?? `trc_${randomUUID()}`;
@@ -354,7 +261,10 @@ export function createLexNodeClient(options) {
354
261
  })) {
355
262
  throw error;
356
263
  }
357
- await sleep(retryDelayMs(delays, round, error), args.signal);
264
+ const delay = retryDelayMs(delays, round, error);
265
+ if (delay === null)
266
+ throw error;
267
+ await sleep(delay, args.signal);
358
268
  round += 1;
359
269
  }
360
270
  }
@@ -430,13 +340,6 @@ export function createLexNodeClient(options) {
430
340
  delete: (body, opts = {}) => request("/v1/subscriptions", "delete", { body, ...opts }),
431
341
  },
432
342
  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
343
  create: (body, opts = {}) => request("/v1/processes/lookups", "post", {
441
344
  body,
442
345
  idempotent: true,