@pairus/product-data 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # PAIRUS Product Data SDK para Node.js & TypeScript (`@pairus/product-data`)
2
+
3
+ SDK oficial da **PAIRUS Soluções Tecnológicas** para Node.js e TypeScript com tipagem completa, auto-complete inteligente, retentativas automáticas e helper para validação de Webhooks HMAC-SHA256.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@pairus/product-data.svg)](https://www.npmjs.com/package/@pairus/product-data)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## 📦 Instalação
11
+
12
+ ```bash
13
+ npm install @pairus/product-data
14
+ # ou
15
+ yarn add @pairus/product-data
16
+ # ou
17
+ pnpm add @pairus/product-data
18
+ ```
19
+
20
+ ---
21
+
22
+ ## 🚀 Início Rápido
23
+
24
+ ### 1. Consulta de Produto por GTIN
25
+
26
+ ```typescript
27
+ import { PairusProductData } from '@pairus/product-data';
28
+
29
+ // Inicializa o cliente (lê automaticamente process.env.PAIRUS_API_KEY se omitido)
30
+ const client = new PairusProductData({ apiKey: 'pk_live_...' });
31
+
32
+ async function main() {
33
+ const produto = await client.products.get('7891000744703');
34
+ console.log(`Produto: ${produto.xProd}`);
35
+ console.log(`NCM: ${produto.ncm} | CEST: ${produto.cest}`);
36
+ }
37
+
38
+ main();
39
+ ```
40
+
41
+ ### 2. Predição Fiscal com Reforma Tributária (IBS/CBS/IS)
42
+
43
+ ```typescript
44
+ import { PairusProductData } from '@pairus/product-data';
45
+
46
+ const client = new PairusProductData();
47
+
48
+ async function prever() {
49
+ const predicao = await client.fiscal.predict({
50
+ xProd: 'Refrigerante Coca-Cola Lata 350ml',
51
+ gtin: '7894900010015',
52
+ regimeTributario: 'simples_nacional',
53
+ ufOrigem: 'SP',
54
+ ufDestino: 'RJ',
55
+ finalidade: 'revenda',
56
+ });
57
+
58
+ const tributos = predicao.dados_tributarios!;
59
+ console.log(`NCM Sugerido: ${tributos.ncm_sugerido}`);
60
+ console.log(`CST IBS/CBS: ${tributos.ibscbs.cst}`);
61
+ console.log(`Alíquota Efetiva CBS: ${tributos.ibscbs.cbs_aliquota_efetiva}%`);
62
+ console.log(`Alíquota Efetiva IBS: ${tributos.ibscbs.ibs_aliquota_efetiva}%`);
63
+ console.log(`Alíquota Unificada: ${tributos.aliquota_efetiva_unificada}%`);
64
+ }
65
+
66
+ prever();
67
+ ```
68
+
69
+ ### 3. Validação de Webhooks (Express / Next.js)
70
+
71
+ ```typescript
72
+ import express from 'express';
73
+ import { Webhooks } from '@pairus/product-data';
74
+
75
+ const app = express();
76
+
77
+ app.post('/webhooks/pairus', express.raw({ type: 'application/json' }), (req, res) => {
78
+ const signature = req.headers['x-pairus-signature'] as string;
79
+ const secret = process.env.PAIRUS_WEBHOOK_SECRET!;
80
+
81
+ try {
82
+ const evento = Webhooks.constructEvent(req.body, signature, secret);
83
+ console.log(`Evento recebido: ${evento.event}`, evento.data);
84
+ res.status(200).json({ received: true });
85
+ } catch (err) {
86
+ res.status(400).json({ error: 'Assinatura inválida' });
87
+ }
88
+ });
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 🛡️ Licença
94
+ Distribuído sob a licença MIT.
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Opções de configuração para o cliente PairusProductData.
3
+ */
4
+ interface PairusClientOptions {
5
+ apiKey?: string;
6
+ baseUrl?: string;
7
+ timeoutMs?: number;
8
+ maxRetries?: number;
9
+ }
10
+ declare const DEFAULT_BASE_URL = "https://api.pairus.com.br";
11
+ declare const DEFAULT_TIMEOUT_MS = 15000;
12
+ declare const DEFAULT_MAX_RETRIES = 3;
13
+
14
+ interface RequestOptions {
15
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
16
+ path: string;
17
+ params?: Record<string, string>;
18
+ body?: any;
19
+ headers?: Record<string, string>;
20
+ }
21
+ declare class BaseResource {
22
+ protected apiKey: string;
23
+ protected baseUrl: string;
24
+ protected timeoutMs: number;
25
+ protected maxRetries: number;
26
+ constructor(apiKey: string, baseUrl: string, timeoutMs: number, maxRetries: number);
27
+ protected request<T>(options: RequestOptions): Promise<T>;
28
+ }
29
+
30
+ interface IBSCBSData {
31
+ cst: string;
32
+ cClassTrib: string;
33
+ cbs_aliquota: number;
34
+ cbs_diferimento: number;
35
+ cbs_reducao_aliquota: number;
36
+ cbs_aliquota_efetiva: number;
37
+ ibs_aliquota_estadual: number;
38
+ ibs_aliquota_municipal: number;
39
+ ibs_diferimento: number;
40
+ ibs_reducao_aliquota: number;
41
+ ibs_aliquota_efetiva: number;
42
+ }
43
+ interface SelectiveTaxData {
44
+ cst: string;
45
+ cClassTribIS: string;
46
+ aliquota: number;
47
+ }
48
+ interface FuelData {
49
+ codigo_anp: string;
50
+ descricao_anp: string;
51
+ perc_glp?: number;
52
+ perc_gas_nacional?: number;
53
+ perc_gas_importado?: number;
54
+ valor_por_kg?: number;
55
+ }
56
+ interface TaxPredictionData {
57
+ ncm_sugerido: string;
58
+ cest_sugerido?: string;
59
+ cfop: string;
60
+ cfop_devolucao?: string;
61
+ icms_cst_csosn: string;
62
+ icms_aliquota: number;
63
+ icms_aliquota_st: number;
64
+ icms_mva_st: number;
65
+ icms_reducao_bc: number;
66
+ icms_reducao_bc_st: number;
67
+ icms_modalidade_bc: string;
68
+ icms_modalidade_bc_st: string;
69
+ pis_cst: string;
70
+ pis_aliquota: number;
71
+ cofins_cst: string;
72
+ cofins_aliquota: number;
73
+ ipi_cst?: string;
74
+ ipi_aliquota?: number;
75
+ ibscbs: IBSCBSData;
76
+ imposto_seletivo?: SelectiveTaxData;
77
+ dados_combustivel?: FuelData;
78
+ beneficio_fiscal?: string;
79
+ aliquota_efetiva_unificada: number;
80
+ motor_ia: string;
81
+ avisos: string[];
82
+ }
83
+ interface TaxPredictionItemInput {
84
+ xProd?: string;
85
+ gtin?: string;
86
+ ncm?: string;
87
+ cest?: string;
88
+ }
89
+ interface TaxPredictionParams {
90
+ regimeTributario: 'simples_nacional' | 'lucro_presumido' | 'lucro_real' | string;
91
+ ufOrigem: string;
92
+ ufDestino?: string;
93
+ finalidade?: 'revenda' | 'consumo_final' | 'industrializacao' | string;
94
+ destinatarioContribuinte?: boolean;
95
+ xProd?: string;
96
+ gtin?: string;
97
+ ncm?: string;
98
+ cest?: string;
99
+ itens?: TaxPredictionItemInput[];
100
+ }
101
+ interface TaxPredictionItemResult {
102
+ item_index: number;
103
+ xProd?: string;
104
+ dados_tributarios: TaxPredictionData;
105
+ }
106
+ interface TaxPredictionResponse {
107
+ status: string;
108
+ provider: string;
109
+ xProd?: string;
110
+ dados_tributarios?: TaxPredictionData;
111
+ resultados?: TaxPredictionItemResult[];
112
+ }
113
+
114
+ declare class FiscalResource extends BaseResource {
115
+ /**
116
+ * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.
117
+ */
118
+ predict(params: TaxPredictionParams): Promise<TaxPredictionResponse>;
119
+ }
120
+
121
+ interface ProductDetails {
122
+ gtin: string;
123
+ xProd: string;
124
+ ncm?: string;
125
+ cest?: string;
126
+ marca?: string;
127
+ fabricante?: string;
128
+ categoria?: string;
129
+ imagemUrl?: string;
130
+ pesoBruto?: number;
131
+ pesoLiquido?: number;
132
+ quantidadeEmbalagem?: number;
133
+ dataCadastro?: string;
134
+ dataAtualizacao?: string;
135
+ }
136
+ interface ProductResponse {
137
+ status: string;
138
+ provider: string;
139
+ produto?: ProductDetails;
140
+ raw_data?: Record<string, any>;
141
+ }
142
+
143
+ declare class ProductsResource extends BaseResource {
144
+ /**
145
+ * Consulta um produto por código de barras GTIN/EAN.
146
+ * @param gtin Código numérico de 8 a 14 dígitos.
147
+ */
148
+ get(gtin: string): Promise<ProductDetails>;
149
+ }
150
+
151
+ interface WebhookEvent<T = Record<string, any>> {
152
+ id?: string;
153
+ event: string;
154
+ timestamp: string;
155
+ data: T;
156
+ }
157
+
158
+ declare class Webhooks {
159
+ /**
160
+ * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.
161
+ */
162
+ static computeSignature(payload: string | Buffer, secret: string): string;
163
+ /**
164
+ * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.
165
+ */
166
+ static verifySignature(payload: string | Buffer | Record<string, any>, signature: string | undefined | null, secret: string): boolean;
167
+ /**
168
+ * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.
169
+ */
170
+ static constructEvent<T = Record<string, any>>(payload: string | Buffer, signature: string | undefined | null, secret: string): WebhookEvent<T>;
171
+ }
172
+
173
+ declare class PairusProductData {
174
+ static readonly webhooks: typeof Webhooks;
175
+ readonly webhooks: typeof Webhooks;
176
+ readonly products: ProductsResource;
177
+ readonly fiscal: FiscalResource;
178
+ constructor(options?: PairusClientOptions);
179
+ }
180
+
181
+ /**
182
+ * Classes de erro oficiais do SDK @pairus/product-data.
183
+ */
184
+ declare class PairusError extends Error {
185
+ constructor(message: string);
186
+ }
187
+ declare class PairusAPIError extends PairusError {
188
+ readonly statusCode: number;
189
+ readonly cStat: string;
190
+ readonly xMotivo: string;
191
+ readonly details?: any;
192
+ constructor(statusCode: number, cStat?: string, xMotivo?: string, details?: any);
193
+ }
194
+ declare class AuthenticationError extends PairusAPIError {
195
+ constructor(cStat?: string, xMotivo?: string, details?: any);
196
+ }
197
+ declare class RateLimitError extends PairusAPIError {
198
+ readonly retryAfter?: number;
199
+ constructor(retryAfter?: number, cStat?: string, xMotivo?: string, details?: any);
200
+ }
201
+ declare class InvalidSignatureError extends PairusError {
202
+ constructor(message?: string);
203
+ }
204
+ declare class NetworkError extends PairusError {
205
+ constructor(message: string);
206
+ }
207
+
208
+ export { AuthenticationError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, type FuelData, type IBSCBSData, InvalidSignatureError, NetworkError, PairusAPIError, type PairusClientOptions, PairusError, PairusProductData, type ProductDetails, type ProductResponse, RateLimitError, type SelectiveTaxData, type TaxPredictionData, type TaxPredictionItemInput, type TaxPredictionItemResult, type TaxPredictionParams, type TaxPredictionResponse, type WebhookEvent, Webhooks };
@@ -0,0 +1,208 @@
1
+ /**
2
+ * Opções de configuração para o cliente PairusProductData.
3
+ */
4
+ interface PairusClientOptions {
5
+ apiKey?: string;
6
+ baseUrl?: string;
7
+ timeoutMs?: number;
8
+ maxRetries?: number;
9
+ }
10
+ declare const DEFAULT_BASE_URL = "https://api.pairus.com.br";
11
+ declare const DEFAULT_TIMEOUT_MS = 15000;
12
+ declare const DEFAULT_MAX_RETRIES = 3;
13
+
14
+ interface RequestOptions {
15
+ method: 'GET' | 'POST' | 'PUT' | 'DELETE';
16
+ path: string;
17
+ params?: Record<string, string>;
18
+ body?: any;
19
+ headers?: Record<string, string>;
20
+ }
21
+ declare class BaseResource {
22
+ protected apiKey: string;
23
+ protected baseUrl: string;
24
+ protected timeoutMs: number;
25
+ protected maxRetries: number;
26
+ constructor(apiKey: string, baseUrl: string, timeoutMs: number, maxRetries: number);
27
+ protected request<T>(options: RequestOptions): Promise<T>;
28
+ }
29
+
30
+ interface IBSCBSData {
31
+ cst: string;
32
+ cClassTrib: string;
33
+ cbs_aliquota: number;
34
+ cbs_diferimento: number;
35
+ cbs_reducao_aliquota: number;
36
+ cbs_aliquota_efetiva: number;
37
+ ibs_aliquota_estadual: number;
38
+ ibs_aliquota_municipal: number;
39
+ ibs_diferimento: number;
40
+ ibs_reducao_aliquota: number;
41
+ ibs_aliquota_efetiva: number;
42
+ }
43
+ interface SelectiveTaxData {
44
+ cst: string;
45
+ cClassTribIS: string;
46
+ aliquota: number;
47
+ }
48
+ interface FuelData {
49
+ codigo_anp: string;
50
+ descricao_anp: string;
51
+ perc_glp?: number;
52
+ perc_gas_nacional?: number;
53
+ perc_gas_importado?: number;
54
+ valor_por_kg?: number;
55
+ }
56
+ interface TaxPredictionData {
57
+ ncm_sugerido: string;
58
+ cest_sugerido?: string;
59
+ cfop: string;
60
+ cfop_devolucao?: string;
61
+ icms_cst_csosn: string;
62
+ icms_aliquota: number;
63
+ icms_aliquota_st: number;
64
+ icms_mva_st: number;
65
+ icms_reducao_bc: number;
66
+ icms_reducao_bc_st: number;
67
+ icms_modalidade_bc: string;
68
+ icms_modalidade_bc_st: string;
69
+ pis_cst: string;
70
+ pis_aliquota: number;
71
+ cofins_cst: string;
72
+ cofins_aliquota: number;
73
+ ipi_cst?: string;
74
+ ipi_aliquota?: number;
75
+ ibscbs: IBSCBSData;
76
+ imposto_seletivo?: SelectiveTaxData;
77
+ dados_combustivel?: FuelData;
78
+ beneficio_fiscal?: string;
79
+ aliquota_efetiva_unificada: number;
80
+ motor_ia: string;
81
+ avisos: string[];
82
+ }
83
+ interface TaxPredictionItemInput {
84
+ xProd?: string;
85
+ gtin?: string;
86
+ ncm?: string;
87
+ cest?: string;
88
+ }
89
+ interface TaxPredictionParams {
90
+ regimeTributario: 'simples_nacional' | 'lucro_presumido' | 'lucro_real' | string;
91
+ ufOrigem: string;
92
+ ufDestino?: string;
93
+ finalidade?: 'revenda' | 'consumo_final' | 'industrializacao' | string;
94
+ destinatarioContribuinte?: boolean;
95
+ xProd?: string;
96
+ gtin?: string;
97
+ ncm?: string;
98
+ cest?: string;
99
+ itens?: TaxPredictionItemInput[];
100
+ }
101
+ interface TaxPredictionItemResult {
102
+ item_index: number;
103
+ xProd?: string;
104
+ dados_tributarios: TaxPredictionData;
105
+ }
106
+ interface TaxPredictionResponse {
107
+ status: string;
108
+ provider: string;
109
+ xProd?: string;
110
+ dados_tributarios?: TaxPredictionData;
111
+ resultados?: TaxPredictionItemResult[];
112
+ }
113
+
114
+ declare class FiscalResource extends BaseResource {
115
+ /**
116
+ * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.
117
+ */
118
+ predict(params: TaxPredictionParams): Promise<TaxPredictionResponse>;
119
+ }
120
+
121
+ interface ProductDetails {
122
+ gtin: string;
123
+ xProd: string;
124
+ ncm?: string;
125
+ cest?: string;
126
+ marca?: string;
127
+ fabricante?: string;
128
+ categoria?: string;
129
+ imagemUrl?: string;
130
+ pesoBruto?: number;
131
+ pesoLiquido?: number;
132
+ quantidadeEmbalagem?: number;
133
+ dataCadastro?: string;
134
+ dataAtualizacao?: string;
135
+ }
136
+ interface ProductResponse {
137
+ status: string;
138
+ provider: string;
139
+ produto?: ProductDetails;
140
+ raw_data?: Record<string, any>;
141
+ }
142
+
143
+ declare class ProductsResource extends BaseResource {
144
+ /**
145
+ * Consulta um produto por código de barras GTIN/EAN.
146
+ * @param gtin Código numérico de 8 a 14 dígitos.
147
+ */
148
+ get(gtin: string): Promise<ProductDetails>;
149
+ }
150
+
151
+ interface WebhookEvent<T = Record<string, any>> {
152
+ id?: string;
153
+ event: string;
154
+ timestamp: string;
155
+ data: T;
156
+ }
157
+
158
+ declare class Webhooks {
159
+ /**
160
+ * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.
161
+ */
162
+ static computeSignature(payload: string | Buffer, secret: string): string;
163
+ /**
164
+ * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.
165
+ */
166
+ static verifySignature(payload: string | Buffer | Record<string, any>, signature: string | undefined | null, secret: string): boolean;
167
+ /**
168
+ * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.
169
+ */
170
+ static constructEvent<T = Record<string, any>>(payload: string | Buffer, signature: string | undefined | null, secret: string): WebhookEvent<T>;
171
+ }
172
+
173
+ declare class PairusProductData {
174
+ static readonly webhooks: typeof Webhooks;
175
+ readonly webhooks: typeof Webhooks;
176
+ readonly products: ProductsResource;
177
+ readonly fiscal: FiscalResource;
178
+ constructor(options?: PairusClientOptions);
179
+ }
180
+
181
+ /**
182
+ * Classes de erro oficiais do SDK @pairus/product-data.
183
+ */
184
+ declare class PairusError extends Error {
185
+ constructor(message: string);
186
+ }
187
+ declare class PairusAPIError extends PairusError {
188
+ readonly statusCode: number;
189
+ readonly cStat: string;
190
+ readonly xMotivo: string;
191
+ readonly details?: any;
192
+ constructor(statusCode: number, cStat?: string, xMotivo?: string, details?: any);
193
+ }
194
+ declare class AuthenticationError extends PairusAPIError {
195
+ constructor(cStat?: string, xMotivo?: string, details?: any);
196
+ }
197
+ declare class RateLimitError extends PairusAPIError {
198
+ readonly retryAfter?: number;
199
+ constructor(retryAfter?: number, cStat?: string, xMotivo?: string, details?: any);
200
+ }
201
+ declare class InvalidSignatureError extends PairusError {
202
+ constructor(message?: string);
203
+ }
204
+ declare class NetworkError extends PairusError {
205
+ constructor(message: string);
206
+ }
207
+
208
+ export { AuthenticationError, DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT_MS, type FuelData, type IBSCBSData, InvalidSignatureError, NetworkError, PairusAPIError, type PairusClientOptions, PairusError, PairusProductData, type ProductDetails, type ProductResponse, RateLimitError, type SelectiveTaxData, type TaxPredictionData, type TaxPredictionItemInput, type TaxPredictionItemResult, type TaxPredictionParams, type TaxPredictionResponse, type WebhookEvent, Webhooks };
package/dist/index.js ADDED
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AuthenticationError: () => AuthenticationError,
34
+ DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
35
+ DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES,
36
+ DEFAULT_TIMEOUT_MS: () => DEFAULT_TIMEOUT_MS,
37
+ InvalidSignatureError: () => InvalidSignatureError,
38
+ NetworkError: () => NetworkError,
39
+ PairusAPIError: () => PairusAPIError,
40
+ PairusError: () => PairusError,
41
+ PairusProductData: () => PairusProductData,
42
+ RateLimitError: () => RateLimitError,
43
+ Webhooks: () => Webhooks
44
+ });
45
+ module.exports = __toCommonJS(index_exports);
46
+
47
+ // src/config.ts
48
+ var DEFAULT_BASE_URL = "https://api.pairus.com.br";
49
+ var DEFAULT_TIMEOUT_MS = 15e3;
50
+ var DEFAULT_MAX_RETRIES = 3;
51
+
52
+ // src/errors.ts
53
+ var PairusError = class extends Error {
54
+ constructor(message) {
55
+ super(message);
56
+ this.name = "PairusError";
57
+ }
58
+ };
59
+ var PairusAPIError = class extends PairusError {
60
+ statusCode;
61
+ cStat;
62
+ xMotivo;
63
+ details;
64
+ constructor(statusCode, cStat, xMotivo, details) {
65
+ const code = cStat || String(statusCode);
66
+ const reason = xMotivo || details?.detail || `Erro HTTP ${statusCode}`;
67
+ super(`[${code}] ${reason}`);
68
+ this.name = "PairusAPIError";
69
+ this.statusCode = statusCode;
70
+ this.cStat = code;
71
+ this.xMotivo = reason;
72
+ this.details = details;
73
+ }
74
+ };
75
+ var AuthenticationError = class extends PairusAPIError {
76
+ constructor(cStat = "401", xMotivo = "Chave de API inv\xE1lida ou n\xE3o autorizada.", details) {
77
+ super(401, cStat, xMotivo, details);
78
+ this.name = "AuthenticationError";
79
+ }
80
+ };
81
+ var RateLimitError = class extends PairusAPIError {
82
+ retryAfter;
83
+ constructor(retryAfter, cStat = "429", xMotivo = "Limite de requisi\xE7\xF5es excedido.", details) {
84
+ super(429, cStat, xMotivo, details);
85
+ this.name = "RateLimitError";
86
+ this.retryAfter = retryAfter;
87
+ }
88
+ };
89
+ var InvalidSignatureError = class extends PairusError {
90
+ constructor(message = "A assinatura criptogr\xE1fica do webhook ('X-Pairus-Signature') \xE9 inv\xE1lida.") {
91
+ super(message);
92
+ this.name = "InvalidSignatureError";
93
+ }
94
+ };
95
+ var NetworkError = class extends PairusError {
96
+ constructor(message) {
97
+ super(message);
98
+ this.name = "NetworkError";
99
+ }
100
+ };
101
+
102
+ // src/resources/base.ts
103
+ var BaseResource = class {
104
+ apiKey;
105
+ baseUrl;
106
+ timeoutMs;
107
+ maxRetries;
108
+ constructor(apiKey, baseUrl, timeoutMs, maxRetries) {
109
+ this.apiKey = apiKey;
110
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
111
+ this.timeoutMs = timeoutMs;
112
+ this.maxRetries = maxRetries;
113
+ }
114
+ async request(options) {
115
+ let url = `${this.baseUrl}/${options.path.replace(/^\/+/, "")}`;
116
+ if (options.params) {
117
+ const query = new URLSearchParams(options.params).toString();
118
+ url = `${url}?${query}`;
119
+ }
120
+ const reqHeaders = {
121
+ "Accept": "application/json",
122
+ "X-API-Key": this.apiKey,
123
+ "User-Agent": "Pairus-NodeJS-SDK/1.0.0",
124
+ ...options.headers || {}
125
+ };
126
+ if (options.body) {
127
+ reqHeaders["Content-Type"] = "application/json";
128
+ }
129
+ let lastError = null;
130
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
131
+ try {
132
+ const controller = new AbortController();
133
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
134
+ const response = await fetch(url, {
135
+ method: options.method,
136
+ headers: reqHeaders,
137
+ body: options.body ? JSON.stringify(options.body) : void 0,
138
+ signal: controller.signal
139
+ });
140
+ clearTimeout(timeoutId);
141
+ if (response.ok) {
142
+ return await response.json();
143
+ }
144
+ let errData = {};
145
+ try {
146
+ errData = await response.json();
147
+ } catch {
148
+ errData = {};
149
+ }
150
+ if (response.status === 401) {
151
+ throw new AuthenticationError(errData.cStat, errData.xMotivo, errData);
152
+ }
153
+ if (response.status === 429) {
154
+ const retryAfterSec = parseFloat(response.headers.get("Retry-After") || "2");
155
+ if (attempt < this.maxRetries - 1) {
156
+ await new Promise((res) => setTimeout(res, (retryAfterSec + Math.random() * 0.5) * 1e3));
157
+ continue;
158
+ }
159
+ throw new RateLimitError(retryAfterSec, errData.cStat, errData.xMotivo, errData);
160
+ }
161
+ if ([502, 503, 504].includes(response.status) && attempt < this.maxRetries - 1) {
162
+ const delay = Math.pow(2, attempt) * 1e3 + Math.random() * 500;
163
+ await new Promise((res) => setTimeout(res, delay));
164
+ continue;
165
+ }
166
+ throw new PairusAPIError(response.status, errData.cStat, errData.xMotivo, errData);
167
+ } catch (err) {
168
+ if (err instanceof PairusAPIError) {
169
+ throw err;
170
+ }
171
+ lastError = err;
172
+ if (attempt < this.maxRetries - 1) {
173
+ const delay = Math.pow(2, attempt) * 1e3 + Math.random() * 500;
174
+ await new Promise((res) => setTimeout(res, delay));
175
+ continue;
176
+ }
177
+ break;
178
+ }
179
+ }
180
+ throw new NetworkError(`Falha de conex\xE3o com a API PAIRUS ap\xF3s ${this.maxRetries} tentativas: ${lastError?.message || lastError}`);
181
+ }
182
+ };
183
+
184
+ // src/resources/fiscal.ts
185
+ var FiscalResource = class extends BaseResource {
186
+ /**
187
+ * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.
188
+ */
189
+ async predict(params) {
190
+ const payload = {
191
+ regime_tributario: params.regimeTributario,
192
+ uf_origem: params.ufOrigem,
193
+ uf_destino: params.ufDestino || params.ufOrigem,
194
+ finalidade: params.finalidade || "revenda",
195
+ destinatario_contribuinte: params.destinatarioContribuinte ?? true
196
+ };
197
+ if (params.xProd) payload.xProd = params.xProd;
198
+ if (params.gtin) payload.gtin = params.gtin;
199
+ if (params.ncm) payload.ncm = params.ncm;
200
+ if (params.cest) payload.cest = params.cest;
201
+ if (params.itens) payload.itens = params.itens;
202
+ return this.request({
203
+ method: "POST",
204
+ path: "/v2/fiscal/predict",
205
+ body: payload
206
+ });
207
+ }
208
+ };
209
+
210
+ // src/resources/products.ts
211
+ var ProductsResource = class extends BaseResource {
212
+ /**
213
+ * Consulta um produto por código de barras GTIN/EAN.
214
+ * @param gtin Código numérico de 8 a 14 dígitos.
215
+ */
216
+ async get(gtin) {
217
+ const gtinLimpo = gtin.replace(/\D/g, "");
218
+ const data = await this.request({
219
+ method: "GET",
220
+ path: `/api/produtos/${gtinLimpo}`
221
+ });
222
+ const prod = data.produto || data;
223
+ return {
224
+ gtin: prod.GTIN || prod.gtin || gtinLimpo,
225
+ xProd: prod.xProd || prod.descricao || "Descri\xE7\xE3o Indispon\xEDvel",
226
+ ncm: prod.NCM || prod.ncm,
227
+ cest: prod.CEST || prod.cest,
228
+ marca: prod.marca,
229
+ fabricante: prod.fabricante,
230
+ categoria: prod.categoria,
231
+ imagemUrl: prod.imagem_url || prod.thumbnail,
232
+ pesoBruto: prod.peso_bruto ? Number(prod.peso_bruto) : void 0,
233
+ pesoLiquido: prod.peso_liquido ? Number(prod.peso_liquido) : void 0,
234
+ quantidadeEmbalagem: Number(prod.quantidade_embalagem || 1)
235
+ };
236
+ }
237
+ };
238
+
239
+ // src/webhooks.ts
240
+ var crypto = __toESM(require("crypto"));
241
+ var Webhooks = class {
242
+ /**
243
+ * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.
244
+ */
245
+ static computeSignature(payload, secret) {
246
+ return crypto.createHmac("sha256", secret).update(payload).digest("hex");
247
+ }
248
+ /**
249
+ * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.
250
+ */
251
+ static verifySignature(payload, signature, secret) {
252
+ if (!signature || !secret) {
253
+ return false;
254
+ }
255
+ let payloadBuffer;
256
+ if (Buffer.isBuffer(payload)) {
257
+ payloadBuffer = payload;
258
+ } else if (typeof payload === "string") {
259
+ payloadBuffer = Buffer.from(payload, "utf-8");
260
+ } else {
261
+ payloadBuffer = Buffer.from(JSON.stringify(payload), "utf-8");
262
+ }
263
+ const expectedSignature = this.computeSignature(payloadBuffer, secret);
264
+ try {
265
+ const sigBuf = Buffer.from(signature.trim(), "hex");
266
+ const expectedBuf = Buffer.from(expectedSignature, "hex");
267
+ if (sigBuf.length !== expectedBuf.length) {
268
+ return false;
269
+ }
270
+ return crypto.timingSafeEqual(sigBuf, expectedBuf);
271
+ } catch {
272
+ return false;
273
+ }
274
+ }
275
+ /**
276
+ * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.
277
+ */
278
+ static constructEvent(payload, signature, secret) {
279
+ if (!this.verifySignature(payload, signature, secret)) {
280
+ throw new InvalidSignatureError("Assinatura do webhook ('X-Pairus-Signature') \xE9 inv\xE1lida.");
281
+ }
282
+ const rawStr = Buffer.isBuffer(payload) ? payload.toString("utf-8") : payload;
283
+ return JSON.parse(rawStr);
284
+ }
285
+ };
286
+
287
+ // src/client.ts
288
+ var PairusProductData = class {
289
+ static webhooks = Webhooks;
290
+ webhooks = Webhooks;
291
+ products;
292
+ fiscal;
293
+ constructor(options) {
294
+ const apiKey = options?.apiKey || (typeof process !== "undefined" ? process.env.PAIRUS_API_KEY : void 0);
295
+ if (!apiKey) {
296
+ throw new Error(
297
+ "A chave de API da PAIRUS \xE9 obrigat\xF3ria. Passe 'apiKey' no construtor ou defina a vari\xE1vel 'PAIRUS_API_KEY'."
298
+ );
299
+ }
300
+ const baseUrl = options?.baseUrl || (typeof process !== "undefined" ? process.env.PAIRUS_BASE_URL : void 0) || DEFAULT_BASE_URL;
301
+ const timeoutMs = options?.timeoutMs || DEFAULT_TIMEOUT_MS;
302
+ const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
303
+ this.products = new ProductsResource(apiKey, baseUrl, timeoutMs, maxRetries);
304
+ this.fiscal = new FiscalResource(apiKey, baseUrl, timeoutMs, maxRetries);
305
+ }
306
+ };
307
+ // Annotate the CommonJS export names for ESM import in node:
308
+ 0 && (module.exports = {
309
+ AuthenticationError,
310
+ DEFAULT_BASE_URL,
311
+ DEFAULT_MAX_RETRIES,
312
+ DEFAULT_TIMEOUT_MS,
313
+ InvalidSignatureError,
314
+ NetworkError,
315
+ PairusAPIError,
316
+ PairusError,
317
+ PairusProductData,
318
+ RateLimitError,
319
+ Webhooks
320
+ });
321
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/resources/base.ts","../src/resources/fiscal.ts","../src/resources/products.ts","../src/webhooks.ts","../src/client.ts"],"sourcesContent":["export { PairusProductData } from './client.js';\r\nexport { Webhooks } from './webhooks.js';\r\nexport * from './errors.js';\r\nexport * from './config.js';\r\nexport * from './types/index.js';\r\n","/**\r\n * Opções de configuração para o cliente PairusProductData.\r\n */\r\n\r\nexport interface PairusClientOptions {\r\n apiKey?: string;\r\n baseUrl?: string;\r\n timeoutMs?: number;\r\n maxRetries?: number;\r\n}\r\n\r\nexport const DEFAULT_BASE_URL = 'https://api.pairus.com.br';\r\nexport const DEFAULT_TIMEOUT_MS = 15000;\r\nexport const DEFAULT_MAX_RETRIES = 3;\r\n","/**\r\n * Classes de erro oficiais do SDK @pairus/product-data.\r\n */\r\n\r\nexport class PairusError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'PairusError';\r\n }\r\n}\r\n\r\nexport class PairusAPIError extends PairusError {\r\n public readonly statusCode: number;\r\n public readonly cStat: string;\r\n public readonly xMotivo: string;\r\n public readonly details?: any;\r\n\r\n constructor(statusCode: number, cStat?: string, xMotivo?: string, details?: any) {\r\n const code = cStat || String(statusCode);\r\n const reason = xMotivo || details?.detail || `Erro HTTP ${statusCode}`;\r\n super(`[${code}] ${reason}`);\r\n this.name = 'PairusAPIError';\r\n this.statusCode = statusCode;\r\n this.cStat = code;\r\n this.xMotivo = reason;\r\n this.details = details;\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends PairusAPIError {\r\n constructor(cStat = '401', xMotivo = 'Chave de API inválida ou não autorizada.', details?: any) {\r\n super(401, cStat, xMotivo, details);\r\n this.name = 'AuthenticationError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends PairusAPIError {\r\n public readonly retryAfter?: number;\r\n\r\n constructor(retryAfter?: number, cStat = '429', xMotivo = 'Limite de requisições excedido.', details?: any) {\r\n super(429, cStat, xMotivo, details);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class InvalidSignatureError extends PairusError {\r\n constructor(message = \"A assinatura criptográfica do webhook ('X-Pairus-Signature') é inválida.\") {\r\n super(message);\r\n this.name = 'InvalidSignatureError';\r\n }\r\n}\r\n\r\nexport class NetworkError extends PairusError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'NetworkError';\r\n }\r\n}\r\n","import {\r\n AuthenticationError,\r\n NetworkError,\r\n PairusAPIError,\r\n RateLimitError,\r\n} from '../errors.js';\r\n\r\nexport interface RequestOptions {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string>;\r\n body?: any;\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport class BaseResource {\r\n protected apiKey: string;\r\n protected baseUrl: string;\r\n protected timeoutMs: number;\r\n protected maxRetries: number;\r\n\r\n constructor(apiKey: string, baseUrl: string, timeoutMs: number, maxRetries: number) {\r\n this.apiKey = apiKey;\r\n this.baseUrl = baseUrl.replace(/\\/+$/, '');\r\n this.timeoutMs = timeoutMs;\r\n this.maxRetries = maxRetries;\r\n }\r\n\r\n protected async request<T>(options: RequestOptions): Promise<T> {\r\n let url = `${this.baseUrl}/${options.path.replace(/^\\/+/, '')}`;\r\n if (options.params) {\r\n const query = new URLSearchParams(options.params).toString();\r\n url = `${url}?${query}`;\r\n }\r\n\r\n const reqHeaders: Record<string, string> = {\r\n 'Accept': 'application/json',\r\n 'X-API-Key': this.apiKey,\r\n 'User-Agent': 'Pairus-NodeJS-SDK/1.0.0',\r\n ...(options.headers || {}),\r\n };\r\n\r\n if (options.body) {\r\n reqHeaders['Content-Type'] = 'application/json';\r\n }\r\n\r\n let lastError: any = null;\r\n\r\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\r\n try {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\r\n\r\n const response = await fetch(url, {\r\n method: options.method,\r\n headers: reqHeaders,\r\n body: options.body ? JSON.stringify(options.body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (response.ok) {\r\n return (await response.json()) as T;\r\n }\r\n\r\n let errData: any = {};\r\n try {\r\n errData = await response.json();\r\n } catch {\r\n errData = {};\r\n }\r\n\r\n if (response.status === 401) {\r\n throw new AuthenticationError(errData.cStat, errData.xMotivo, errData);\r\n }\r\n\r\n if (response.status === 429) {\r\n const retryAfterSec = parseFloat(response.headers.get('Retry-After') || '2');\r\n if (attempt < this.maxRetries - 1) {\r\n await new Promise((res) => setTimeout(res, (retryAfterSec + Math.random() * 0.5) * 1000));\r\n continue;\r\n }\r\n throw new RateLimitError(retryAfterSec, errData.cStat, errData.xMotivo, errData);\r\n }\r\n\r\n if ([502, 503, 504].includes(response.status) && attempt < this.maxRetries - 1) {\r\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;\r\n await new Promise((res) => setTimeout(res, delay));\r\n continue;\r\n }\r\n\r\n throw new PairusAPIError(response.status, errData.cStat, errData.xMotivo, errData);\r\n } catch (err: any) {\r\n if (err instanceof PairusAPIError) {\r\n throw err;\r\n }\r\n lastError = err;\r\n if (attempt < this.maxRetries - 1) {\r\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;\r\n await new Promise((res) => setTimeout(res, delay));\r\n continue;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n throw new NetworkError(`Falha de conexão com a API PAIRUS após ${this.maxRetries} tentativas: ${lastError?.message || lastError}`);\r\n }\r\n}\r\n","import { BaseResource } from './base.js';\r\nimport { TaxPredictionParams, TaxPredictionResponse } from '../types/fiscal.js';\r\n\r\nexport class FiscalResource extends BaseResource {\r\n /**\r\n * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.\r\n */\r\n public async predict(params: TaxPredictionParams): Promise<TaxPredictionResponse> {\r\n const payload: Record<string, any> = {\r\n regime_tributario: params.regimeTributario,\r\n uf_origem: params.ufOrigem,\r\n uf_destino: params.ufDestino || params.ufOrigem,\r\n finalidade: params.finalidade || 'revenda',\r\n destinatario_contribuinte: params.destinatarioContribuinte ?? true,\r\n };\r\n\r\n if (params.xProd) payload.xProd = params.xProd;\r\n if (params.gtin) payload.gtin = params.gtin;\r\n if (params.ncm) payload.ncm = params.ncm;\r\n if (params.cest) payload.cest = params.cest;\r\n if (params.itens) payload.itens = params.itens;\r\n\r\n return this.request<TaxPredictionResponse>({\r\n method: 'POST',\r\n path: '/v2/fiscal/predict',\r\n body: payload,\r\n });\r\n }\r\n}\r\n","import { BaseResource } from './base.js';\r\nimport { ProductDetails, ProductResponse } from '../types/product.js';\r\n\r\nexport class ProductsResource extends BaseResource {\r\n /**\r\n * Consulta um produto por código de barras GTIN/EAN.\r\n * @param gtin Código numérico de 8 a 14 dígitos.\r\n */\r\n public async get(gtin: string): Promise<ProductDetails> {\r\n const gtinLimpo = gtin.replace(/\\D/g, '');\r\n const data = await this.request<ProductResponse>({\r\n method: 'GET',\r\n path: `/api/produtos/${gtinLimpo}`,\r\n });\r\n\r\n const prod: any = data.produto || data;\r\n return {\r\n gtin: prod.GTIN || prod.gtin || gtinLimpo,\r\n xProd: prod.xProd || prod.descricao || 'Descrição Indisponível',\r\n ncm: prod.NCM || prod.ncm,\r\n cest: prod.CEST || prod.cest,\r\n marca: prod.marca,\r\n fabricante: prod.fabricante,\r\n categoria: prod.categoria,\r\n imagemUrl: prod.imagem_url || prod.thumbnail,\r\n pesoBruto: prod.peso_bruto ? Number(prod.peso_bruto) : undefined,\r\n pesoLiquido: prod.peso_liquido ? Number(prod.peso_liquido) : undefined,\r\n quantidadeEmbalagem: Number(prod.quantidade_embalagem || 1),\r\n };\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { InvalidSignatureError } from './errors.js';\r\nimport { WebhookEvent } from './types/webhook.js';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.\r\n */\r\n public static computeSignature(payload: string | Buffer, secret: string): string {\r\n return crypto\r\n .createHmac('sha256', secret)\r\n .update(payload)\r\n .digest('hex');\r\n }\r\n\r\n /**\r\n * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.\r\n */\r\n public static verifySignature(\r\n payload: string | Buffer | Record<string, any>,\r\n signature: string | undefined | null,\r\n secret: string\r\n ): boolean {\r\n if (!signature || !secret) {\r\n return false;\r\n }\r\n\r\n let payloadBuffer: Buffer;\r\n if (Buffer.isBuffer(payload)) {\r\n payloadBuffer = payload;\r\n } else if (typeof payload === 'string') {\r\n payloadBuffer = Buffer.from(payload, 'utf-8');\r\n } else {\r\n payloadBuffer = Buffer.from(JSON.stringify(payload), 'utf-8');\r\n }\r\n\r\n const expectedSignature = this.computeSignature(payloadBuffer, secret);\r\n\r\n try {\r\n const sigBuf = Buffer.from(signature.trim(), 'hex');\r\n const expectedBuf = Buffer.from(expectedSignature, 'hex');\r\n\r\n if (sigBuf.length !== expectedBuf.length) {\r\n return false;\r\n }\r\n\r\n return crypto.timingSafeEqual(sigBuf, expectedBuf);\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.\r\n */\r\n public static constructEvent<T = Record<string, any>>(\r\n payload: string | Buffer,\r\n signature: string | undefined | null,\r\n secret: string\r\n ): WebhookEvent<T> {\r\n if (!this.verifySignature(payload, signature, secret)) {\r\n throw new InvalidSignatureError(\"Assinatura do webhook ('X-Pairus-Signature') é inválida.\");\r\n }\r\n\r\n const rawStr = Buffer.isBuffer(payload) ? payload.toString('utf-8') : payload;\r\n return JSON.parse(rawStr) as WebhookEvent<T>;\r\n }\r\n}\r\n","import {\r\n DEFAULT_BASE_URL,\r\n DEFAULT_MAX_RETRIES,\r\n DEFAULT_TIMEOUT_MS,\r\n PairusClientOptions,\r\n} from './config.js';\r\nimport { FiscalResource } from './resources/fiscal.js';\r\nimport { ProductsResource } from './resources/products.js';\r\nimport { Webhooks } from './webhooks.js';\r\n\r\nexport class PairusProductData {\r\n public static readonly webhooks = Webhooks;\r\n public readonly webhooks = Webhooks;\r\n\r\n public readonly products: ProductsResource;\r\n public readonly fiscal: FiscalResource;\r\n\r\n constructor(options?: PairusClientOptions) {\r\n const apiKey = options?.apiKey || (typeof process !== 'undefined' ? process.env.PAIRUS_API_KEY : undefined);\r\n if (!apiKey) {\r\n throw new Error(\r\n \"A chave de API da PAIRUS é obrigatória. Passe 'apiKey' no construtor ou defina a variável 'PAIRUS_API_KEY'.\"\r\n );\r\n }\r\n\r\n const baseUrl = options?.baseUrl || (typeof process !== 'undefined' ? process.env.PAIRUS_BASE_URL : undefined) || DEFAULT_BASE_URL;\r\n const timeoutMs = options?.timeoutMs || DEFAULT_TIMEOUT_MS;\r\n const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n\r\n this.products = new ProductsResource(apiKey, baseUrl, timeoutMs, maxRetries);\r\n this.fiscal = new FiscalResource(apiKey, baseUrl, timeoutMs, maxRetries);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.mjs ADDED
@@ -0,0 +1,274 @@
1
+ // src/config.ts
2
+ var DEFAULT_BASE_URL = "https://api.pairus.com.br";
3
+ var DEFAULT_TIMEOUT_MS = 15e3;
4
+ var DEFAULT_MAX_RETRIES = 3;
5
+
6
+ // src/errors.ts
7
+ var PairusError = class extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = "PairusError";
11
+ }
12
+ };
13
+ var PairusAPIError = class extends PairusError {
14
+ statusCode;
15
+ cStat;
16
+ xMotivo;
17
+ details;
18
+ constructor(statusCode, cStat, xMotivo, details) {
19
+ const code = cStat || String(statusCode);
20
+ const reason = xMotivo || details?.detail || `Erro HTTP ${statusCode}`;
21
+ super(`[${code}] ${reason}`);
22
+ this.name = "PairusAPIError";
23
+ this.statusCode = statusCode;
24
+ this.cStat = code;
25
+ this.xMotivo = reason;
26
+ this.details = details;
27
+ }
28
+ };
29
+ var AuthenticationError = class extends PairusAPIError {
30
+ constructor(cStat = "401", xMotivo = "Chave de API inv\xE1lida ou n\xE3o autorizada.", details) {
31
+ super(401, cStat, xMotivo, details);
32
+ this.name = "AuthenticationError";
33
+ }
34
+ };
35
+ var RateLimitError = class extends PairusAPIError {
36
+ retryAfter;
37
+ constructor(retryAfter, cStat = "429", xMotivo = "Limite de requisi\xE7\xF5es excedido.", details) {
38
+ super(429, cStat, xMotivo, details);
39
+ this.name = "RateLimitError";
40
+ this.retryAfter = retryAfter;
41
+ }
42
+ };
43
+ var InvalidSignatureError = class extends PairusError {
44
+ constructor(message = "A assinatura criptogr\xE1fica do webhook ('X-Pairus-Signature') \xE9 inv\xE1lida.") {
45
+ super(message);
46
+ this.name = "InvalidSignatureError";
47
+ }
48
+ };
49
+ var NetworkError = class extends PairusError {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = "NetworkError";
53
+ }
54
+ };
55
+
56
+ // src/resources/base.ts
57
+ var BaseResource = class {
58
+ apiKey;
59
+ baseUrl;
60
+ timeoutMs;
61
+ maxRetries;
62
+ constructor(apiKey, baseUrl, timeoutMs, maxRetries) {
63
+ this.apiKey = apiKey;
64
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
65
+ this.timeoutMs = timeoutMs;
66
+ this.maxRetries = maxRetries;
67
+ }
68
+ async request(options) {
69
+ let url = `${this.baseUrl}/${options.path.replace(/^\/+/, "")}`;
70
+ if (options.params) {
71
+ const query = new URLSearchParams(options.params).toString();
72
+ url = `${url}?${query}`;
73
+ }
74
+ const reqHeaders = {
75
+ "Accept": "application/json",
76
+ "X-API-Key": this.apiKey,
77
+ "User-Agent": "Pairus-NodeJS-SDK/1.0.0",
78
+ ...options.headers || {}
79
+ };
80
+ if (options.body) {
81
+ reqHeaders["Content-Type"] = "application/json";
82
+ }
83
+ let lastError = null;
84
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
85
+ try {
86
+ const controller = new AbortController();
87
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
88
+ const response = await fetch(url, {
89
+ method: options.method,
90
+ headers: reqHeaders,
91
+ body: options.body ? JSON.stringify(options.body) : void 0,
92
+ signal: controller.signal
93
+ });
94
+ clearTimeout(timeoutId);
95
+ if (response.ok) {
96
+ return await response.json();
97
+ }
98
+ let errData = {};
99
+ try {
100
+ errData = await response.json();
101
+ } catch {
102
+ errData = {};
103
+ }
104
+ if (response.status === 401) {
105
+ throw new AuthenticationError(errData.cStat, errData.xMotivo, errData);
106
+ }
107
+ if (response.status === 429) {
108
+ const retryAfterSec = parseFloat(response.headers.get("Retry-After") || "2");
109
+ if (attempt < this.maxRetries - 1) {
110
+ await new Promise((res) => setTimeout(res, (retryAfterSec + Math.random() * 0.5) * 1e3));
111
+ continue;
112
+ }
113
+ throw new RateLimitError(retryAfterSec, errData.cStat, errData.xMotivo, errData);
114
+ }
115
+ if ([502, 503, 504].includes(response.status) && attempt < this.maxRetries - 1) {
116
+ const delay = Math.pow(2, attempt) * 1e3 + Math.random() * 500;
117
+ await new Promise((res) => setTimeout(res, delay));
118
+ continue;
119
+ }
120
+ throw new PairusAPIError(response.status, errData.cStat, errData.xMotivo, errData);
121
+ } catch (err) {
122
+ if (err instanceof PairusAPIError) {
123
+ throw err;
124
+ }
125
+ lastError = err;
126
+ if (attempt < this.maxRetries - 1) {
127
+ const delay = Math.pow(2, attempt) * 1e3 + Math.random() * 500;
128
+ await new Promise((res) => setTimeout(res, delay));
129
+ continue;
130
+ }
131
+ break;
132
+ }
133
+ }
134
+ throw new NetworkError(`Falha de conex\xE3o com a API PAIRUS ap\xF3s ${this.maxRetries} tentativas: ${lastError?.message || lastError}`);
135
+ }
136
+ };
137
+
138
+ // src/resources/fiscal.ts
139
+ var FiscalResource = class extends BaseResource {
140
+ /**
141
+ * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.
142
+ */
143
+ async predict(params) {
144
+ const payload = {
145
+ regime_tributario: params.regimeTributario,
146
+ uf_origem: params.ufOrigem,
147
+ uf_destino: params.ufDestino || params.ufOrigem,
148
+ finalidade: params.finalidade || "revenda",
149
+ destinatario_contribuinte: params.destinatarioContribuinte ?? true
150
+ };
151
+ if (params.xProd) payload.xProd = params.xProd;
152
+ if (params.gtin) payload.gtin = params.gtin;
153
+ if (params.ncm) payload.ncm = params.ncm;
154
+ if (params.cest) payload.cest = params.cest;
155
+ if (params.itens) payload.itens = params.itens;
156
+ return this.request({
157
+ method: "POST",
158
+ path: "/v2/fiscal/predict",
159
+ body: payload
160
+ });
161
+ }
162
+ };
163
+
164
+ // src/resources/products.ts
165
+ var ProductsResource = class extends BaseResource {
166
+ /**
167
+ * Consulta um produto por código de barras GTIN/EAN.
168
+ * @param gtin Código numérico de 8 a 14 dígitos.
169
+ */
170
+ async get(gtin) {
171
+ const gtinLimpo = gtin.replace(/\D/g, "");
172
+ const data = await this.request({
173
+ method: "GET",
174
+ path: `/api/produtos/${gtinLimpo}`
175
+ });
176
+ const prod = data.produto || data;
177
+ return {
178
+ gtin: prod.GTIN || prod.gtin || gtinLimpo,
179
+ xProd: prod.xProd || prod.descricao || "Descri\xE7\xE3o Indispon\xEDvel",
180
+ ncm: prod.NCM || prod.ncm,
181
+ cest: prod.CEST || prod.cest,
182
+ marca: prod.marca,
183
+ fabricante: prod.fabricante,
184
+ categoria: prod.categoria,
185
+ imagemUrl: prod.imagem_url || prod.thumbnail,
186
+ pesoBruto: prod.peso_bruto ? Number(prod.peso_bruto) : void 0,
187
+ pesoLiquido: prod.peso_liquido ? Number(prod.peso_liquido) : void 0,
188
+ quantidadeEmbalagem: Number(prod.quantidade_embalagem || 1)
189
+ };
190
+ }
191
+ };
192
+
193
+ // src/webhooks.ts
194
+ import * as crypto from "crypto";
195
+ var Webhooks = class {
196
+ /**
197
+ * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.
198
+ */
199
+ static computeSignature(payload, secret) {
200
+ return crypto.createHmac("sha256", secret).update(payload).digest("hex");
201
+ }
202
+ /**
203
+ * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.
204
+ */
205
+ static verifySignature(payload, signature, secret) {
206
+ if (!signature || !secret) {
207
+ return false;
208
+ }
209
+ let payloadBuffer;
210
+ if (Buffer.isBuffer(payload)) {
211
+ payloadBuffer = payload;
212
+ } else if (typeof payload === "string") {
213
+ payloadBuffer = Buffer.from(payload, "utf-8");
214
+ } else {
215
+ payloadBuffer = Buffer.from(JSON.stringify(payload), "utf-8");
216
+ }
217
+ const expectedSignature = this.computeSignature(payloadBuffer, secret);
218
+ try {
219
+ const sigBuf = Buffer.from(signature.trim(), "hex");
220
+ const expectedBuf = Buffer.from(expectedSignature, "hex");
221
+ if (sigBuf.length !== expectedBuf.length) {
222
+ return false;
223
+ }
224
+ return crypto.timingSafeEqual(sigBuf, expectedBuf);
225
+ } catch {
226
+ return false;
227
+ }
228
+ }
229
+ /**
230
+ * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.
231
+ */
232
+ static constructEvent(payload, signature, secret) {
233
+ if (!this.verifySignature(payload, signature, secret)) {
234
+ throw new InvalidSignatureError("Assinatura do webhook ('X-Pairus-Signature') \xE9 inv\xE1lida.");
235
+ }
236
+ const rawStr = Buffer.isBuffer(payload) ? payload.toString("utf-8") : payload;
237
+ return JSON.parse(rawStr);
238
+ }
239
+ };
240
+
241
+ // src/client.ts
242
+ var PairusProductData = class {
243
+ static webhooks = Webhooks;
244
+ webhooks = Webhooks;
245
+ products;
246
+ fiscal;
247
+ constructor(options) {
248
+ const apiKey = options?.apiKey || (typeof process !== "undefined" ? process.env.PAIRUS_API_KEY : void 0);
249
+ if (!apiKey) {
250
+ throw new Error(
251
+ "A chave de API da PAIRUS \xE9 obrigat\xF3ria. Passe 'apiKey' no construtor ou defina a vari\xE1vel 'PAIRUS_API_KEY'."
252
+ );
253
+ }
254
+ const baseUrl = options?.baseUrl || (typeof process !== "undefined" ? process.env.PAIRUS_BASE_URL : void 0) || DEFAULT_BASE_URL;
255
+ const timeoutMs = options?.timeoutMs || DEFAULT_TIMEOUT_MS;
256
+ const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
257
+ this.products = new ProductsResource(apiKey, baseUrl, timeoutMs, maxRetries);
258
+ this.fiscal = new FiscalResource(apiKey, baseUrl, timeoutMs, maxRetries);
259
+ }
260
+ };
261
+ export {
262
+ AuthenticationError,
263
+ DEFAULT_BASE_URL,
264
+ DEFAULT_MAX_RETRIES,
265
+ DEFAULT_TIMEOUT_MS,
266
+ InvalidSignatureError,
267
+ NetworkError,
268
+ PairusAPIError,
269
+ PairusError,
270
+ PairusProductData,
271
+ RateLimitError,
272
+ Webhooks
273
+ };
274
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/resources/base.ts","../src/resources/fiscal.ts","../src/resources/products.ts","../src/webhooks.ts","../src/client.ts"],"sourcesContent":["/**\r\n * Opções de configuração para o cliente PairusProductData.\r\n */\r\n\r\nexport interface PairusClientOptions {\r\n apiKey?: string;\r\n baseUrl?: string;\r\n timeoutMs?: number;\r\n maxRetries?: number;\r\n}\r\n\r\nexport const DEFAULT_BASE_URL = 'https://api.pairus.com.br';\r\nexport const DEFAULT_TIMEOUT_MS = 15000;\r\nexport const DEFAULT_MAX_RETRIES = 3;\r\n","/**\r\n * Classes de erro oficiais do SDK @pairus/product-data.\r\n */\r\n\r\nexport class PairusError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'PairusError';\r\n }\r\n}\r\n\r\nexport class PairusAPIError extends PairusError {\r\n public readonly statusCode: number;\r\n public readonly cStat: string;\r\n public readonly xMotivo: string;\r\n public readonly details?: any;\r\n\r\n constructor(statusCode: number, cStat?: string, xMotivo?: string, details?: any) {\r\n const code = cStat || String(statusCode);\r\n const reason = xMotivo || details?.detail || `Erro HTTP ${statusCode}`;\r\n super(`[${code}] ${reason}`);\r\n this.name = 'PairusAPIError';\r\n this.statusCode = statusCode;\r\n this.cStat = code;\r\n this.xMotivo = reason;\r\n this.details = details;\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends PairusAPIError {\r\n constructor(cStat = '401', xMotivo = 'Chave de API inválida ou não autorizada.', details?: any) {\r\n super(401, cStat, xMotivo, details);\r\n this.name = 'AuthenticationError';\r\n }\r\n}\r\n\r\nexport class RateLimitError extends PairusAPIError {\r\n public readonly retryAfter?: number;\r\n\r\n constructor(retryAfter?: number, cStat = '429', xMotivo = 'Limite de requisições excedido.', details?: any) {\r\n super(429, cStat, xMotivo, details);\r\n this.name = 'RateLimitError';\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class InvalidSignatureError extends PairusError {\r\n constructor(message = \"A assinatura criptográfica do webhook ('X-Pairus-Signature') é inválida.\") {\r\n super(message);\r\n this.name = 'InvalidSignatureError';\r\n }\r\n}\r\n\r\nexport class NetworkError extends PairusError {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = 'NetworkError';\r\n }\r\n}\r\n","import {\r\n AuthenticationError,\r\n NetworkError,\r\n PairusAPIError,\r\n RateLimitError,\r\n} from '../errors.js';\r\n\r\nexport interface RequestOptions {\r\n method: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n path: string;\r\n params?: Record<string, string>;\r\n body?: any;\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport class BaseResource {\r\n protected apiKey: string;\r\n protected baseUrl: string;\r\n protected timeoutMs: number;\r\n protected maxRetries: number;\r\n\r\n constructor(apiKey: string, baseUrl: string, timeoutMs: number, maxRetries: number) {\r\n this.apiKey = apiKey;\r\n this.baseUrl = baseUrl.replace(/\\/+$/, '');\r\n this.timeoutMs = timeoutMs;\r\n this.maxRetries = maxRetries;\r\n }\r\n\r\n protected async request<T>(options: RequestOptions): Promise<T> {\r\n let url = `${this.baseUrl}/${options.path.replace(/^\\/+/, '')}`;\r\n if (options.params) {\r\n const query = new URLSearchParams(options.params).toString();\r\n url = `${url}?${query}`;\r\n }\r\n\r\n const reqHeaders: Record<string, string> = {\r\n 'Accept': 'application/json',\r\n 'X-API-Key': this.apiKey,\r\n 'User-Agent': 'Pairus-NodeJS-SDK/1.0.0',\r\n ...(options.headers || {}),\r\n };\r\n\r\n if (options.body) {\r\n reqHeaders['Content-Type'] = 'application/json';\r\n }\r\n\r\n let lastError: any = null;\r\n\r\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\r\n try {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\r\n\r\n const response = await fetch(url, {\r\n method: options.method,\r\n headers: reqHeaders,\r\n body: options.body ? JSON.stringify(options.body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (response.ok) {\r\n return (await response.json()) as T;\r\n }\r\n\r\n let errData: any = {};\r\n try {\r\n errData = await response.json();\r\n } catch {\r\n errData = {};\r\n }\r\n\r\n if (response.status === 401) {\r\n throw new AuthenticationError(errData.cStat, errData.xMotivo, errData);\r\n }\r\n\r\n if (response.status === 429) {\r\n const retryAfterSec = parseFloat(response.headers.get('Retry-After') || '2');\r\n if (attempt < this.maxRetries - 1) {\r\n await new Promise((res) => setTimeout(res, (retryAfterSec + Math.random() * 0.5) * 1000));\r\n continue;\r\n }\r\n throw new RateLimitError(retryAfterSec, errData.cStat, errData.xMotivo, errData);\r\n }\r\n\r\n if ([502, 503, 504].includes(response.status) && attempt < this.maxRetries - 1) {\r\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;\r\n await new Promise((res) => setTimeout(res, delay));\r\n continue;\r\n }\r\n\r\n throw new PairusAPIError(response.status, errData.cStat, errData.xMotivo, errData);\r\n } catch (err: any) {\r\n if (err instanceof PairusAPIError) {\r\n throw err;\r\n }\r\n lastError = err;\r\n if (attempt < this.maxRetries - 1) {\r\n const delay = Math.pow(2, attempt) * 1000 + Math.random() * 500;\r\n await new Promise((res) => setTimeout(res, delay));\r\n continue;\r\n }\r\n break;\r\n }\r\n }\r\n\r\n throw new NetworkError(`Falha de conexão com a API PAIRUS após ${this.maxRetries} tentativas: ${lastError?.message || lastError}`);\r\n }\r\n}\r\n","import { BaseResource } from './base.js';\r\nimport { TaxPredictionParams, TaxPredictionResponse } from '../types/fiscal.js';\r\n\r\nexport class FiscalResource extends BaseResource {\r\n /**\r\n * Executa a predição fiscal completa da Reforma Tributária (IBS/CBS/IS) e NF-e.\r\n */\r\n public async predict(params: TaxPredictionParams): Promise<TaxPredictionResponse> {\r\n const payload: Record<string, any> = {\r\n regime_tributario: params.regimeTributario,\r\n uf_origem: params.ufOrigem,\r\n uf_destino: params.ufDestino || params.ufOrigem,\r\n finalidade: params.finalidade || 'revenda',\r\n destinatario_contribuinte: params.destinatarioContribuinte ?? true,\r\n };\r\n\r\n if (params.xProd) payload.xProd = params.xProd;\r\n if (params.gtin) payload.gtin = params.gtin;\r\n if (params.ncm) payload.ncm = params.ncm;\r\n if (params.cest) payload.cest = params.cest;\r\n if (params.itens) payload.itens = params.itens;\r\n\r\n return this.request<TaxPredictionResponse>({\r\n method: 'POST',\r\n path: '/v2/fiscal/predict',\r\n body: payload,\r\n });\r\n }\r\n}\r\n","import { BaseResource } from './base.js';\r\nimport { ProductDetails, ProductResponse } from '../types/product.js';\r\n\r\nexport class ProductsResource extends BaseResource {\r\n /**\r\n * Consulta um produto por código de barras GTIN/EAN.\r\n * @param gtin Código numérico de 8 a 14 dígitos.\r\n */\r\n public async get(gtin: string): Promise<ProductDetails> {\r\n const gtinLimpo = gtin.replace(/\\D/g, '');\r\n const data = await this.request<ProductResponse>({\r\n method: 'GET',\r\n path: `/api/produtos/${gtinLimpo}`,\r\n });\r\n\r\n const prod: any = data.produto || data;\r\n return {\r\n gtin: prod.GTIN || prod.gtin || gtinLimpo,\r\n xProd: prod.xProd || prod.descricao || 'Descrição Indisponível',\r\n ncm: prod.NCM || prod.ncm,\r\n cest: prod.CEST || prod.cest,\r\n marca: prod.marca,\r\n fabricante: prod.fabricante,\r\n categoria: prod.categoria,\r\n imagemUrl: prod.imagem_url || prod.thumbnail,\r\n pesoBruto: prod.peso_bruto ? Number(prod.peso_bruto) : undefined,\r\n pesoLiquido: prod.peso_liquido ? Number(prod.peso_liquido) : undefined,\r\n quantidadeEmbalagem: Number(prod.quantidade_embalagem || 1),\r\n };\r\n }\r\n}\r\n","import * as crypto from 'crypto';\r\nimport { InvalidSignatureError } from './errors.js';\r\nimport { WebhookEvent } from './types/webhook.js';\r\n\r\nexport class Webhooks {\r\n /**\r\n * Calcula a assinatura HMAC-SHA256 esperada para o payload informado.\r\n */\r\n public static computeSignature(payload: string | Buffer, secret: string): string {\r\n return crypto\r\n .createHmac('sha256', secret)\r\n .update(payload)\r\n .digest('hex');\r\n }\r\n\r\n /**\r\n * Verifica de forma segura (resistente a timing attacks) a assinatura de um webhook.\r\n */\r\n public static verifySignature(\r\n payload: string | Buffer | Record<string, any>,\r\n signature: string | undefined | null,\r\n secret: string\r\n ): boolean {\r\n if (!signature || !secret) {\r\n return false;\r\n }\r\n\r\n let payloadBuffer: Buffer;\r\n if (Buffer.isBuffer(payload)) {\r\n payloadBuffer = payload;\r\n } else if (typeof payload === 'string') {\r\n payloadBuffer = Buffer.from(payload, 'utf-8');\r\n } else {\r\n payloadBuffer = Buffer.from(JSON.stringify(payload), 'utf-8');\r\n }\r\n\r\n const expectedSignature = this.computeSignature(payloadBuffer, secret);\r\n\r\n try {\r\n const sigBuf = Buffer.from(signature.trim(), 'hex');\r\n const expectedBuf = Buffer.from(expectedSignature, 'hex');\r\n\r\n if (sigBuf.length !== expectedBuf.length) {\r\n return false;\r\n }\r\n\r\n return crypto.timingSafeEqual(sigBuf, expectedBuf);\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Valida a assinatura e converte o payload em objeto tipado WebhookEvent.\r\n */\r\n public static constructEvent<T = Record<string, any>>(\r\n payload: string | Buffer,\r\n signature: string | undefined | null,\r\n secret: string\r\n ): WebhookEvent<T> {\r\n if (!this.verifySignature(payload, signature, secret)) {\r\n throw new InvalidSignatureError(\"Assinatura do webhook ('X-Pairus-Signature') é inválida.\");\r\n }\r\n\r\n const rawStr = Buffer.isBuffer(payload) ? payload.toString('utf-8') : payload;\r\n return JSON.parse(rawStr) as WebhookEvent<T>;\r\n }\r\n}\r\n","import {\r\n DEFAULT_BASE_URL,\r\n DEFAULT_MAX_RETRIES,\r\n DEFAULT_TIMEOUT_MS,\r\n PairusClientOptions,\r\n} from './config.js';\r\nimport { FiscalResource } from './resources/fiscal.js';\r\nimport { ProductsResource } from './resources/products.js';\r\nimport { Webhooks } from './webhooks.js';\r\n\r\nexport class PairusProductData {\r\n public static readonly webhooks = Webhooks;\r\n public readonly webhooks = Webhooks;\r\n\r\n public readonly products: ProductsResource;\r\n public readonly fiscal: FiscalResource;\r\n\r\n constructor(options?: PairusClientOptions) {\r\n const apiKey = options?.apiKey || (typeof process !== 'undefined' ? process.env.PAIRUS_API_KEY : undefined);\r\n if (!apiKey) {\r\n throw new Error(\r\n \"A chave de API da PAIRUS é obrigatória. Passe 'apiKey' no construtor ou defina a variável 'PAIRUS_API_KEY'.\"\r\n );\r\n }\r\n\r\n const baseUrl = options?.baseUrl || (typeof process !== 'undefined' ? process.env.PAIRUS_BASE_URL : undefined) || DEFAULT_BASE_URL;\r\n const timeoutMs = options?.timeoutMs || DEFAULT_TIMEOUT_MS;\r\n const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;\r\n\r\n this.products = new ProductsResource(apiKey, baseUrl, timeoutMs, maxRetries);\r\n this.fiscal = new FiscalResource(apiKey, baseUrl, timeoutMs, maxRetries);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@pairus/product-data",
3
+ "version": "1.0.0",
4
+ "description": "SDK oficial da PAIRUS para integração com o catálogo GTIN/EAN e motor de predição fiscal da Reforma Tributária (IBS/CBS/IS).",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup",
22
+ "test": "vitest run",
23
+ "lint": "eslint src/**/*.ts",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "keywords": [
30
+ "pairus",
31
+ "gtin",
32
+ "ean",
33
+ "fiscal",
34
+ "reforma-tributaria",
35
+ "ibs",
36
+ "cbs",
37
+ "imposto-seletivo",
38
+ "nfe",
39
+ "sefaz",
40
+ "tributacao"
41
+ ],
42
+ "author": "PAIRUS Soluções Tecnológicas <suporte@pairus.com.br>",
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/marcos2r/api-consulta-gtin.git",
47
+ "directory": "sdks/nodejs"
48
+ },
49
+ "devDependencies": {
50
+ "@types/node": "^20.14.0",
51
+ "tsup": "^8.1.0",
52
+ "typescript": "^5.4.5",
53
+ "vitest": "^1.6.0"
54
+ },
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ }
58
+ }