@radardata/sdk 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +202 -2
- package/dist/cjs/configuracao.js +28 -0
- package/dist/cjs/configuracao.js.map +1 -0
- package/dist/cjs/dados.js +44 -0
- package/dist/cjs/dados.js.map +1 -0
- package/dist/cjs/erros.js +86 -0
- package/dist/cjs/erros.js.map +1 -0
- package/dist/cjs/index.js +69 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/recursos/analises.js +53 -0
- package/dist/cjs/recursos/analises.js.map +1 -0
- package/dist/cjs/recursos/catalogo.js +21 -0
- package/dist/cjs/recursos/catalogo.js.map +1 -0
- package/dist/cjs/recursos/consultas.js +33 -0
- package/dist/cjs/recursos/consultas.js.map +1 -0
- package/dist/cjs/recursos/verify.js +39 -0
- package/dist/cjs/recursos/verify.js.map +1 -0
- package/dist/cjs/recursos/webhooks.js +45 -0
- package/dist/cjs/recursos/webhooks.js.map +1 -0
- package/dist/cjs/transporte.js +128 -0
- package/dist/cjs/transporte.js.map +1 -0
- package/dist/cjs/webhooks/assinatura.js +65 -0
- package/dist/cjs/webhooks/assinatura.js.map +1 -0
- package/dist/esm/configuracao.d.ts +27 -0
- package/dist/esm/configuracao.d.ts.map +1 -0
- package/dist/esm/configuracao.js +23 -0
- package/dist/esm/configuracao.js.map +1 -0
- package/dist/esm/dados.d.ts +59 -0
- package/dist/esm/dados.d.ts.map +1 -0
- package/dist/esm/dados.js +38 -0
- package/dist/esm/dados.js.map +1 -0
- package/dist/esm/erros.d.ts +53 -0
- package/dist/esm/erros.d.ts.map +1 -0
- package/dist/esm/erros.js +73 -0
- package/dist/esm/erros.js.map +1 -0
- package/dist/esm/index.d.ts +41 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +47 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/recursos/analises.d.ts +25 -0
- package/dist/esm/recursos/analises.d.ts.map +1 -0
- package/dist/esm/recursos/analises.js +49 -0
- package/dist/esm/recursos/analises.js.map +1 -0
- package/dist/esm/recursos/catalogo.d.ts +11 -0
- package/dist/esm/recursos/catalogo.d.ts.map +1 -0
- package/dist/esm/recursos/catalogo.js +17 -0
- package/dist/esm/recursos/catalogo.js.map +1 -0
- package/dist/esm/recursos/consultas.d.ts +22 -0
- package/dist/esm/recursos/consultas.d.ts.map +1 -0
- package/dist/esm/recursos/consultas.js +29 -0
- package/dist/esm/recursos/consultas.js.map +1 -0
- package/dist/esm/recursos/verify.d.ts +25 -0
- package/dist/esm/recursos/verify.d.ts.map +1 -0
- package/dist/esm/recursos/verify.js +35 -0
- package/dist/esm/recursos/verify.js.map +1 -0
- package/dist/esm/recursos/webhooks.d.ts +27 -0
- package/dist/esm/recursos/webhooks.d.ts.map +1 -0
- package/dist/esm/recursos/webhooks.js +41 -0
- package/dist/esm/recursos/webhooks.js.map +1 -0
- package/dist/esm/transporte.d.ts +35 -0
- package/dist/esm/transporte.d.ts.map +1 -0
- package/dist/esm/transporte.js +123 -0
- package/dist/esm/transporte.js.map +1 -0
- package/dist/esm/webhooks/assinatura.d.ts +32 -0
- package/dist/esm/webhooks/assinatura.d.ts.map +1 -0
- package/dist/esm/webhooks/assinatura.js +61 -0
- package/dist/esm/webhooks/assinatura.js.map +1 -0
- package/package.json +46 -4
- package/src/configuracao.ts +50 -0
- package/src/dados.ts +93 -0
- package/src/erros.ts +70 -0
- package/src/index.ts +66 -0
- package/src/recursos/analises.ts +61 -0
- package/src/recursos/catalogo.ts +17 -0
- package/src/recursos/consultas.ts +32 -0
- package/src/recursos/verify.ts +40 -0
- package/src/recursos/webhooks.ts +43 -0
- package/src/transporte.ts +145 -0
- package/src/webhooks/assinatura.ts +72 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Webhooks = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Para onde mandamos os eventos, e o segredo que os assina.
|
|
6
|
+
*
|
|
7
|
+
* Escopo `webhooks`, que e proposital e separado: de a um token de
|
|
8
|
+
* PROVISIONAMENTO, nao ao token que o seu servidor usa todo dia. Quem tem
|
|
9
|
+
* este escopo pode redirecionar os seus eventos. O token padrao NAO o tem, e
|
|
10
|
+
* por isso estas chamadas devolvem `SemEscopo` com um token comum.
|
|
11
|
+
*/
|
|
12
|
+
class Webhooks {
|
|
13
|
+
t;
|
|
14
|
+
constructor(t) {
|
|
15
|
+
this.t = t;
|
|
16
|
+
}
|
|
17
|
+
/** Destino atual e o PREFIXO do segredo, nunca o segredo. */
|
|
18
|
+
async atual() {
|
|
19
|
+
return this.t.pedir("GET", "webhooks");
|
|
20
|
+
}
|
|
21
|
+
async definir(url, eventos = []) {
|
|
22
|
+
const corpo = { url };
|
|
23
|
+
if (eventos.length > 0)
|
|
24
|
+
corpo.eventos = eventos;
|
|
25
|
+
return this.t.pedir("PUT", "webhooks", { corpo });
|
|
26
|
+
}
|
|
27
|
+
async remover() {
|
|
28
|
+
return this.t.pedir("DELETE", "webhooks");
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Gira o segredo e devolve o novo, UMA unica vez.
|
|
32
|
+
*
|
|
33
|
+
* Guarde na hora: a consulta nunca mais mostra o valor inteiro. E lembre
|
|
34
|
+
* que girar invalida a assinatura dos avisos em voo.
|
|
35
|
+
*/
|
|
36
|
+
async girarSegredo() {
|
|
37
|
+
return this.t.pedir("POST", "webhooks/secret/rotate");
|
|
38
|
+
}
|
|
39
|
+
/** Dispara um evento de teste para o seu endpoint. */
|
|
40
|
+
async testar(url) {
|
|
41
|
+
return this.t.pedir("POST", "webhooks/testar", { corpo: url ? { url } : null });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.Webhooks = Webhooks;
|
|
45
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../src/recursos/webhooks.ts"],"names":[],"mappings":";;;AAEA;;;;;;;GAOG;AACH,MAAa,QAAQ;IACU;IAA7B,YAA6B,CAAa;QAAb,MAAC,GAAD,CAAC,CAAY;IAAG,CAAC;IAE9C,6DAA6D;IAC7D,KAAK,CAAC,KAAK;QACT,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,UAAoB,EAAE;QAC/C,MAAM,KAAK,GAA4B,EAAE,GAAG,EAAE,CAAC;QAC/C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC;QAChD,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,YAAY;QAChB,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;IACxD,CAAC;IAED,sDAAsD;IACtD,KAAK,CAAC,MAAM,CAAC,GAAY;QACvB,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAClF,CAAC;CACF;AAhCD,4BAgCC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Transporte = void 0;
|
|
4
|
+
exports.chaveIdempotencia = chaveIdempotencia;
|
|
5
|
+
const configuracao_js_1 = require("./configuracao.js");
|
|
6
|
+
const erros_js_1 = require("./erros.js");
|
|
7
|
+
/**
|
|
8
|
+
* O transporte: fala HTTP com a `/api/v2` e traduz resposta em dado ou erro.
|
|
9
|
+
*
|
|
10
|
+
* Tres decisoes que valem o comentario, porque sao as que diferenciam um SDK
|
|
11
|
+
* de um `fetch` embrulhado:
|
|
12
|
+
*
|
|
13
|
+
* 1. RETRY SO ONDE E SEGURO. A api aceita `Idempotency-Key` em consulta,
|
|
14
|
+
* analise e operacao, e e so nessas que repetir e seguro: a mesma chave
|
|
15
|
+
* devolve a mesma resposta em vez de cobrar de novo. Criar sessao de
|
|
16
|
+
* Verify NAO tem idempotencia, entao repetir ali criaria uma segunda
|
|
17
|
+
* sessao faturavel. Por isso o retry nao e uma opcao global: ele e ligado
|
|
18
|
+
* por chamada, e so quando o SDK manda a chave.
|
|
19
|
+
* 2. A CHAVE E GERADA PELO SDK quando quem chama nao passa uma. Deixar isso
|
|
20
|
+
* para o integrador significa, na pratica, ninguem usar, e e justamente o
|
|
21
|
+
* caso em que a falha doi: timeout numa consulta paga.
|
|
22
|
+
* 3. FALHA SEM RESPOSTA NAO E ERRO DE SERVIDOR. `FalhaDeRede` existe porque
|
|
23
|
+
* nesse caso nao se sabe se a operacao aconteceu, e a acao correta e
|
|
24
|
+
* consultar pela chave, nao repetir as cegas.
|
|
25
|
+
*/
|
|
26
|
+
class Transporte {
|
|
27
|
+
config;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
}
|
|
31
|
+
async pedir(metodo, caminho, opcoes = {}) {
|
|
32
|
+
const { corpo, query, chaveIdempotencia } = opcoes;
|
|
33
|
+
const cabecalhos = {
|
|
34
|
+
Authorization: `Bearer ${this.config.token}`,
|
|
35
|
+
Accept: "application/json",
|
|
36
|
+
"User-Agent": (0, configuracao_js_1.userAgent)(),
|
|
37
|
+
};
|
|
38
|
+
// Repetir so e seguro com a chave: sem ela, uma consulta cobrada duas
|
|
39
|
+
// vezes seria dinheiro do cliente.
|
|
40
|
+
const podeRepetir = typeof chaveIdempotencia === "string" && chaveIdempotencia !== "";
|
|
41
|
+
if (podeRepetir)
|
|
42
|
+
cabecalhos["Idempotency-Key"] = chaveIdempotencia;
|
|
43
|
+
if (corpo != null)
|
|
44
|
+
cabecalhos["Content-Type"] = "application/json";
|
|
45
|
+
let url = `${this.config.base}/${caminho.replace(/^\/+/, "")}`;
|
|
46
|
+
if (query) {
|
|
47
|
+
const q = new URLSearchParams();
|
|
48
|
+
for (const [k, v] of Object.entries(query))
|
|
49
|
+
if (v !== undefined)
|
|
50
|
+
q.set(k, String(v));
|
|
51
|
+
if ([...q].length > 0)
|
|
52
|
+
url += `?${q.toString()}`;
|
|
53
|
+
}
|
|
54
|
+
const tentativas = podeRepetir ? this.config.tentativas : 1;
|
|
55
|
+
let ultimo = null;
|
|
56
|
+
for (let i = 1; i <= tentativas; i++) {
|
|
57
|
+
const abortar = new AbortController();
|
|
58
|
+
const relogio = setTimeout(() => abortar.abort(), this.config.timeoutMs);
|
|
59
|
+
let resposta;
|
|
60
|
+
try {
|
|
61
|
+
resposta = await this.config.fetch(url, {
|
|
62
|
+
method: metodo,
|
|
63
|
+
headers: cabecalhos,
|
|
64
|
+
body: corpo != null ? JSON.stringify(corpo) : undefined,
|
|
65
|
+
signal: abortar.signal,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
ultimo = new erros_js_1.FalhaDeRede(`Não foi possível falar com o RadarData: ${e instanceof Error ? e.message : String(e)}`, "falha_de_rede", null, {}, { cause: e });
|
|
70
|
+
if (i < tentativas) {
|
|
71
|
+
await this.esperar(i);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw ultimo;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
clearTimeout(relogio);
|
|
78
|
+
}
|
|
79
|
+
// 429 e 5xx valem nova tentativa; o resto e resposta final.
|
|
80
|
+
if ((resposta.status === 429 || resposta.status >= 500) && i < tentativas) {
|
|
81
|
+
await this.esperar(i, resposta);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
return (await this.interpretar(resposta));
|
|
85
|
+
}
|
|
86
|
+
throw ultimo ?? new erros_js_1.ErroRadarData("Falha desconhecida no transporte.");
|
|
87
|
+
}
|
|
88
|
+
async interpretar(resposta) {
|
|
89
|
+
const cru = await resposta.text();
|
|
90
|
+
let json;
|
|
91
|
+
try {
|
|
92
|
+
json = cru === "" ? {} : JSON.parse(cru);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
json = {};
|
|
96
|
+
}
|
|
97
|
+
const corpo = (json ?? {});
|
|
98
|
+
if (resposta.ok) {
|
|
99
|
+
// `data` quando a rota embrulha (catalogo, saldo, analises) e o corpo
|
|
100
|
+
// inteiro quando nao (sessao de Verify). Devolver sempre o conteudo
|
|
101
|
+
// util poupa quem chama de saber qual rota faz o que.
|
|
102
|
+
return "data" in corpo && corpo.data !== null && typeof corpo.data === "object" ? corpo.data : corpo;
|
|
103
|
+
}
|
|
104
|
+
const erro = (corpo.error ?? {});
|
|
105
|
+
const mensagem = erro.message ?? corpo.message ?? `O RadarData respondeu ${resposta.status} sem detalhe.`;
|
|
106
|
+
throw (0, erros_js_1.erroDoStatus)(resposta.status, mensagem, erro.code ?? null, corpo);
|
|
107
|
+
}
|
|
108
|
+
/** Espera entre tentativas, respeitando `Retry-After` quando ele vem. */
|
|
109
|
+
async esperar(tentativa, resposta) {
|
|
110
|
+
const cabecalho = Number(resposta?.headers.get("Retry-After") ?? 0);
|
|
111
|
+
if (cabecalho > 0) {
|
|
112
|
+
await new Promise((r) => setTimeout(r, Math.min(cabecalho, 30) * 1000));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Recuo exponencial com um pouco de aleatorio, para muitos clientes
|
|
116
|
+
// falhando juntos nao voltarem todos no mesmo instante.
|
|
117
|
+
const base = Math.min(8, 2 ** (tentativa - 1));
|
|
118
|
+
await new Promise((r) => setTimeout(r, base * 1000 + Math.random() * 250));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.Transporte = Transporte;
|
|
122
|
+
/** Chave nova de idempotencia, no formato que a api aceita. */
|
|
123
|
+
function chaveIdempotencia() {
|
|
124
|
+
const bytes = new Uint8Array(16);
|
|
125
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
126
|
+
return [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=transporte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transporte.js","sourceRoot":"","sources":["../../src/transporte.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.confereAssinatura = confereAssinatura;
|
|
4
|
+
exports.exigirAssinatura = exigirAssinatura;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
/**
|
|
7
|
+
* Confere que o webhook veio mesmo do RadarData.
|
|
8
|
+
*
|
|
9
|
+
* Mandamos `X-RadarData-Signature: sha256=<hmac do CORPO CRU com o seu
|
|
10
|
+
* webhook_secret>`, mais `X-RadarData-Event`, `X-RadarData-Delivery` e
|
|
11
|
+
* `X-RadarData-Timestamp`.
|
|
12
|
+
*
|
|
13
|
+
* Aceita `string` ou `Uint8Array`, e nao `Buffer`, de proposito: `Buffer` e um
|
|
14
|
+
* global do Node e poria `@types/node` na superficie publica do pacote, o que
|
|
15
|
+
* quebra o `tsc` de quem compila para borda, Deno ou navegador. `Buffer` E um
|
|
16
|
+
* `Uint8Array`, entao o que o `express.raw()` entrega continua servindo.
|
|
17
|
+
*
|
|
18
|
+
* O CORPO TEM DE SER O CRU. Em Express e `express.raw()`, nao `express.json()`;
|
|
19
|
+
* reserializar o objeto ja decodificado muda espaco e ordem de chave, o HMAC
|
|
20
|
+
* muda junto e a conferencia falha sem motivo aparente. E o erro mais comum
|
|
21
|
+
* nesta parte, em qualquer integracao.
|
|
22
|
+
*
|
|
23
|
+
* LIMITE QUE VOCE PRECISA CONHECER: o timestamp e o id de entrega viajam em
|
|
24
|
+
* CABECALHO, fora do corpo assinado, entao a assinatura prova a ORIGEM e o
|
|
25
|
+
* CONTEUDO, e nao a hora. Ela nao protege contra reenvio de um aviso antigo e
|
|
26
|
+
* autentico por quem o tenha interceptado. A defesa pratica e guardar o
|
|
27
|
+
* `X-RadarData-Delivery` e ignorar o que ja foi processado, que voce deve
|
|
28
|
+
* fazer de qualquer forma, porque reenviamos em caso de falha.
|
|
29
|
+
*/
|
|
30
|
+
function confereAssinatura(corpoCru, assinatura, segredo) {
|
|
31
|
+
if (!assinatura || !segredo)
|
|
32
|
+
return false;
|
|
33
|
+
const esperada = `sha256=${(0, node_crypto_1.createHmac)("sha256", segredo).update(corpoCru).digest("hex")}`;
|
|
34
|
+
const a = Buffer.from(esperada, "utf8");
|
|
35
|
+
const b = Buffer.from(assinatura, "utf8");
|
|
36
|
+
// `timingSafeEqual` exige tamanhos iguais e lança quando diferem; comparar
|
|
37
|
+
// o tamanho antes não vaza nada, porque o tamanho da assinatura é fixo e
|
|
38
|
+
// público.
|
|
39
|
+
if (a.length !== b.length)
|
|
40
|
+
return false;
|
|
41
|
+
// E não `===`: comparação normal vaza, pelo tempo que leva, quantos bytes
|
|
42
|
+
// iniciais bateram, e com isso dá para descobrir a assinatura byte a byte.
|
|
43
|
+
return (0, node_crypto_1.timingSafeEqual)(a, b);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Confere e devolve o evento decodificado, ou lança.
|
|
47
|
+
*
|
|
48
|
+
* @throws Error quando a assinatura nao confere
|
|
49
|
+
*/
|
|
50
|
+
function exigirAssinatura(corpoCru, assinatura, segredo) {
|
|
51
|
+
if (!confereAssinatura(corpoCru, assinatura, segredo)) {
|
|
52
|
+
throw new Error("Assinatura do webhook do RadarData não confere.");
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
// `TextDecoder` e nao `Buffer.toString`: existe em Node, em navegador, em
|
|
56
|
+
// Deno e em Bun, e nao arrasta os tipos do Node para a superficie publica.
|
|
57
|
+
const texto = typeof corpoCru === "string" ? corpoCru : new TextDecoder().decode(corpoCru);
|
|
58
|
+
const dados = JSON.parse(texto);
|
|
59
|
+
return dados && typeof dados === "object" ? dados : {};
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return {};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=assinatura.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assinatura.js","sourceRoot":"","sources":["../../../src/webhooks/assinatura.ts"],"names":[],"mappings":";;AA0BA,8CAoBC;AAOD,4CAkBC;AAvED,6CAA0D;AAE1D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAgB,iBAAiB,CAC/B,QAA6B,EAC7B,UAAqC,EACrC,OAAe;IAEf,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE1C,MAAM,QAAQ,GAAG,UAAU,IAAA,wBAAU,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAE1F,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAE1C,2EAA2E;IAC3E,yEAAyE;IACzE,WAAW;IACX,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAExC,0EAA0E;IAC1E,2EAA2E;IAC3E,OAAO,IAAA,6BAAe,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAC9B,QAA6B,EAC7B,UAAqC,EACrC,OAAe;IAEf,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,CAAC;QACH,0EAA0E;QAC1E,2EAA2E;QAC3E,MAAM,KAAK,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC3F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,KAAiC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** O que o SDK precisa saber para falar com o RadarData. */
|
|
2
|
+
export interface Configuracao {
|
|
3
|
+
/** Token de API da empresa, criado no painel. Nunca o de sessao do painel. */
|
|
4
|
+
token: string;
|
|
5
|
+
/** Base da api. Trocavel para apontar o SDK a um ambiente seu. */
|
|
6
|
+
base?: string;
|
|
7
|
+
/** Milissegundos de espera por resposta. */
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Tentativas em chamada IDEMPOTENTE. Vale so onde o SDK manda
|
|
11
|
+
* `Idempotency-Key`; onde nao manda, repetir criaria cobranca nova e o SDK
|
|
12
|
+
* nao repete, qualquer que seja este numero.
|
|
13
|
+
*/
|
|
14
|
+
tentativas?: number;
|
|
15
|
+
/** Para teste: um `fetch` seu no lugar do global. */
|
|
16
|
+
fetch?: typeof globalThis.fetch;
|
|
17
|
+
}
|
|
18
|
+
export declare const VERSAO = "0.1.0";
|
|
19
|
+
/** @internal */
|
|
20
|
+
export interface ConfigResolvida extends Required<Omit<Configuracao, "fetch">> {
|
|
21
|
+
fetch: typeof globalThis.fetch;
|
|
22
|
+
}
|
|
23
|
+
/** @internal */
|
|
24
|
+
export declare function resolver(c: Configuracao): ConfigResolvida;
|
|
25
|
+
/** @internal */
|
|
26
|
+
export declare function userAgent(): string;
|
|
27
|
+
//# sourceMappingURL=configuracao.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuracao.d.ts","sourceRoot":"","sources":["../../src/configuracao.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CACjC;AAED,eAAO,MAAM,MAAM,UAAU,CAAC;AAE9B,gBAAgB;AAChB,MAAM,WAAW,eAAgB,SAAQ,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC5E,KAAK,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED,gBAAgB;AAChB,wBAAgB,QAAQ,CAAC,CAAC,EAAE,YAAY,GAAG,eAAe,CAiBzD;AAED,gBAAgB;AAChB,wBAAgB,SAAS,IAAI,MAAM,CAGlC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const VERSAO = "0.1.0";
|
|
2
|
+
/** @internal */
|
|
3
|
+
export function resolver(c) {
|
|
4
|
+
if (!c.token)
|
|
5
|
+
throw new Error("RadarData: token de API é obrigatório.");
|
|
6
|
+
const buscar = c.fetch ?? globalThis.fetch;
|
|
7
|
+
if (typeof buscar !== "function") {
|
|
8
|
+
throw new Error("RadarData: `fetch` não existe neste runtime. Use Node 18 ou mais novo, ou passe um `fetch` na configuração.");
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
token: c.token,
|
|
12
|
+
base: (c.base ?? "https://api.radardata.com.br/api/v2").replace(/\/+$/, ""),
|
|
13
|
+
timeoutMs: c.timeoutMs ?? 30_000,
|
|
14
|
+
tentativas: c.tentativas ?? 3,
|
|
15
|
+
fetch: buscar,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/** @internal */
|
|
19
|
+
export function userAgent() {
|
|
20
|
+
const v = typeof process !== "undefined" ? process.versions?.node : undefined;
|
|
21
|
+
return `radardata-sdk-node/${VERSAO}${v ? ` node/${v}` : ""}`;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=configuracao.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuracao.js","sourceRoot":"","sources":["../../src/configuracao.ts"],"names":[],"mappings":"AAkBA,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC;AAO9B,gBAAgB;AAChB,MAAM,UAAU,QAAQ,CAAC,CAAe;IACtC,IAAI,CAAC,CAAC,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAExE,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAC3C,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,6GAA6G,CAC9G,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,qCAAqC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3E,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,MAAM;QAChC,UAAU,EAAE,CAAC,CAAC,UAAU,IAAI,CAAC;QAC7B,KAAK,EAAE,MAAM;KACd,CAAC;AACJ,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,SAAS;IACvB,MAAM,CAAC,GAAG,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,OAAO,sBAAsB,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** Tipos do que a api devolve, onde tipar compensa. */
|
|
2
|
+
/**
|
|
3
|
+
* Saldo da conta, em CENTAVOS.
|
|
4
|
+
*
|
|
5
|
+
* Centavo inteiro, nunca float: o sistema inteiro guarda dinheiro assim, e
|
|
6
|
+
* converter para ponto flutuante aqui reintroduziria o erro de
|
|
7
|
+
* arredondamento que o inteiro existe para evitar.
|
|
8
|
+
*/
|
|
9
|
+
export interface Saldo {
|
|
10
|
+
readonly centavos: number;
|
|
11
|
+
/** O que da para gastar agora: desconta o que ja esta reservado. */
|
|
12
|
+
readonly disponivelCentavos: number;
|
|
13
|
+
/** PRE (saldo) ou POS (fatura). */
|
|
14
|
+
readonly modoCobranca: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Um servico do catalogo, com o preco DAQUELA conta.
|
|
18
|
+
*
|
|
19
|
+
* O preco vem resolvido por empresa: duas contas podem ver precos diferentes
|
|
20
|
+
* para o mesmo slug, e por isso ele nao e constante no SDK.
|
|
21
|
+
*/
|
|
22
|
+
export interface Servico {
|
|
23
|
+
readonly slug: string;
|
|
24
|
+
readonly nome: string;
|
|
25
|
+
readonly categoria: string | null;
|
|
26
|
+
readonly descricao: string | null;
|
|
27
|
+
/** CPF, CNPJ, PLACA... o que a consulta espera receber. */
|
|
28
|
+
readonly tipoDocumento: string | null;
|
|
29
|
+
readonly precoCentavos: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Uma sessao de Verify.
|
|
33
|
+
*
|
|
34
|
+
* `url` so vem na CRIACAO: e o link que voce manda para a pessoa. Depois
|
|
35
|
+
* disso a consulta devolve estado e resultado, e nao o link de novo.
|
|
36
|
+
*/
|
|
37
|
+
export interface SessaoVerify {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
/** pending, in_progress, completed, expired, canceled. */
|
|
40
|
+
readonly status: string;
|
|
41
|
+
readonly url: string | null;
|
|
42
|
+
/** APROVADO, REPROVADO, REVISAO_MANUAL; null enquanto nao concluiu. */
|
|
43
|
+
readonly resultado: string | null;
|
|
44
|
+
readonly expiraEm: string | null;
|
|
45
|
+
readonly referenceId: string | null;
|
|
46
|
+
/** Quanto este run custou para voce, em centavos. */
|
|
47
|
+
readonly custoCentavos: number;
|
|
48
|
+
/** O corpo cru, para o que o SDK nao tipou. */
|
|
49
|
+
readonly cru: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
export declare function paraSaldo(d: Record<string, unknown>): Saldo;
|
|
53
|
+
/** @internal */
|
|
54
|
+
export declare function paraServico(d: Record<string, unknown>): Servico;
|
|
55
|
+
/** @internal */
|
|
56
|
+
export declare function paraSessao(d: Record<string, unknown>): SessaoVerify;
|
|
57
|
+
/** Em reais, para exibir. O calculo continua em centavos. */
|
|
58
|
+
export declare function emReais(centavos: number): string;
|
|
59
|
+
//# sourceMappingURL=dados.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dados.d.ts","sourceRoot":"","sources":["../../src/dados.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD;;;;;;GAMG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,mCAAmC;IACnC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,gBAAgB;AAChB,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAM3D;AAED,gBAAgB;AAChB,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAS/D;AAED,gBAAgB;AAChB,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAWnE;AAED,6DAA6D;AAC7D,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Tipos do que a api devolve, onde tipar compensa. */
|
|
2
|
+
/** @internal */
|
|
3
|
+
export function paraSaldo(d) {
|
|
4
|
+
return {
|
|
5
|
+
centavos: Number(d.saldo ?? 0),
|
|
6
|
+
disponivelCentavos: Number(d.saldo_disponivel ?? 0),
|
|
7
|
+
modoCobranca: String(d.modo_cobranca ?? ""),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** @internal */
|
|
11
|
+
export function paraServico(d) {
|
|
12
|
+
return {
|
|
13
|
+
slug: String(d.slug ?? ""),
|
|
14
|
+
nome: String(d.nome ?? ""),
|
|
15
|
+
categoria: d.categoria ?? null,
|
|
16
|
+
descricao: d.descricao ?? null,
|
|
17
|
+
tipoDocumento: d.tipo_documento ?? null,
|
|
18
|
+
precoCentavos: Number(d.preco ?? 0),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** @internal */
|
|
22
|
+
export function paraSessao(d) {
|
|
23
|
+
return {
|
|
24
|
+
id: String(d.session_id ?? ""),
|
|
25
|
+
status: String(d.status ?? ""),
|
|
26
|
+
url: d.url ?? null,
|
|
27
|
+
resultado: d.outcome ?? null,
|
|
28
|
+
expiraEm: d.expires_at ?? null,
|
|
29
|
+
referenceId: d.reference_id ?? null,
|
|
30
|
+
custoCentavos: Number(d.custo_total_centavos ?? 0),
|
|
31
|
+
cru: d,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Em reais, para exibir. O calculo continua em centavos. */
|
|
35
|
+
export function emReais(centavos) {
|
|
36
|
+
return (centavos / 100).toLocaleString("pt-BR", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=dados.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dados.js","sourceRoot":"","sources":["../../src/dados.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAsDvD,gBAAgB;AAChB,MAAM,UAAU,SAAS,CAAC,CAA0B;IAClD,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAC9B,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACnD,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,WAAW,CAAC,CAA0B;IACpD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,SAAS,EAAG,CAAC,CAAC,SAA2B,IAAI,IAAI;QACjD,SAAS,EAAG,CAAC,CAAC,SAA2B,IAAI,IAAI;QACjD,aAAa,EAAG,CAAC,CAAC,cAAgC,IAAI,IAAI;QAC1D,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;KACpC,CAAC;AACJ,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,UAAU,CAAC,CAA0B;IACnD,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;QAC9B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;QAC9B,GAAG,EAAG,CAAC,CAAC,GAAqB,IAAI,IAAI;QACrC,SAAS,EAAG,CAAC,CAAC,OAAyB,IAAI,IAAI;QAC/C,QAAQ,EAAG,CAAC,CAAC,UAA4B,IAAI,IAAI;QACjD,WAAW,EAAG,CAAC,CAAC,YAA8B,IAAI,IAAI;QACtD,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC,oBAAoB,IAAI,CAAC,CAAC;QAClD,GAAG,EAAE,CAAC;KACP,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,OAAO,CAAC,QAAgB;IACtC,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,qBAAqB,EAAE,CAAC,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAC;AAC1G,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Erros do SDK, um por situacao.
|
|
3
|
+
*
|
|
4
|
+
* A api devolve sempre `{"error": {"code": "...", "message": "..."}}`, e o
|
|
5
|
+
* `code` e o que vale para decidir no codigo: a `message` e escrita para
|
|
6
|
+
* pessoa e muda. Por isso ele fica acessivel aqui, e cada classe existe para
|
|
7
|
+
* um `catch` especifico, em vez de obrigar quem integra a comparar strings.
|
|
8
|
+
*/
|
|
9
|
+
export declare class ErroRadarData extends Error {
|
|
10
|
+
readonly codigo: string | null;
|
|
11
|
+
readonly status: number | null;
|
|
12
|
+
/** O corpo cru, para quando o SDK nao previu algo. */
|
|
13
|
+
readonly corpo: Record<string, unknown>;
|
|
14
|
+
constructor(mensagem: string, codigo?: string | null, status?: number | null,
|
|
15
|
+
/** O corpo cru, para quando o SDK nao previu algo. */
|
|
16
|
+
corpo?: Record<string, unknown>, opcoes?: {
|
|
17
|
+
cause?: unknown;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** 401, token ausente, invalido ou revogado. */
|
|
21
|
+
export declare class NaoAutenticado extends ErroRadarData {
|
|
22
|
+
}
|
|
23
|
+
/** 402, a conta nao tem saldo para esta operacao. */
|
|
24
|
+
export declare class SaldoInsuficiente extends ErroRadarData {
|
|
25
|
+
}
|
|
26
|
+
/** 403, o token existe mas nao tem o escopo daquela rota. */
|
|
27
|
+
export declare class SemEscopo extends ErroRadarData {
|
|
28
|
+
}
|
|
29
|
+
/** 404, recurso inexistente ou de outra empresa. */
|
|
30
|
+
export declare class NaoEncontrado extends ErroRadarData {
|
|
31
|
+
}
|
|
32
|
+
/** 422, o que foi enviado nao passou na validacao. Veja `corpo`. */
|
|
33
|
+
export declare class EntradaInvalida extends ErroRadarData {
|
|
34
|
+
}
|
|
35
|
+
/** 429, teto de chamadas atingido. */
|
|
36
|
+
export declare class MuitasTentativas extends ErroRadarData {
|
|
37
|
+
}
|
|
38
|
+
/** 5xx, falha nossa. */
|
|
39
|
+
export declare class ErroDoServidor extends ErroRadarData {
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Nao houve resposta: timeout, DNS, conexao recusada.
|
|
43
|
+
*
|
|
44
|
+
* Separado dos erros com status de proposito: aqui o SDK NAO SABE se a
|
|
45
|
+
* operacao aconteceu. Numa chamada que gasta saldo isso importa, e o jeito de
|
|
46
|
+
* descobrir e consultar pela mesma chave de idempotencia, nao repetir as
|
|
47
|
+
* cegas.
|
|
48
|
+
*/
|
|
49
|
+
export declare class FalhaDeRede extends ErroRadarData {
|
|
50
|
+
}
|
|
51
|
+
/** @internal */
|
|
52
|
+
export declare function erroDoStatus(status: number, mensagem: string, codigo: string | null, corpo: Record<string, unknown>): ErroRadarData;
|
|
53
|
+
//# sourceMappingURL=erros.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erros.d.ts","sourceRoot":"","sources":["../../src/erros.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,qBAAa,aAAc,SAAQ,KAAK;IAGpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAC9B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAJvC,QAAQ,EAAE,MAAM,EACP,MAAM,GAAE,MAAM,GAAG,IAAW,EAC5B,MAAM,GAAE,MAAM,GAAG,IAAW;IACrC,sDAAsD;IAC7C,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAC5C,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAM/B;AAED,gDAAgD;AAChD,qBAAa,cAAe,SAAQ,aAAa;CAAG;AAEpD,qDAAqD;AACrD,qBAAa,iBAAkB,SAAQ,aAAa;CAAG;AAEvD,6DAA6D;AAC7D,qBAAa,SAAU,SAAQ,aAAa;CAAG;AAE/C,oDAAoD;AACpD,qBAAa,aAAc,SAAQ,aAAa;CAAG;AAEnD,oEAAoE;AACpE,qBAAa,eAAgB,SAAQ,aAAa;CAAG;AAErD,sCAAsC;AACtC,qBAAa,gBAAiB,SAAQ,aAAa;CAAG;AAEtD,wBAAwB;AACxB,qBAAa,cAAe,SAAQ,aAAa;CAAG;AAEpD;;;;;;;GAOG;AACH,qBAAa,WAAY,SAAQ,aAAa;CAAG;AAEjD,gBAAgB;AAChB,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,aAAa,CASf"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Erros do SDK, um por situacao.
|
|
3
|
+
*
|
|
4
|
+
* A api devolve sempre `{"error": {"code": "...", "message": "..."}}`, e o
|
|
5
|
+
* `code` e o que vale para decidir no codigo: a `message` e escrita para
|
|
6
|
+
* pessoa e muda. Por isso ele fica acessivel aqui, e cada classe existe para
|
|
7
|
+
* um `catch` especifico, em vez de obrigar quem integra a comparar strings.
|
|
8
|
+
*/
|
|
9
|
+
export class ErroRadarData extends Error {
|
|
10
|
+
codigo;
|
|
11
|
+
status;
|
|
12
|
+
corpo;
|
|
13
|
+
constructor(mensagem, codigo = null, status = null,
|
|
14
|
+
/** O corpo cru, para quando o SDK nao previu algo. */
|
|
15
|
+
corpo = {}, opcoes) {
|
|
16
|
+
super(mensagem, opcoes);
|
|
17
|
+
this.codigo = codigo;
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.corpo = corpo;
|
|
20
|
+
this.name = new.target.name;
|
|
21
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** 401, token ausente, invalido ou revogado. */
|
|
25
|
+
export class NaoAutenticado extends ErroRadarData {
|
|
26
|
+
}
|
|
27
|
+
/** 402, a conta nao tem saldo para esta operacao. */
|
|
28
|
+
export class SaldoInsuficiente extends ErroRadarData {
|
|
29
|
+
}
|
|
30
|
+
/** 403, o token existe mas nao tem o escopo daquela rota. */
|
|
31
|
+
export class SemEscopo extends ErroRadarData {
|
|
32
|
+
}
|
|
33
|
+
/** 404, recurso inexistente ou de outra empresa. */
|
|
34
|
+
export class NaoEncontrado extends ErroRadarData {
|
|
35
|
+
}
|
|
36
|
+
/** 422, o que foi enviado nao passou na validacao. Veja `corpo`. */
|
|
37
|
+
export class EntradaInvalida extends ErroRadarData {
|
|
38
|
+
}
|
|
39
|
+
/** 429, teto de chamadas atingido. */
|
|
40
|
+
export class MuitasTentativas extends ErroRadarData {
|
|
41
|
+
}
|
|
42
|
+
/** 5xx, falha nossa. */
|
|
43
|
+
export class ErroDoServidor extends ErroRadarData {
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Nao houve resposta: timeout, DNS, conexao recusada.
|
|
47
|
+
*
|
|
48
|
+
* Separado dos erros com status de proposito: aqui o SDK NAO SABE se a
|
|
49
|
+
* operacao aconteceu. Numa chamada que gasta saldo isso importa, e o jeito de
|
|
50
|
+
* descobrir e consultar pela mesma chave de idempotencia, nao repetir as
|
|
51
|
+
* cegas.
|
|
52
|
+
*/
|
|
53
|
+
export class FalhaDeRede extends ErroRadarData {
|
|
54
|
+
}
|
|
55
|
+
/** @internal */
|
|
56
|
+
export function erroDoStatus(status, mensagem, codigo, corpo) {
|
|
57
|
+
if (status === 401)
|
|
58
|
+
return new NaoAutenticado(mensagem, codigo, status, corpo);
|
|
59
|
+
if (status === 402)
|
|
60
|
+
return new SaldoInsuficiente(mensagem, codigo, status, corpo);
|
|
61
|
+
if (status === 403)
|
|
62
|
+
return new SemEscopo(mensagem, codigo, status, corpo);
|
|
63
|
+
if (status === 404)
|
|
64
|
+
return new NaoEncontrado(mensagem, codigo, status, corpo);
|
|
65
|
+
if (status === 422)
|
|
66
|
+
return new EntradaInvalida(mensagem, codigo, status, corpo);
|
|
67
|
+
if (status === 429)
|
|
68
|
+
return new MuitasTentativas(mensagem, codigo, status, corpo);
|
|
69
|
+
if (status >= 500)
|
|
70
|
+
return new ErroDoServidor(mensagem, codigo, status, corpo);
|
|
71
|
+
return new ErroRadarData(mensagem, codigo, status, corpo);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=erros.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"erros.js","sourceRoot":"","sources":["../../src/erros.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG3B;IACA;IAEA;IALX,YACE,QAAgB,EACP,SAAwB,IAAI,EAC5B,SAAwB,IAAI;IACrC,sDAAsD;IAC7C,QAAiC,EAAE,EAC5C,MAA4B;QAE5B,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QANf,WAAM,GAAN,MAAM,CAAsB;QAC5B,WAAM,GAAN,MAAM,CAAsB;QAE5B,UAAK,GAAL,KAAK,CAA8B;QAI5C,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED,gDAAgD;AAChD,MAAM,OAAO,cAAe,SAAQ,aAAa;CAAG;AAEpD,qDAAqD;AACrD,MAAM,OAAO,iBAAkB,SAAQ,aAAa;CAAG;AAEvD,6DAA6D;AAC7D,MAAM,OAAO,SAAU,SAAQ,aAAa;CAAG;AAE/C,oDAAoD;AACpD,MAAM,OAAO,aAAc,SAAQ,aAAa;CAAG;AAEnD,oEAAoE;AACpE,MAAM,OAAO,eAAgB,SAAQ,aAAa;CAAG;AAErD,sCAAsC;AACtC,MAAM,OAAO,gBAAiB,SAAQ,aAAa;CAAG;AAEtD,wBAAwB;AACxB,MAAM,OAAO,cAAe,SAAQ,aAAa;CAAG;AAEpD;;;;;;;GAOG;AACH,MAAM,OAAO,WAAY,SAAQ,aAAa;CAAG;AAEjD,gBAAgB;AAChB,MAAM,UAAU,YAAY,CAC1B,MAAc,EACd,QAAgB,EAChB,MAAqB,EACrB,KAA8B;IAE9B,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/E,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAClF,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC1E,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9E,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAChF,IAAI,MAAM,KAAK,GAAG;QAAE,OAAO,IAAI,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IACjF,IAAI,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9E,OAAO,IAAI,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Configuracao } from "./configuracao.js";
|
|
2
|
+
import { Analises } from "./recursos/analises.js";
|
|
3
|
+
import { Catalogo } from "./recursos/catalogo.js";
|
|
4
|
+
import { Consultas } from "./recursos/consultas.js";
|
|
5
|
+
import { Verify } from "./recursos/verify.js";
|
|
6
|
+
import { Webhooks } from "./recursos/webhooks.js";
|
|
7
|
+
/**
|
|
8
|
+
* Ponto de entrada do SDK.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { RadarData } from "@radardata/sdk";
|
|
12
|
+
*
|
|
13
|
+
* const radar = new RadarData({ token: process.env.RADARDATA_TOKEN! });
|
|
14
|
+
* const saldo = await radar.catalogo.saldo();
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* O token e o de API, criado no painel, e NAO o de sessao do painel. Ele
|
|
18
|
+
* carrega escopos: uma chamada fora do escopo do token volta `SemEscopo`, e
|
|
19
|
+
* isso e proposital, para um token de servidor nao poder redirecionar os seus
|
|
20
|
+
* webhooks.
|
|
21
|
+
*/
|
|
22
|
+
export declare class RadarData {
|
|
23
|
+
readonly catalogo: Catalogo;
|
|
24
|
+
readonly consultas: Consultas;
|
|
25
|
+
readonly verify: Verify;
|
|
26
|
+
readonly analises: Analises;
|
|
27
|
+
readonly webhooks: Webhooks;
|
|
28
|
+
constructor(config: Configuracao);
|
|
29
|
+
}
|
|
30
|
+
export { chaveIdempotencia } from "./transporte.js";
|
|
31
|
+
export { confereAssinatura, exigirAssinatura } from "./webhooks/assinatura.js";
|
|
32
|
+
export { emReais } from "./dados.js";
|
|
33
|
+
export type { Configuracao } from "./configuracao.js";
|
|
34
|
+
export type { Saldo, Servico, SessaoVerify } from "./dados.js";
|
|
35
|
+
export { EntradaInvalida, ErroDoServidor, ErroRadarData, FalhaDeRede, MuitasTentativas, NaoAutenticado, NaoEncontrado, SaldoInsuficiente, SemEscopo, } from "./erros.js";
|
|
36
|
+
export { Analises } from "./recursos/analises.js";
|
|
37
|
+
export { Catalogo } from "./recursos/catalogo.js";
|
|
38
|
+
export { Consultas } from "./recursos/consultas.js";
|
|
39
|
+
export { Verify } from "./recursos/verify.js";
|
|
40
|
+
export { Webhooks } from "./recursos/webhooks.js";
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAY,MAAM,mBAAmB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAS;IACpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBAEhB,MAAM,EAAE,YAAY;CASjC;AAED,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EACL,eAAe,EACf,cAAc,EACd,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,SAAS,GACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC"}
|