iptuapi 1.2.0 → 2.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 +230 -44
- package/dist/index.d.mts +276 -78
- package/dist/index.d.ts +276 -78
- package/dist/index.js +450 -98
- package/dist/index.mjs +444 -97
- package/package.json +25 -3
package/dist/index.js
CHANGED
|
@@ -21,166 +21,513 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AuthenticationError: () => AuthenticationError,
|
|
24
|
+
CidadeEnum: () => CidadeEnum,
|
|
24
25
|
ForbiddenError: () => ForbiddenError,
|
|
25
26
|
IPTUAPIError: () => IPTUAPIError,
|
|
26
27
|
IPTUClient: () => IPTUClient,
|
|
28
|
+
NetworkError: () => NetworkError,
|
|
27
29
|
NotFoundError: () => NotFoundError,
|
|
28
30
|
RateLimitError: () => RateLimitError,
|
|
31
|
+
ServerError: () => ServerError,
|
|
32
|
+
TimeoutError: () => TimeoutError,
|
|
33
|
+
ValidationError: () => ValidationError,
|
|
29
34
|
default: () => index_default
|
|
30
35
|
});
|
|
31
36
|
module.exports = __toCommonJS(index_exports);
|
|
32
|
-
var
|
|
33
|
-
|
|
37
|
+
var CidadeEnum = {
|
|
38
|
+
SAO_PAULO: "sp",
|
|
39
|
+
BELO_HORIZONTE: "bh",
|
|
40
|
+
RECIFE: "recife"
|
|
41
|
+
};
|
|
42
|
+
var IPTUAPIError = class _IPTUAPIError extends Error {
|
|
43
|
+
statusCode;
|
|
44
|
+
requestId;
|
|
45
|
+
responseBody;
|
|
46
|
+
constructor(message, statusCode, requestId, responseBody) {
|
|
34
47
|
super(message);
|
|
35
|
-
this.statusCode = statusCode;
|
|
36
48
|
this.name = "IPTUAPIError";
|
|
49
|
+
this.statusCode = statusCode;
|
|
50
|
+
this.requestId = requestId;
|
|
51
|
+
this.responseBody = responseBody;
|
|
52
|
+
Object.setPrototypeOf(this, _IPTUAPIError.prototype);
|
|
53
|
+
}
|
|
54
|
+
get isRetryable() {
|
|
55
|
+
return this.statusCode ? [429, 500, 502, 503, 504].includes(this.statusCode) : false;
|
|
37
56
|
}
|
|
38
57
|
};
|
|
39
|
-
var AuthenticationError = class extends IPTUAPIError {
|
|
40
|
-
constructor(message = "API Key inv\xE1lida ou expirada") {
|
|
41
|
-
super(message, 401);
|
|
58
|
+
var AuthenticationError = class _AuthenticationError extends IPTUAPIError {
|
|
59
|
+
constructor(message = "API Key inv\xE1lida ou expirada", requestId, responseBody) {
|
|
60
|
+
super(message, 401, requestId, responseBody);
|
|
42
61
|
this.name = "AuthenticationError";
|
|
62
|
+
Object.setPrototypeOf(this, _AuthenticationError.prototype);
|
|
43
63
|
}
|
|
44
64
|
};
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
65
|
+
var ForbiddenError = class _ForbiddenError extends IPTUAPIError {
|
|
66
|
+
requiredPlan;
|
|
67
|
+
constructor(message = "Plano n\xE3o autorizado para este recurso", requiredPlan, requestId, responseBody) {
|
|
68
|
+
super(message, 403, requestId, responseBody);
|
|
69
|
+
this.name = "ForbiddenError";
|
|
70
|
+
this.requiredPlan = requiredPlan;
|
|
71
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
|
49
72
|
}
|
|
50
73
|
};
|
|
51
|
-
var NotFoundError = class extends IPTUAPIError {
|
|
52
|
-
constructor(message = "Recurso n\xE3o encontrado") {
|
|
53
|
-
super(message, 404);
|
|
74
|
+
var NotFoundError = class _NotFoundError extends IPTUAPIError {
|
|
75
|
+
constructor(message = "Recurso n\xE3o encontrado", requestId, responseBody) {
|
|
76
|
+
super(message, 404, requestId, responseBody);
|
|
54
77
|
this.name = "NotFoundError";
|
|
78
|
+
Object.setPrototypeOf(this, _NotFoundError.prototype);
|
|
55
79
|
}
|
|
56
80
|
};
|
|
57
|
-
var
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
81
|
+
var RateLimitError = class _RateLimitError extends IPTUAPIError {
|
|
82
|
+
retryAfter;
|
|
83
|
+
limit;
|
|
84
|
+
remaining;
|
|
85
|
+
constructor(message = "Limite de requisi\xE7\xF5es excedido", retryAfter, limit, remaining, requestId, responseBody) {
|
|
86
|
+
super(message, 429, requestId, responseBody);
|
|
87
|
+
this.name = "RateLimitError";
|
|
88
|
+
this.retryAfter = retryAfter;
|
|
89
|
+
this.limit = limit;
|
|
90
|
+
this.remaining = remaining;
|
|
91
|
+
Object.setPrototypeOf(this, _RateLimitError.prototype);
|
|
92
|
+
}
|
|
93
|
+
get isRetryable() {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
var ValidationError = class _ValidationError extends IPTUAPIError {
|
|
98
|
+
errors;
|
|
99
|
+
constructor(message = "Par\xE2metros inv\xE1lidos", errors, requestId, responseBody) {
|
|
100
|
+
super(message, 400, requestId, responseBody);
|
|
101
|
+
this.name = "ValidationError";
|
|
102
|
+
this.errors = errors;
|
|
103
|
+
Object.setPrototypeOf(this, _ValidationError.prototype);
|
|
61
104
|
}
|
|
62
105
|
};
|
|
106
|
+
var ServerError = class _ServerError extends IPTUAPIError {
|
|
107
|
+
constructor(message = "Erro interno do servidor", statusCode = 500, requestId, responseBody) {
|
|
108
|
+
super(message, statusCode, requestId, responseBody);
|
|
109
|
+
this.name = "ServerError";
|
|
110
|
+
Object.setPrototypeOf(this, _ServerError.prototype);
|
|
111
|
+
}
|
|
112
|
+
get isRetryable() {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
var TimeoutError = class _TimeoutError extends IPTUAPIError {
|
|
117
|
+
timeoutMs;
|
|
118
|
+
constructor(message = "Timeout na requisi\xE7\xE3o", timeoutMs) {
|
|
119
|
+
super(message, 408);
|
|
120
|
+
this.name = "TimeoutError";
|
|
121
|
+
this.timeoutMs = timeoutMs;
|
|
122
|
+
Object.setPrototypeOf(this, _TimeoutError.prototype);
|
|
123
|
+
}
|
|
124
|
+
get isRetryable() {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
var NetworkError = class _NetworkError extends IPTUAPIError {
|
|
129
|
+
originalError;
|
|
130
|
+
constructor(message = "Erro de conex\xE3o com a API", originalError) {
|
|
131
|
+
super(message);
|
|
132
|
+
this.name = "NetworkError";
|
|
133
|
+
this.originalError = originalError;
|
|
134
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
135
|
+
}
|
|
136
|
+
get isRetryable() {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
141
|
+
maxRetries: 3,
|
|
142
|
+
initialDelay: 500,
|
|
143
|
+
maxDelay: 1e4,
|
|
144
|
+
backoffFactor: 2,
|
|
145
|
+
retryableStatuses: [429, 500, 502, 503, 504]
|
|
146
|
+
};
|
|
63
147
|
var IPTUClient = class {
|
|
64
148
|
apiKey;
|
|
65
149
|
baseUrl;
|
|
66
150
|
timeout;
|
|
151
|
+
retryConfig;
|
|
152
|
+
logger;
|
|
153
|
+
logRequests;
|
|
154
|
+
logResponses;
|
|
155
|
+
userAgent;
|
|
156
|
+
_rateLimit;
|
|
157
|
+
_lastRequestId;
|
|
67
158
|
constructor(apiKey, options = {}) {
|
|
159
|
+
if (!apiKey) {
|
|
160
|
+
throw new Error("API Key \xE9 obrigat\xF3ria");
|
|
161
|
+
}
|
|
68
162
|
this.apiKey = apiKey;
|
|
69
163
|
this.baseUrl = options.baseUrl || "https://iptuapi.com.br/api/v1";
|
|
70
164
|
this.timeout = options.timeout || 3e4;
|
|
165
|
+
this.retryConfig = { ...DEFAULT_RETRY_CONFIG, ...options.retry };
|
|
166
|
+
this.logger = options.logger;
|
|
167
|
+
this.logRequests = options.logRequests || false;
|
|
168
|
+
this.logResponses = options.logResponses || false;
|
|
169
|
+
this.userAgent = options.userAgent || "iptuapi-js/2.0.0";
|
|
170
|
+
}
|
|
171
|
+
// ===========================================================================
|
|
172
|
+
// Properties
|
|
173
|
+
// ===========================================================================
|
|
174
|
+
/** Rate limit info from last request */
|
|
175
|
+
get rateLimit() {
|
|
176
|
+
return this._rateLimit;
|
|
177
|
+
}
|
|
178
|
+
/** Request ID from last request (useful for support) */
|
|
179
|
+
get lastRequestId() {
|
|
180
|
+
return this._lastRequestId;
|
|
181
|
+
}
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
// Private Methods
|
|
184
|
+
// ===========================================================================
|
|
185
|
+
log(level, message, ...args) {
|
|
186
|
+
if (this.logger && this.logger[level]) {
|
|
187
|
+
this.logger[level](message, ...args);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
sleep(ms) {
|
|
191
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
192
|
+
}
|
|
193
|
+
calculateDelay(attempt) {
|
|
194
|
+
const delay = this.retryConfig.initialDelay * Math.pow(this.retryConfig.backoffFactor, attempt);
|
|
195
|
+
return Math.min(delay, this.retryConfig.maxDelay);
|
|
196
|
+
}
|
|
197
|
+
extractRateLimit(headers) {
|
|
198
|
+
const limit = headers.get("X-RateLimit-Limit");
|
|
199
|
+
const remaining = headers.get("X-RateLimit-Remaining");
|
|
200
|
+
const reset = headers.get("X-RateLimit-Reset");
|
|
201
|
+
if (limit && remaining && reset) {
|
|
202
|
+
const resetTimestamp = parseInt(reset, 10);
|
|
203
|
+
return {
|
|
204
|
+
limit: parseInt(limit, 10),
|
|
205
|
+
remaining: parseInt(remaining, 10),
|
|
206
|
+
reset: resetTimestamp,
|
|
207
|
+
resetDate: new Date(resetTimestamp * 1e3)
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return void 0;
|
|
211
|
+
}
|
|
212
|
+
async handleErrorResponse(response, requestId) {
|
|
213
|
+
let body = {};
|
|
214
|
+
try {
|
|
215
|
+
body = await response.json();
|
|
216
|
+
} catch {
|
|
217
|
+
body = { detail: response.statusText };
|
|
218
|
+
}
|
|
219
|
+
const message = body.detail || `HTTP ${response.status}`;
|
|
220
|
+
switch (response.status) {
|
|
221
|
+
case 400:
|
|
222
|
+
case 422:
|
|
223
|
+
throw new ValidationError(
|
|
224
|
+
message,
|
|
225
|
+
body.errors,
|
|
226
|
+
requestId,
|
|
227
|
+
body
|
|
228
|
+
);
|
|
229
|
+
case 401:
|
|
230
|
+
throw new AuthenticationError(message, requestId, body);
|
|
231
|
+
case 403:
|
|
232
|
+
throw new ForbiddenError(
|
|
233
|
+
message,
|
|
234
|
+
body.required_plan,
|
|
235
|
+
requestId,
|
|
236
|
+
body
|
|
237
|
+
);
|
|
238
|
+
case 404:
|
|
239
|
+
throw new NotFoundError(message, requestId, body);
|
|
240
|
+
case 429:
|
|
241
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
242
|
+
throw new RateLimitError(
|
|
243
|
+
message,
|
|
244
|
+
retryAfter ? parseInt(retryAfter, 10) : void 0,
|
|
245
|
+
this._rateLimit?.limit,
|
|
246
|
+
this._rateLimit?.remaining,
|
|
247
|
+
requestId,
|
|
248
|
+
body
|
|
249
|
+
);
|
|
250
|
+
case 500:
|
|
251
|
+
case 502:
|
|
252
|
+
case 503:
|
|
253
|
+
case 504:
|
|
254
|
+
throw new ServerError(message, response.status, requestId, body);
|
|
255
|
+
default:
|
|
256
|
+
throw new IPTUAPIError(message, response.status, requestId, body);
|
|
257
|
+
}
|
|
71
258
|
}
|
|
72
259
|
async request(method, endpoint, params, body) {
|
|
73
260
|
const url = new URL(`${this.baseUrl}${endpoint}`);
|
|
74
261
|
if (params) {
|
|
75
262
|
Object.entries(params).forEach(([key, value]) => {
|
|
76
|
-
if (value
|
|
263
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
264
|
+
url.searchParams.append(key, String(value));
|
|
265
|
+
}
|
|
77
266
|
});
|
|
78
267
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
throw new AuthenticationError();
|
|
98
|
-
case 403:
|
|
99
|
-
throw new ForbiddenError();
|
|
100
|
-
case 404:
|
|
101
|
-
throw new NotFoundError();
|
|
102
|
-
case 429:
|
|
103
|
-
throw new RateLimitError();
|
|
104
|
-
default:
|
|
105
|
-
const errorData = await response.json().catch(() => ({}));
|
|
106
|
-
throw new IPTUAPIError(
|
|
107
|
-
errorData.detail || `Erro na API: ${response.statusText}`,
|
|
108
|
-
response.status
|
|
268
|
+
const headers = {
|
|
269
|
+
"X-API-Key": this.apiKey,
|
|
270
|
+
"Content-Type": "application/json",
|
|
271
|
+
Accept: "application/json",
|
|
272
|
+
"User-Agent": this.userAgent
|
|
273
|
+
};
|
|
274
|
+
let lastError;
|
|
275
|
+
let attempt = 0;
|
|
276
|
+
while (attempt <= this.retryConfig.maxRetries) {
|
|
277
|
+
const controller = new AbortController();
|
|
278
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
279
|
+
try {
|
|
280
|
+
if (this.logRequests) {
|
|
281
|
+
this.log(
|
|
282
|
+
"debug",
|
|
283
|
+
`Request: ${method} ${url}`,
|
|
284
|
+
params ? { params } : {},
|
|
285
|
+
body ? { body } : {}
|
|
109
286
|
);
|
|
287
|
+
}
|
|
288
|
+
const startTime = Date.now();
|
|
289
|
+
const response = await fetch(url.toString(), {
|
|
290
|
+
method,
|
|
291
|
+
headers,
|
|
292
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
293
|
+
signal: controller.signal
|
|
294
|
+
});
|
|
295
|
+
clearTimeout(timeoutId);
|
|
296
|
+
const elapsedMs = Date.now() - startTime;
|
|
297
|
+
this._rateLimit = this.extractRateLimit(response.headers);
|
|
298
|
+
this._lastRequestId = response.headers.get("X-Request-ID") || void 0;
|
|
299
|
+
if (this.logResponses) {
|
|
300
|
+
this.log(
|
|
301
|
+
"debug",
|
|
302
|
+
`Response: ${response.status} ${url} (${elapsedMs}ms)`
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
if (response.ok) {
|
|
306
|
+
return await response.json();
|
|
307
|
+
}
|
|
308
|
+
if (this.retryConfig.retryableStatuses.includes(response.status) && attempt < this.retryConfig.maxRetries) {
|
|
309
|
+
const delay = this.calculateDelay(attempt);
|
|
310
|
+
this.log(
|
|
311
|
+
"warn",
|
|
312
|
+
`Request failed with ${response.status}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
|
|
313
|
+
);
|
|
314
|
+
await this.sleep(delay);
|
|
315
|
+
attempt++;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
await this.handleErrorResponse(response, this._lastRequestId);
|
|
319
|
+
} catch (error) {
|
|
320
|
+
clearTimeout(timeoutId);
|
|
321
|
+
if (error instanceof IPTUAPIError) {
|
|
322
|
+
throw error;
|
|
323
|
+
}
|
|
324
|
+
if (error instanceof Error) {
|
|
325
|
+
if (error.name === "AbortError") {
|
|
326
|
+
lastError = new TimeoutError(
|
|
327
|
+
`Timeout ap\xF3s ${this.timeout}ms`,
|
|
328
|
+
this.timeout
|
|
329
|
+
);
|
|
330
|
+
} else if (error.message.includes("fetch") || error.message.includes("network")) {
|
|
331
|
+
lastError = new NetworkError(
|
|
332
|
+
`Erro de conex\xE3o: ${error.message}`,
|
|
333
|
+
error
|
|
334
|
+
);
|
|
335
|
+
} else {
|
|
336
|
+
lastError = error;
|
|
337
|
+
}
|
|
338
|
+
if (attempt < this.retryConfig.maxRetries) {
|
|
339
|
+
const delay = this.calculateDelay(attempt);
|
|
340
|
+
this.log(
|
|
341
|
+
"warn",
|
|
342
|
+
`Request failed: ${error.message}, retrying in ${delay}ms (attempt ${attempt + 1}/${this.retryConfig.maxRetries})`
|
|
343
|
+
);
|
|
344
|
+
await this.sleep(delay);
|
|
345
|
+
attempt++;
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
throw lastError || error;
|
|
110
350
|
}
|
|
111
|
-
} catch (error) {
|
|
112
|
-
clearTimeout(timeoutId);
|
|
113
|
-
if (error instanceof IPTUAPIError) throw error;
|
|
114
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
115
|
-
throw new IPTUAPIError("Timeout na requisi\xE7\xE3o", 408);
|
|
116
|
-
}
|
|
117
|
-
throw error;
|
|
118
351
|
}
|
|
352
|
+
throw lastError || new IPTUAPIError("Max retries exceeded");
|
|
353
|
+
}
|
|
354
|
+
async consultaEndereco(paramsOrLogradouro, numero, cidade) {
|
|
355
|
+
let params;
|
|
356
|
+
if (typeof paramsOrLogradouro === "string") {
|
|
357
|
+
params = {
|
|
358
|
+
logradouro: paramsOrLogradouro,
|
|
359
|
+
numero,
|
|
360
|
+
cidade: cidade || "sp"
|
|
361
|
+
};
|
|
362
|
+
} else {
|
|
363
|
+
params = {
|
|
364
|
+
logradouro: paramsOrLogradouro.logradouro,
|
|
365
|
+
numero: paramsOrLogradouro.numero,
|
|
366
|
+
complemento: paramsOrLogradouro.complemento,
|
|
367
|
+
cidade: paramsOrLogradouro.cidade || "sp",
|
|
368
|
+
incluir_historico: paramsOrLogradouro.incluirHistorico,
|
|
369
|
+
incluir_comparaveis: paramsOrLogradouro.incluirComparaveis,
|
|
370
|
+
incluir_zoneamento: paramsOrLogradouro.incluirZoneamento
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return this.request(
|
|
374
|
+
"GET",
|
|
375
|
+
"/consulta/endereco",
|
|
376
|
+
params
|
|
377
|
+
);
|
|
119
378
|
}
|
|
120
379
|
/**
|
|
121
|
-
* Busca dados de IPTU por
|
|
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
|
|
385
|
+
* @returns Dados completos do imóvel
|
|
122
386
|
*/
|
|
123
|
-
async
|
|
124
|
-
return this.request("GET",
|
|
125
|
-
|
|
126
|
-
|
|
387
|
+
async consultaSQL(sql, cidade = "sp", options) {
|
|
388
|
+
return this.request("GET", `/consulta/sql/${sql}`, {
|
|
389
|
+
cidade,
|
|
390
|
+
incluir_historico: options?.incluirHistorico,
|
|
391
|
+
incluir_comparaveis: options?.incluirComparaveis
|
|
127
392
|
});
|
|
128
393
|
}
|
|
129
394
|
/**
|
|
130
|
-
* Busca
|
|
395
|
+
* Busca imóveis por CEP.
|
|
396
|
+
*
|
|
397
|
+
* @param cep - CEP do imóvel
|
|
398
|
+
* @param cidade - Cidade da consulta
|
|
399
|
+
* @returns Lista de imóveis no CEP
|
|
131
400
|
*/
|
|
132
|
-
async
|
|
133
|
-
|
|
401
|
+
async consultaCEP(cep, cidade = "sp") {
|
|
402
|
+
const cleanCep = cep.replace(/\D/g, "");
|
|
403
|
+
return this.request(
|
|
404
|
+
"GET",
|
|
405
|
+
`/consulta/cep/${cleanCep}`,
|
|
406
|
+
{ cidade }
|
|
407
|
+
);
|
|
134
408
|
}
|
|
135
409
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* @param
|
|
139
|
-
* @param
|
|
140
|
-
* @
|
|
141
|
-
* @param limit - Limite de resultados (default: 20)
|
|
410
|
+
* Consulta zoneamento por coordenadas.
|
|
411
|
+
*
|
|
412
|
+
* @param latitude - Latitude do ponto
|
|
413
|
+
* @param longitude - Longitude do ponto
|
|
414
|
+
* @returns Dados de zoneamento
|
|
142
415
|
*/
|
|
143
|
-
async
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
416
|
+
async consultaZoneamento(latitude, longitude) {
|
|
417
|
+
return this.request("GET", "/consulta/zoneamento", {
|
|
418
|
+
latitude,
|
|
419
|
+
longitude
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
// ===========================================================================
|
|
423
|
+
// Valuation Endpoints (Pro+)
|
|
424
|
+
// ===========================================================================
|
|
425
|
+
/**
|
|
426
|
+
* Estima o valor de mercado do imóvel usando ML.
|
|
427
|
+
* Disponível apenas para planos Pro e Enterprise.
|
|
428
|
+
*
|
|
429
|
+
* @param params - Parâmetros do imóvel
|
|
430
|
+
* @returns Estimativa de valor
|
|
431
|
+
* @throws {ForbiddenError} Se o plano não permitir
|
|
432
|
+
*/
|
|
433
|
+
async valuationEstimate(params) {
|
|
434
|
+
return this.request(
|
|
435
|
+
"POST",
|
|
436
|
+
"/valuation/estimate",
|
|
437
|
+
void 0,
|
|
438
|
+
{
|
|
439
|
+
area_terreno: params.area_terreno,
|
|
440
|
+
area_construida: params.area_construida,
|
|
441
|
+
bairro: params.bairro,
|
|
442
|
+
zona: params.zona,
|
|
443
|
+
tipo_uso: params.tipo_uso,
|
|
444
|
+
tipo_padrao: params.tipo_padrao,
|
|
445
|
+
ano_construcao: params.ano_construcao,
|
|
446
|
+
cidade: params.cidade || "sp"
|
|
447
|
+
}
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Valuation em lote (até 100 imóveis).
|
|
452
|
+
* Disponível apenas para plano Enterprise.
|
|
453
|
+
*
|
|
454
|
+
* @param imoveis - Lista de imóveis para avaliar
|
|
455
|
+
* @returns Resultados de valuation para cada imóvel
|
|
456
|
+
*/
|
|
457
|
+
async valuationBatch(imoveis) {
|
|
458
|
+
return this.request(
|
|
459
|
+
"POST",
|
|
460
|
+
"/valuation/estimate/batch",
|
|
461
|
+
void 0,
|
|
462
|
+
{ imoveis }
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Busca imóveis comparáveis para análise.
|
|
467
|
+
*
|
|
468
|
+
* @param bairro - Nome do bairro
|
|
469
|
+
* @param areaMin - Área mínima em m²
|
|
470
|
+
* @param areaMax - Área máxima em m²
|
|
471
|
+
* @param options - Opções adicionais
|
|
472
|
+
* @returns Lista de imóveis comparáveis
|
|
473
|
+
*/
|
|
474
|
+
async valuationComparables(bairro, areaMin, areaMax, options) {
|
|
475
|
+
return this.request("GET", "/valuation/comparables", {
|
|
476
|
+
bairro,
|
|
477
|
+
area_min: areaMin,
|
|
478
|
+
area_max: areaMax,
|
|
479
|
+
tipo_uso: options?.tipoUso,
|
|
480
|
+
cidade: options?.cidade || "sp",
|
|
481
|
+
limit: options?.limit || 10
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
// ===========================================================================
|
|
485
|
+
// Dados Endpoints
|
|
486
|
+
// ===========================================================================
|
|
487
|
+
/**
|
|
488
|
+
* Histórico de valores IPTU de um imóvel.
|
|
489
|
+
*
|
|
490
|
+
* @param sql - Número SQL do imóvel
|
|
491
|
+
* @param cidade - Cidade da consulta
|
|
492
|
+
* @returns Lista com histórico anual
|
|
493
|
+
*/
|
|
494
|
+
async dadosIPTUHistorico(sql, cidade = "sp") {
|
|
152
495
|
return this.request(
|
|
153
496
|
"GET",
|
|
154
|
-
`/dados/iptu/${
|
|
155
|
-
|
|
497
|
+
`/dados/iptu/historico/${sql}`,
|
|
498
|
+
{ cidade }
|
|
156
499
|
);
|
|
157
500
|
}
|
|
158
501
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* @param
|
|
162
|
-
* @
|
|
502
|
+
* Consulta dados de empresa por CNPJ.
|
|
503
|
+
*
|
|
504
|
+
* @param cnpj - CNPJ da empresa
|
|
505
|
+
* @returns Dados cadastrais
|
|
163
506
|
*/
|
|
164
|
-
async
|
|
165
|
-
const
|
|
166
|
-
if (ano !== void 0) {
|
|
167
|
-
params.ano = ano.toString();
|
|
168
|
-
}
|
|
507
|
+
async dadosCNPJ(cnpj) {
|
|
508
|
+
const cleanCnpj = cnpj.replace(/\D/g, "");
|
|
169
509
|
return this.request(
|
|
170
510
|
"GET",
|
|
171
|
-
`/dados/
|
|
172
|
-
params
|
|
511
|
+
`/dados/cnpj/${cleanCnpj}`
|
|
173
512
|
);
|
|
174
513
|
}
|
|
175
514
|
/**
|
|
176
|
-
*
|
|
515
|
+
* Correção monetária pelo IPCA.
|
|
516
|
+
*
|
|
517
|
+
* @param valor - Valor a corrigir
|
|
518
|
+
* @param dataOrigem - Data do valor original (YYYY-MM)
|
|
519
|
+
* @param dataDestino - Data destino (default: atual)
|
|
520
|
+
* @returns Valor corrigido e fator de correção
|
|
177
521
|
*/
|
|
178
|
-
async
|
|
522
|
+
async dadosIPCACorrigir(valor, dataOrigem, dataDestino) {
|
|
179
523
|
return this.request(
|
|
180
|
-
"
|
|
181
|
-
"/
|
|
182
|
-
|
|
183
|
-
|
|
524
|
+
"GET",
|
|
525
|
+
"/dados/ipca/corrigir",
|
|
526
|
+
{
|
|
527
|
+
valor,
|
|
528
|
+
data_origem: dataOrigem,
|
|
529
|
+
data_destino: dataDestino
|
|
530
|
+
}
|
|
184
531
|
);
|
|
185
532
|
}
|
|
186
533
|
};
|
|
@@ -188,9 +535,14 @@ var index_default = IPTUClient;
|
|
|
188
535
|
// Annotate the CommonJS export names for ESM import in node:
|
|
189
536
|
0 && (module.exports = {
|
|
190
537
|
AuthenticationError,
|
|
538
|
+
CidadeEnum,
|
|
191
539
|
ForbiddenError,
|
|
192
540
|
IPTUAPIError,
|
|
193
541
|
IPTUClient,
|
|
542
|
+
NetworkError,
|
|
194
543
|
NotFoundError,
|
|
195
|
-
RateLimitError
|
|
544
|
+
RateLimitError,
|
|
545
|
+
ServerError,
|
|
546
|
+
TimeoutError,
|
|
547
|
+
ValidationError
|
|
196
548
|
});
|