iptuapi 2.1.0 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,610 +1,666 @@
1
- // src/errors.ts
1
+ // src/index.ts
2
+ var CidadeEnum = {
3
+ SAO_PAULO: "sp",
4
+ BELO_HORIZONTE: "bh",
5
+ RECIFE: "recife",
6
+ PORTO_ALEGRE: "poa",
7
+ FORTALEZA: "fortaleza",
8
+ CURITIBA: "curitiba",
9
+ RIO_DE_JANEIRO: "rj",
10
+ BRASILIA: "brasilia"
11
+ };
2
12
  var IPTUAPIError = class _IPTUAPIError extends Error {
3
13
  statusCode;
4
14
  requestId;
5
- responseData;
6
- constructor(message, statusCode, requestId, responseData) {
15
+ responseBody;
16
+ constructor(message, statusCode, requestId, responseBody) {
7
17
  super(message);
8
18
  this.name = "IPTUAPIError";
9
19
  this.statusCode = statusCode;
10
20
  this.requestId = requestId;
11
- this.responseData = responseData || {};
21
+ this.responseBody = responseBody;
12
22
  Object.setPrototypeOf(this, _IPTUAPIError.prototype);
13
23
  }
14
- isRetryable() {
15
- return false;
16
- }
17
- toJSON() {
18
- return {
19
- error: this.name,
20
- message: this.message,
21
- statusCode: this.statusCode,
22
- requestId: this.requestId,
23
- retryable: this.isRetryable()
24
- };
24
+ get isRetryable() {
25
+ return this.statusCode ? [429, 500, 502, 503, 504].includes(this.statusCode) : false;
25
26
  }
26
27
  };
27
28
  var AuthenticationError = class _AuthenticationError extends IPTUAPIError {
28
- constructor(message = "API Key invalida ou ausente", requestId) {
29
- super(message, 401, requestId);
29
+ constructor(message = "API Key inv\xE1lida ou expirada", requestId, responseBody) {
30
+ super(message, 401, requestId, responseBody);
30
31
  this.name = "AuthenticationError";
31
32
  Object.setPrototypeOf(this, _AuthenticationError.prototype);
32
33
  }
33
34
  };
34
35
  var ForbiddenError = class _ForbiddenError extends IPTUAPIError {
35
36
  requiredPlan;
36
- constructor(message = "Acesso negado", requiredPlan, requestId) {
37
- super(message, 403, requestId);
37
+ constructor(message = "Plano n\xE3o autorizado para este recurso", requiredPlan, requestId, responseBody) {
38
+ super(message, 403, requestId, responseBody);
38
39
  this.name = "ForbiddenError";
39
40
  this.requiredPlan = requiredPlan;
40
41
  Object.setPrototypeOf(this, _ForbiddenError.prototype);
41
42
  }
42
- toJSON() {
43
- return {
44
- ...super.toJSON(),
45
- requiredPlan: this.requiredPlan
46
- };
47
- }
48
43
  };
49
44
  var NotFoundError = class _NotFoundError extends IPTUAPIError {
50
- resource;
51
- constructor(message = "Recurso nao encontrado", resource, requestId) {
52
- super(message, 404, requestId);
45
+ constructor(message = "Recurso n\xE3o encontrado", requestId, responseBody) {
46
+ super(message, 404, requestId, responseBody);
53
47
  this.name = "NotFoundError";
54
- this.resource = resource;
55
48
  Object.setPrototypeOf(this, _NotFoundError.prototype);
56
49
  }
57
- toJSON() {
58
- return {
59
- ...super.toJSON(),
60
- resource: this.resource
61
- };
62
- }
63
50
  };
64
51
  var RateLimitError = class _RateLimitError extends IPTUAPIError {
65
52
  retryAfter;
66
- constructor(message = "Rate limit excedido", retryAfter = 60, requestId) {
67
- super(message, 429, requestId);
53
+ limit;
54
+ remaining;
55
+ constructor(message = "Limite de requisi\xE7\xF5es excedido", retryAfter, limit, remaining, requestId, responseBody) {
56
+ super(message, 429, requestId, responseBody);
68
57
  this.name = "RateLimitError";
69
58
  this.retryAfter = retryAfter;
59
+ this.limit = limit;
60
+ this.remaining = remaining;
70
61
  Object.setPrototypeOf(this, _RateLimitError.prototype);
71
62
  }
72
- isRetryable() {
63
+ get isRetryable() {
73
64
  return true;
74
65
  }
75
- toJSON() {
76
- return {
77
- ...super.toJSON(),
78
- retryAfter: this.retryAfter
79
- };
80
- }
81
66
  };
82
67
  var ValidationError = class _ValidationError extends IPTUAPIError {
83
68
  errors;
84
- constructor(message = "Parametros invalidos", errors, statusCode = 422, requestId) {
85
- super(message, statusCode, requestId);
69
+ constructor(message = "Par\xE2metros inv\xE1lidos", errors, requestId, responseBody) {
70
+ super(message, 400, requestId, responseBody);
86
71
  this.name = "ValidationError";
87
- this.errors = errors || {};
72
+ this.errors = errors;
88
73
  Object.setPrototypeOf(this, _ValidationError.prototype);
89
74
  }
90
- toJSON() {
91
- return {
92
- ...super.toJSON(),
93
- validationErrors: this.errors
94
- };
95
- }
96
75
  };
97
76
  var ServerError = class _ServerError extends IPTUAPIError {
98
- constructor(message = "Erro interno do servidor", statusCode = 500, requestId) {
99
- super(message, statusCode, requestId);
77
+ constructor(message = "Erro interno do servidor", statusCode = 500, requestId, responseBody) {
78
+ super(message, statusCode, requestId, responseBody);
100
79
  this.name = "ServerError";
101
80
  Object.setPrototypeOf(this, _ServerError.prototype);
102
81
  }
103
- isRetryable() {
82
+ get isRetryable() {
104
83
  return true;
105
84
  }
106
85
  };
107
86
  var TimeoutError = class _TimeoutError extends IPTUAPIError {
108
- timeoutSeconds;
109
- constructor(message = "Timeout na requisicao", timeoutSeconds, requestId) {
110
- super(message, 408, requestId);
87
+ timeoutMs;
88
+ constructor(message = "Timeout na requisi\xE7\xE3o", timeoutMs) {
89
+ super(message, 408);
111
90
  this.name = "TimeoutError";
112
- this.timeoutSeconds = timeoutSeconds;
91
+ this.timeoutMs = timeoutMs;
113
92
  Object.setPrototypeOf(this, _TimeoutError.prototype);
114
93
  }
115
- isRetryable() {
94
+ get isRetryable() {
116
95
  return true;
117
96
  }
118
- toJSON() {
119
- return {
120
- ...super.toJSON(),
121
- timeoutSeconds: this.timeoutSeconds
122
- };
123
- }
124
97
  };
125
98
  var NetworkError = class _NetworkError extends IPTUAPIError {
126
99
  originalError;
127
- constructor(message = "Erro de conexao", originalError) {
128
- super(message, void 0, void 0);
100
+ constructor(message = "Erro de conex\xE3o com a API", originalError) {
101
+ super(message);
129
102
  this.name = "NetworkError";
130
103
  this.originalError = originalError;
131
104
  Object.setPrototypeOf(this, _NetworkError.prototype);
132
105
  }
133
- isRetryable() {
106
+ get isRetryable() {
134
107
  return true;
135
108
  }
136
109
  };
137
-
138
- // src/client.ts
139
110
  var DEFAULT_RETRY_CONFIG = {
140
111
  maxRetries: 3,
141
- initialDelay: 1e3,
142
- maxDelay: 3e4,
112
+ initialDelay: 500,
113
+ maxDelay: 1e4,
143
114
  backoffFactor: 2,
144
- retryableStatusCodes: [429, 500, 502, 503, 504]
115
+ retryableStatuses: [429, 500, 502, 503, 504]
145
116
  };
146
- var DEFAULT_CONFIG = {
147
- baseUrl: "https://iptuapi.com.br/api/v1",
148
- timeout: 3e4,
149
- retryConfig: DEFAULT_RETRY_CONFIG
150
- };
151
- function toCamelCase(obj) {
152
- const result = {};
153
- for (const [key, value] of Object.entries(obj)) {
154
- const camelKey = key.replace(
155
- /_([a-z])/g,
156
- (_, letter) => letter.toUpperCase()
157
- );
158
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
159
- result[camelKey] = toCamelCase(value);
160
- } else if (Array.isArray(value)) {
161
- result[camelKey] = value.map(
162
- (item) => typeof item === "object" && item !== null ? toCamelCase(item) : item
163
- );
164
- } else {
165
- result[camelKey] = value;
117
+ var IPTUClient = class {
118
+ apiKey;
119
+ baseUrl;
120
+ timeout;
121
+ retryConfig;
122
+ logger;
123
+ logRequests;
124
+ logResponses;
125
+ userAgent;
126
+ _rateLimit;
127
+ _lastRequestId;
128
+ constructor(apiKey, options = {}) {
129
+ if (!apiKey) {
130
+ throw new Error("API Key \xE9 obrigat\xF3ria");
166
131
  }
132
+ this.apiKey = apiKey;
133
+ this.baseUrl = options.baseUrl || "https://iptuapi.com.br/api/v1";
134
+ this.timeout = options.timeout || 3e4;
135
+ this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...options.retry };
136
+ this.logger = options.logger;
137
+ this.logRequests = options.logRequests || false;
138
+ this.logResponses = options.logResponses || false;
139
+ this.userAgent = options.userAgent || "iptuapi-js/2.1.0";
140
+ }
141
+ // ===========================================================================
142
+ // Properties
143
+ // ===========================================================================
144
+ /** Rate limit info from last request */
145
+ get rateLimit() {
146
+ return this._rateLimit;
147
+ }
148
+ /** Request ID from last request (useful for support) */
149
+ get lastRequestId() {
150
+ return this._lastRequestId;
167
151
  }
168
- return result;
169
- }
170
- function toSnakeCase(obj) {
171
- const result = {};
172
- for (const [key, value] of Object.entries(obj)) {
173
- const snakeKey = key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
174
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
175
- result[snakeKey] = toSnakeCase(value);
176
- } else if (Array.isArray(value)) {
177
- result[snakeKey] = value.map(
178
- (item) => typeof item === "object" && item !== null ? toSnakeCase(item) : item
179
- );
180
- } else {
181
- result[snakeKey] = value;
152
+ // ===========================================================================
153
+ // Private Methods
154
+ // ===========================================================================
155
+ log(level, message, ...args) {
156
+ if (this.logger && this.logger[level]) {
157
+ this.logger[level](message, ...args);
182
158
  }
183
159
  }
184
- return result;
185
- }
186
- var IPTUClient = class {
187
- apiKey;
188
- config;
189
- _rateLimitInfo = null;
190
- _lastRequestId = null;
191
- /**
192
- * Cria uma nova instancia do cliente.
193
- *
194
- * @param apiKey - Chave de API para autenticacao
195
- * @param options - Opcoes de configuracao
196
- */
197
- constructor(apiKey, options) {
198
- this.apiKey = apiKey;
199
- this.config = {
200
- baseUrl: options?.baseUrl || DEFAULT_CONFIG.baseUrl,
201
- timeout: options?.timeout || DEFAULT_CONFIG.timeout,
202
- retryConfig: {
203
- ...DEFAULT_RETRY_CONFIG,
204
- ...options?.retryConfig
205
- }
206
- };
160
+ sleep(ms) {
161
+ return new Promise((resolve) => setTimeout(resolve, ms));
207
162
  }
208
- /**
209
- * Retorna informacoes do rate limit da ultima requisicao.
210
- */
211
- get rateLimitInfo() {
212
- return this._rateLimitInfo;
163
+ combineSignals(signal1, signal2) {
164
+ const controller = new AbortController();
165
+ const abort = () => controller.abort();
166
+ if (signal1.aborted || signal2.aborted) {
167
+ controller.abort();
168
+ return controller.signal;
169
+ }
170
+ signal1.addEventListener("abort", abort, { once: true });
171
+ signal2.addEventListener("abort", abort, { once: true });
172
+ return controller.signal;
213
173
  }
214
- /**
215
- * Retorna o ID da ultima requisicao.
216
- */
217
- get lastRequestId() {
218
- return this._lastRequestId;
174
+ calculateDelay(attempt) {
175
+ const delay = this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffFactor, attempt);
176
+ return Math.min(delay, this.retryConfig.maxDelay);
219
177
  }
220
- /**
221
- * Executa uma requisicao HTTP com retry.
222
- */
223
- async makeRequest(method, endpoint, params, body) {
224
- const url = new URL(`${this.config.baseUrl}/${endpoint.replace(/^\//, "")}`);
178
+ extractRateLimit(headers) {
179
+ const limit = headers.get("X-RateLimit-Limit");
180
+ const remaining = headers.get("X-RateLimit-Remaining");
181
+ const reset = headers.get("X-RateLimit-Reset");
182
+ if (limit && remaining && reset) {
183
+ const resetTimestamp = parseInt(reset, 10);
184
+ return {
185
+ limit: parseInt(limit, 10),
186
+ remaining: parseInt(remaining, 10),
187
+ reset: resetTimestamp,
188
+ resetDate: new Date(resetTimestamp * 1e3)
189
+ };
190
+ }
191
+ return void 0;
192
+ }
193
+ async handleErrorResponse(response, requestId) {
194
+ let body = {};
195
+ try {
196
+ body = await response.json();
197
+ } catch {
198
+ body = { detail: response.statusText };
199
+ }
200
+ let message;
201
+ const detail = body.detail;
202
+ if (detail && typeof detail === "object") {
203
+ const detailObj = detail;
204
+ message = detailObj.error || detailObj.detail || detailObj.message || JSON.stringify(detail);
205
+ } else {
206
+ message = detail || `HTTP ${response.status}`;
207
+ }
208
+ switch (response.status) {
209
+ case 400:
210
+ case 422:
211
+ throw new ValidationError(
212
+ message,
213
+ body.errors,
214
+ requestId,
215
+ body
216
+ );
217
+ case 401:
218
+ throw new AuthenticationError(message, requestId, body);
219
+ case 403:
220
+ throw new ForbiddenError(
221
+ message,
222
+ body.required_plan,
223
+ requestId,
224
+ body
225
+ );
226
+ case 404:
227
+ throw new NotFoundError(message, requestId, body);
228
+ case 429:
229
+ const retryAfter = response.headers.get("Retry-After");
230
+ throw new RateLimitError(
231
+ message,
232
+ retryAfter ? parseInt(retryAfter, 10) : void 0,
233
+ this._rateLimit?.limit,
234
+ this._rateLimit?.remaining,
235
+ requestId,
236
+ body
237
+ );
238
+ case 500:
239
+ case 502:
240
+ case 503:
241
+ case 504:
242
+ throw new ServerError(message, response.status, requestId, body);
243
+ default:
244
+ throw new IPTUAPIError(message, response.status, requestId, body);
245
+ }
246
+ }
247
+ async request(method, endpoint, params, body, options) {
248
+ const url = new URL(`${this.baseUrl}${endpoint}`);
225
249
  if (params) {
226
- for (const [key, value] of Object.entries(params)) {
227
- if (value !== void 0 && value !== null) {
250
+ Object.entries(params).forEach(([key, value]) => {
251
+ if (value !== void 0 && value !== null && value !== "") {
228
252
  url.searchParams.append(key, String(value));
229
253
  }
230
- }
254
+ });
231
255
  }
232
- const { maxRetries, initialDelay, maxDelay, backoffFactor } = this.config.retryConfig;
233
- let delay = initialDelay;
234
- for (let attempt = 0; attempt <= maxRetries; attempt++) {
256
+ const headers = {
257
+ "X-API-Key": this.apiKey,
258
+ "Content-Type": "application/json",
259
+ Accept: "application/json",
260
+ "User-Agent": this.userAgent
261
+ };
262
+ const requestTimeout = options?.timeout ?? this.timeout;
263
+ const externalSignal = options?.signal;
264
+ let lastError;
265
+ let attempt = 0;
266
+ while (attempt <= this.retryConfig.maxRetries) {
267
+ if (externalSignal?.aborted) {
268
+ throw new IPTUAPIError("Request aborted", void 0, void 0, void 0);
269
+ }
235
270
  const controller = new AbortController();
236
- const timeoutId = setTimeout(
237
- () => controller.abort(),
238
- this.config.timeout
239
- );
271
+ const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
272
+ const combinedSignal = externalSignal ? this.combineSignals(externalSignal, controller.signal) : controller.signal;
240
273
  try {
274
+ if (this.logRequests) {
275
+ this.log(
276
+ "debug",
277
+ `Request: ${method} ${url}`,
278
+ params ? { params } : {},
279
+ body ? { body } : {}
280
+ );
281
+ }
282
+ const startTime = Date.now();
241
283
  const response = await fetch(url.toString(), {
242
284
  method,
243
- headers: {
244
- "X-API-Key": this.apiKey,
245
- "Content-Type": "application/json",
246
- Accept: "application/json",
247
- "User-Agent": "iptuapi-js/1.0.0"
248
- },
249
- body: body ? JSON.stringify(toSnakeCase(body)) : void 0,
250
- signal: controller.signal
285
+ headers,
286
+ body: body ? JSON.stringify(body) : void 0,
287
+ signal: combinedSignal
251
288
  });
252
289
  clearTimeout(timeoutId);
253
- this.updateRateLimitInfo(response.headers);
254
- this._lastRequestId = response.headers.get("X-Request-ID");
255
- if (!response.ok) {
256
- await this.handleError(response);
290
+ const elapsedMs = Date.now() - startTime;
291
+ this._rateLimit = this.extractRateLimit(response.headers);
292
+ this._lastRequestId = response.headers.get("X-Request-ID") || void 0;
293
+ if (this.logResponses) {
294
+ this.log(
295
+ "debug",
296
+ `Response: ${response.status} ${url} (${elapsedMs}ms)`
297
+ );
257
298
  }
258
- const data = await response.json();
259
- return toCamelCase(data.data || data);
299
+ if (response.ok) {
300
+ return await response.json();
301
+ }
302
+ if (this.retryConfig.retryableStatuses.includes(response.status) && attempt < this.retryConfig.maxRetries) {
303
+ const delay = this.calculateDelay(attempt);
304
+ this.log(
305
+ "warn",
306
+ `Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
307
+ );
308
+ await this.sleep(delay);
309
+ attempt++;
310
+ continue;
311
+ }
312
+ await this.handleErrorResponse(response, this._lastRequestId);
260
313
  } catch (error) {
261
314
  clearTimeout(timeoutId);
262
315
  if (error instanceof IPTUAPIError) {
263
- if (error.isRetryable() && attempt < maxRetries && this.config.retryConfig.retryableStatusCodes.includes(
264
- error.statusCode || 0
265
- )) {
266
- await this.sleep(delay);
267
- delay = Math.min(delay * backoffFactor, maxDelay);
268
- continue;
269
- }
270
316
  throw error;
271
317
  }
272
318
  if (error instanceof Error) {
273
319
  if (error.name === "AbortError") {
274
- if (attempt < maxRetries) {
275
- await this.sleep(delay);
276
- delay = Math.min(delay * backoffFactor, maxDelay);
277
- continue;
278
- }
279
- throw new TimeoutError(
280
- `Timeout apos ${this.config.timeout}ms`,
281
- this.config.timeout / 1e3
320
+ lastError = new TimeoutError(
321
+ `Timeout ap\xF3s ${this.timeout}ms`,
322
+ this.timeout
282
323
  );
324
+ } else if (error.message.includes("fetch") || error.message.includes("network")) {
325
+ lastError = new NetworkError(
326
+ `Erro de conex\xE3o: ${error.message}`,
327
+ error
328
+ );
329
+ } else {
330
+ lastError = error;
283
331
  }
284
- if (attempt < maxRetries) {
332
+ if (attempt < this.retryConfig.maxRetries) {
333
+ const delay = this.calculateDelay(attempt);
334
+ this.log(
335
+ "warn",
336
+ `Request failed: ${error.message}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
337
+ );
285
338
  await this.sleep(delay);
286
- delay = Math.min(delay * backoffFactor, maxDelay);
339
+ attempt++;
287
340
  continue;
288
341
  }
289
- throw new NetworkError(`Erro de conexao: ${error.message}`, error);
290
342
  }
291
- throw new NetworkError("Erro desconhecido");
343
+ throw lastError || error;
292
344
  }
293
345
  }
294
- throw new NetworkError("Maximo de tentativas excedido");
295
- }
296
- /**
297
- * Atualiza informacoes de rate limit a partir dos headers.
298
- */
299
- updateRateLimitInfo(headers) {
300
- const limit = headers.get("X-RateLimit-Limit");
301
- const remaining = headers.get("X-RateLimit-Remaining");
302
- const reset = headers.get("X-RateLimit-Reset");
303
- if (limit && remaining && reset) {
304
- this._rateLimitInfo = {
305
- limit: parseInt(limit, 10),
306
- remaining: parseInt(remaining, 10),
307
- resetAt: new Date(parseInt(reset, 10) * 1e3)
346
+ throw lastError || new IPTUAPIError("Max retries exceeded");
347
+ }
348
+ async consultaEndereco(paramsOrLogradouro, numeroOrOptions, cidade, options) {
349
+ let params;
350
+ let requestOptions;
351
+ if (typeof paramsOrLogradouro === "string") {
352
+ const numero = typeof numeroOrOptions === "string" ? numeroOrOptions : void 0;
353
+ requestOptions = typeof numeroOrOptions === "object" ? numeroOrOptions : options;
354
+ params = {
355
+ logradouro: paramsOrLogradouro,
356
+ numero,
357
+ cidade: cidade || "sp"
358
+ };
359
+ } else {
360
+ requestOptions = numeroOrOptions;
361
+ params = {
362
+ logradouro: paramsOrLogradouro.logradouro,
363
+ numero: paramsOrLogradouro.numero,
364
+ complemento: paramsOrLogradouro.complemento,
365
+ cidade: paramsOrLogradouro.cidade || "sp",
366
+ incluir_historico: paramsOrLogradouro.incluirHistorico,
367
+ incluir_comparaveis: paramsOrLogradouro.incluirComparaveis,
368
+ incluir_zoneamento: paramsOrLogradouro.incluirZoneamento
308
369
  };
309
370
  }
371
+ return this.request(
372
+ "GET",
373
+ "/consulta/endereco",
374
+ params,
375
+ void 0,
376
+ requestOptions
377
+ );
310
378
  }
311
379
  /**
312
- * Converte resposta HTTP em excecao apropriada.
313
- */
314
- async handleError(response) {
315
- const requestId = response.headers.get("X-Request-ID") || void 0;
316
- let data = {};
317
- let message = "Erro desconhecido";
318
- try {
319
- data = await response.json();
320
- message = data.detail || data.message || message;
321
- } catch {
322
- message = response.statusText || message;
323
- }
324
- switch (response.status) {
325
- case 401:
326
- throw new AuthenticationError(message, requestId);
327
- case 403:
328
- throw new ForbiddenError(
329
- message,
330
- data.required_plan,
331
- requestId
332
- );
333
- case 404:
334
- throw new NotFoundError(
335
- message,
336
- data.resource,
337
- requestId
338
- );
339
- case 429: {
340
- const retryAfter = parseInt(
341
- response.headers.get("Retry-After") || "60",
342
- 10
343
- );
344
- throw new RateLimitError(message, retryAfter, requestId);
345
- }
346
- case 400:
347
- case 422:
348
- throw new ValidationError(
349
- message,
350
- data.errors,
351
- response.status,
352
- requestId
353
- );
354
- default:
355
- if (response.status >= 500) {
356
- throw new ServerError(message, response.status, requestId);
357
- }
358
- throw new IPTUAPIError(message, response.status, requestId, data);
359
- }
360
- }
361
- /**
362
- * Aguarda um tempo em milissegundos.
380
+ * Busca dados de IPTU por número SQL (contribuinte).
381
+ *
382
+ * @param sql - Número SQL do imóvel
383
+ * @param cidade - Cidade da consulta
384
+ * @param options - Opções adicionais (incluirHistorico, incluirComparaveis)
385
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
386
+ * @returns Dados completos do imóvel
363
387
  */
364
- sleep(ms) {
365
- return new Promise((resolve) => setTimeout(resolve, ms));
388
+ async consultaSQL(sql, cidade = "sp", options, requestOptions) {
389
+ return this.request("GET", `/consulta/sql/${sql}`, {
390
+ cidade,
391
+ incluir_historico: options?.incluirHistorico,
392
+ incluir_comparaveis: options?.incluirComparaveis
393
+ }, void 0, requestOptions);
366
394
  }
367
- // ==================== CONSULTAS IPTU ====================
368
395
  /**
369
- * Consulta imoveis por endereco.
396
+ * Busca imóveis por CEP.
370
397
  *
371
- * @param logradouro - Nome da rua/avenida
372
- * @param numero - Numero do imovel
373
- * @param cidade - Codigo da cidade (sp, bh, recife)
374
- * @returns Lista de imoveis encontrados
398
+ * @param cep - CEP do imóvel
399
+ * @param cidade - Cidade da consulta
400
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
401
+ * @returns Lista de imóveis no CEP
375
402
  */
376
- async consultaEndereco(logradouro, numero, cidade = "sp") {
377
- const response = await this.makeRequest("GET", "/consulta/endereco", {
378
- logradouro,
379
- numero,
380
- cidade
381
- });
382
- return Array.isArray(response) ? response : [];
403
+ async consultaCEP(cep, cidade = "sp", requestOptions) {
404
+ const cleanCep = cep.replace(/\D/g, "");
405
+ return this.request(
406
+ "GET",
407
+ `/consulta/cep/${cleanCep}`,
408
+ { cidade },
409
+ void 0,
410
+ requestOptions
411
+ );
383
412
  }
384
413
  /**
385
- * Consulta imovel por numero SQL/Indice Cadastral.
386
- * Requer plano Starter ou superior.
414
+ * Consulta zoneamento por coordenadas.
387
415
  *
388
- * @param sql - Numero SQL (SP), Indice Cadastral (BH) ou Sequencial (Recife)
389
- * @param cidade - Codigo da cidade (sp, bh, recife)
390
- * @returns Lista de imoveis encontrados
416
+ * @param latitude - Latitude do ponto
417
+ * @param longitude - Longitude do ponto
418
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
419
+ * @returns Dados de zoneamento
391
420
  */
392
- async consultaSQL(sql, cidade = "sp") {
393
- const response = await this.makeRequest("GET", "/consulta/sql", {
394
- sql,
395
- cidade
396
- });
397
- return Array.isArray(response) ? response : [];
398
- }
421
+ async consultaZoneamento(latitude, longitude, requestOptions) {
422
+ return this.request("GET", "/consulta/zoneamento", {
423
+ latitude,
424
+ longitude
425
+ }, void 0, requestOptions);
426
+ }
427
+ // ===========================================================================
428
+ // Valuation Endpoints (Pro+)
429
+ // ===========================================================================
399
430
  /**
400
- * Consulta imoveis por CEP.
431
+ * Estima o valor de mercado do imóvel usando ML.
432
+ * Disponível apenas para planos Pro e Enterprise.
401
433
  *
402
- * @param cep - CEP do endereco
403
- * @param cidade - Codigo da cidade (sp, bh, recife)
404
- * @returns Lista de imoveis encontrados
434
+ * @param params - Parâmetros do imóvel
435
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
436
+ * @returns Estimativa de valor
437
+ * @throws {ForbiddenError} Se o plano não permitir
405
438
  */
406
- async consultaCEP(cep, cidade = "sp") {
407
- const response = await this.makeRequest("GET", "/consulta/cep", {
408
- cep,
409
- cidade
410
- });
411
- return Array.isArray(response) ? response : [];
439
+ async valuationEstimate(params, requestOptions) {
440
+ return this.request(
441
+ "POST",
442
+ "/valuation/estimate",
443
+ void 0,
444
+ {
445
+ area_terreno: params.area_terreno,
446
+ area_construida: params.area_construida,
447
+ bairro: params.bairro,
448
+ zona: params.zona,
449
+ tipo_uso: params.tipo_uso,
450
+ tipo_padrao: params.tipo_padrao,
451
+ ano_construcao: params.ano_construcao,
452
+ cidade: params.cidade || "sp"
453
+ },
454
+ requestOptions
455
+ );
412
456
  }
413
457
  /**
414
- * Consulta zoneamento por coordenadas.
458
+ * Valuation em lote (até 100 imóveis).
459
+ * Disponível apenas para plano Enterprise.
415
460
  *
416
- * @param latitude - Latitude do ponto
417
- * @param longitude - Longitude do ponto
418
- * @returns Informacoes de zoneamento
461
+ * @param imoveis - Lista de imóveis para avaliar
462
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
463
+ * @returns Resultados de valuation para cada imóvel
419
464
  */
420
- async consultaZoneamento(latitude, longitude) {
421
- return this.makeRequest("GET", "/consulta/zoneamento", {
422
- lat: latitude,
423
- lng: longitude
424
- });
465
+ async valuationBatch(imoveis, requestOptions) {
466
+ return this.request(
467
+ "POST",
468
+ "/valuation/estimate/batch",
469
+ void 0,
470
+ { imoveis },
471
+ requestOptions
472
+ );
425
473
  }
426
- // ==================== VALUATION ====================
427
474
  /**
428
- * Calcula estimativa de valor de mercado.
429
- * Requer plano Pro ou superior.
475
+ * Busca imóveis comparáveis para análise.
430
476
  *
431
- * @param params - Parametros da avaliacao
432
- * @returns Avaliacao de mercado
477
+ * @param bairro - Nome do bairro
478
+ * @param areaMin - Área mínima em m²
479
+ * @param areaMax - Área máxima em m²
480
+ * @param options - Opções adicionais
481
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
482
+ * @returns Lista de imóveis comparáveis
433
483
  */
434
- async valuationEstimate(params) {
435
- return this.makeRequest("GET", "/valuation/estimate", {
436
- area_terreno: params.areaTerreno,
437
- area_construida: params.areaConstruida,
438
- bairro: params.bairro,
439
- cidade: params.cidade || "sp",
440
- zona: params.zona,
441
- tipo_uso: params.tipoUso,
442
- tipo_padrao: params.tipoPadrao,
443
- ano_construcao: params.anoConstrucao
444
- });
484
+ async valuationComparables(bairro, areaMin, areaMax, options, requestOptions) {
485
+ return this.request("GET", "/valuation/comparables", {
486
+ bairro,
487
+ area_min: areaMin,
488
+ area_max: areaMax,
489
+ tipo_uso: options?.tipoUso,
490
+ cidade: options?.cidade || "sp",
491
+ limit: options?.limit || 10
492
+ }, void 0, requestOptions);
445
493
  }
446
494
  /**
447
- * Busca imoveis comparaveis.
448
- * Requer plano Pro ou superior.
495
+ * Estatísticas de valores por bairro.
449
496
  *
450
- * @param params - Parametros da busca
451
- * @returns Lista de imoveis comparaveis
497
+ * @param bairro - Nome do bairro
498
+ * @param cidade - Cidade da consulta
499
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
500
+ * @returns Estatísticas: média, mediana, min, max, etc
452
501
  */
453
- async valuationComparables(params) {
454
- const response = await this.makeRequest(
502
+ async valuationStatistics(bairro, cidade = "sp", requestOptions) {
503
+ return this.request(
455
504
  "GET",
456
- "/valuation/comparables",
457
- {
458
- bairro: params.bairro,
459
- area_min: params.areaMin,
460
- area_max: params.areaMax,
461
- cidade: params.cidade || "sp",
462
- limit: params.limit || 10
463
- }
505
+ `/valuation/statistics/${encodeURIComponent(bairro)}`,
506
+ { cidade },
507
+ void 0,
508
+ requestOptions
464
509
  );
465
- return Array.isArray(response) ? response : [];
466
510
  }
511
+ // ===========================================================================
512
+ // Dados Endpoints
513
+ // ===========================================================================
467
514
  /**
468
- * Avalia imovel por endereco OU SQL.
469
- * Combina dados do modelo AVM (ML) com transacoes ITBI reais.
470
- * Requer plano Pro ou superior.
515
+ * Histórico de valores IPTU de um imóvel.
471
516
  *
472
- * @param params - Parametros da avaliacao (sql OU logradouro+numero)
473
- * @returns Avaliacao completa do imovel
517
+ * @param sql - Número SQL do imóvel
518
+ * @param cidade - Cidade da consulta
519
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
520
+ * @returns Lista com histórico anual
474
521
  */
475
- async valuationEvaluate(params) {
476
- const body = {
477
- cidade: params.cidade || "sp",
478
- incluirItbi: params.incluirItbi ?? true,
479
- incluirComparaveis: params.incluirComparaveis ?? true
480
- };
481
- if (params.sql) {
482
- body.sql = params.sql;
483
- } else {
484
- if (params.logradouro) body.logradouro = params.logradouro;
485
- if (params.numero !== void 0) body.numero = params.numero;
486
- if (params.complemento) body.complemento = params.complemento;
487
- if (params.bairro) body.bairro = params.bairro;
488
- }
489
- return this.makeRequest(
490
- "POST",
491
- "/valuation/evaluate",
522
+ async dadosIPTUHistorico(sql, cidade = "sp", requestOptions) {
523
+ return this.request(
524
+ "GET",
525
+ `/dados/iptu/historico/${sql}`,
526
+ { cidade },
492
527
  void 0,
493
- body
528
+ requestOptions
494
529
  );
495
530
  }
496
- // ==================== ITBI ====================
497
531
  /**
498
- * Consulta status de transacao ITBI.
532
+ * Consulta dados de empresa por CNPJ.
499
533
  *
500
- * @param protocolo - Numero do protocolo ITBI
501
- * @param cidade - Codigo da cidade (sp, bh, recife)
502
- * @returns Status da transacao
534
+ * @param cnpj - CNPJ da empresa
535
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
536
+ * @returns Dados cadastrais
503
537
  */
504
- async itbiStatus(protocolo, cidade = "sp") {
505
- return this.makeRequest("GET", "/itbi/status", {
506
- protocolo,
507
- cidade
508
- });
538
+ async dadosCNPJ(cnpj, requestOptions) {
539
+ const cleanCnpj = cnpj.replace(/\D/g, "");
540
+ return this.request(
541
+ "GET",
542
+ `/dados/cnpj/${cleanCnpj}`,
543
+ void 0,
544
+ void 0,
545
+ requestOptions
546
+ );
509
547
  }
510
548
  /**
511
- * Calcula valor do ITBI.
549
+ * Índice IPCA histórico.
512
550
  *
513
- * @param params - Parametros do calculo
514
- * @returns Calculo do ITBI
551
+ * @param dataInicio - Data inicial (YYYY-MM)
552
+ * @param dataFim - Data final (YYYY-MM)
553
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
554
+ * @returns Série histórica do IPCA
515
555
  */
516
- async itbiCalcular(params) {
517
- return this.makeRequest("POST", "/itbi/calcular", void 0, {
518
- sql: params.sql,
519
- valorTransacao: params.valorTransacao,
520
- cidade: params.cidade || "sp"
521
- });
556
+ async dadosIPCA(dataInicio, dataFim, requestOptions) {
557
+ return this.request(
558
+ "GET",
559
+ "/dados/ipca",
560
+ {
561
+ data_inicio: dataInicio,
562
+ data_fim: dataFim
563
+ },
564
+ void 0,
565
+ requestOptions
566
+ );
522
567
  }
523
568
  /**
524
- * Consulta historico de transacoes ITBI de um imovel.
525
- * Requer plano Starter ou superior.
569
+ * Correção monetária pelo IPCA.
526
570
  *
527
- * @param sql - Numero SQL do imovel
528
- * @param cidade - Codigo da cidade (sp, bh, recife)
529
- * @returns Lista de transacoes historicas
571
+ * @param valor - Valor a corrigir
572
+ * @param dataOrigem - Data do valor original (YYYY-MM)
573
+ * @param dataDestino - Data destino (default: atual)
574
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
575
+ * @returns Valor corrigido e fator de correção
530
576
  */
531
- async itbiHistorico(sql, cidade = "sp") {
532
- const response = await this.makeRequest(
577
+ async dadosIPCACorrigir(valor, dataOrigem, dataDestino, requestOptions) {
578
+ return this.request(
533
579
  "GET",
534
- "/itbi/historico",
535
- { sql, cidade }
580
+ "/dados/ipca/corrigir",
581
+ {
582
+ valor,
583
+ data_origem: dataOrigem,
584
+ data_destino: dataDestino
585
+ },
586
+ void 0,
587
+ requestOptions
536
588
  );
537
- return Array.isArray(response) ? response : [];
538
589
  }
590
+ // ===========================================================================
591
+ // IPTU Tools Endpoints (Ferramentas IPTU 2026)
592
+ // ===========================================================================
539
593
  /**
540
- * Consulta aliquotas ITBI vigentes.
594
+ * Lista todas as cidades com calendario de IPTU disponivel.
541
595
  *
542
- * @param cidade - Codigo da cidade (sp, bh, recife)
543
- * @returns Aliquotas vigentes
596
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
597
+ * @returns Lista de cidades com codigo, nome, desconto e parcelas
544
598
  */
545
- async itbiAliquotas(cidade = "sp") {
546
- return this.makeRequest("GET", "/itbi/aliquotas", { cidade });
599
+ async iptuToolsCidades(requestOptions) {
600
+ return this.request("GET", "/iptu-tools/cidades", void 0, void 0, requestOptions);
547
601
  }
548
602
  /**
549
- * Consulta isencoes ITBI disponiveis.
603
+ * Retorna o calendario completo de IPTU para a cidade especificada.
550
604
  *
551
- * @param cidade - Codigo da cidade (sp, bh, recife)
552
- * @returns Lista de isencoes disponiveis
605
+ * @param cidade - Codigo da cidade (sp, bh, rj, recife, curitiba, poa, fortaleza)
606
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
607
+ * @returns Calendario com vencimentos, descontos, alertas e novidades
553
608
  */
554
- async itbiIsencoes(cidade = "sp") {
555
- const response = await this.makeRequest(
556
- "GET",
557
- "/itbi/isencoes",
558
- { cidade }
559
- );
560
- return Array.isArray(response) ? response : [];
609
+ async iptuToolsCalendario(cidade = "sp", requestOptions) {
610
+ return this.request("GET", "/iptu-tools/calendario", { cidade }, void 0, requestOptions);
561
611
  }
562
612
  /**
563
- * Gera guia de pagamento ITBI.
564
- * Requer plano Starter ou superior.
613
+ * Simula as opcoes de pagamento do IPTU (a vista vs parcelado).
565
614
  *
566
- * @param params - Parametros da guia
567
- * @returns Guia de pagamento gerada
615
+ * @param valorIptu - Valor total do IPTU
616
+ * @param cidade - Codigo da cidade
617
+ * @param valorVenal - Valor venal do imovel (para verificar isencao)
618
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
619
+ * @returns Comparativo entre pagamento a vista e parcelado com recomendacao
568
620
  */
569
- async itbiGuia(params) {
570
- return this.makeRequest("POST", "/itbi/guia", void 0, {
571
- sql: params.sql,
572
- valorTransacao: params.valorTransacao,
573
- comprador: params.comprador,
574
- vendedor: params.vendedor,
575
- cidade: params.cidade || "sp"
576
- });
621
+ async iptuToolsSimulador(valorIptu, cidade = "sp", valorVenal, requestOptions) {
622
+ const body = {
623
+ valor_iptu: valorIptu,
624
+ cidade
625
+ };
626
+ if (valorVenal !== void 0) {
627
+ body.valor_venal = valorVenal;
628
+ }
629
+ return this.request("POST", "/iptu-tools/simulador", void 0, body, requestOptions);
577
630
  }
578
631
  /**
579
- * Valida autenticidade de uma guia ITBI.
632
+ * Verifica se um imovel e elegivel para isencao de IPTU.
580
633
  *
581
- * @param protocolo - Numero do protocolo da guia
582
- * @param cidade - Codigo da cidade (sp, bh, recife)
583
- * @returns Resultado da validacao
634
+ * @param valorVenal - Valor venal do imovel
635
+ * @param cidade - Codigo da cidade
636
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
637
+ * @returns Elegibilidade para isencao total ou parcial
584
638
  */
585
- async itbiValidarGuia(protocolo, cidade = "sp") {
586
- return this.makeRequest("GET", "/itbi/validar", {
587
- protocolo,
639
+ async iptuToolsIsencao(valorVenal, cidade = "sp", requestOptions) {
640
+ return this.request("GET", "/iptu-tools/isencao", {
641
+ valor_venal: valorVenal,
588
642
  cidade
589
- });
643
+ }, void 0, requestOptions);
590
644
  }
591
645
  /**
592
- * Simula calculo de ITBI.
646
+ * Retorna informacoes sobre o proximo vencimento do IPTU.
593
647
  *
594
- * @param params - Parametros da simulacao
595
- * @returns Resultado da simulacao
648
+ * @param cidade - Codigo da cidade
649
+ * @param parcela - Numero da parcela (1-12)
650
+ * @param requestOptions - Opções de request (signal para cancelamento, timeout)
651
+ * @returns Data de vencimento, dias restantes e status
596
652
  */
597
- async itbiSimular(params) {
598
- return this.makeRequest("POST", "/itbi/simular", void 0, {
599
- valorTransacao: params.valorTransacao,
600
- cidade: params.cidade || "sp",
601
- tipoFinanciamento: params.tipoFinanciamento,
602
- valorFinanciado: params.valorFinanciado
603
- });
653
+ async iptuToolsProximoVencimento(cidade = "sp", parcela = 1, requestOptions) {
654
+ return this.request("GET", "/iptu-tools/proximo-vencimento", {
655
+ cidade,
656
+ parcela
657
+ }, void 0, requestOptions);
604
658
  }
605
659
  };
660
+ var index_default = IPTUClient;
606
661
  export {
607
662
  AuthenticationError,
663
+ CidadeEnum,
608
664
  ForbiddenError,
609
665
  IPTUAPIError,
610
666
  IPTUClient,
@@ -613,5 +669,6 @@ export {
613
669
  RateLimitError,
614
670
  ServerError,
615
671
  TimeoutError,
616
- ValidationError
672
+ ValidationError,
673
+ index_default as default
617
674
  };