vies-checker
Version:
Modern European VIES VAT number validator with full TypeScript support
105 lines • 4.24 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = fetchVies;
const errors_js_1 = require("../errors.js");
/**
* Delays execution for a specified number of milliseconds
* @param ms - Milliseconds to delay
*/
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Checks if an error is a network error that might be retryable
*/
function isNetworkError(error) {
return (error instanceof TypeError ||
(error instanceof Error &&
(error.message.includes('fetch') ||
error.message.includes('network') ||
error.message.includes('ECONNREFUSED') ||
error.message.includes('ETIMEDOUT'))));
}
/**
* Validates the VIES response and throws appropriate errors
* @param response - The VIES API response
* @throws {ViesError} If the response contains an error state
*/
function validateResponse(response) {
const errorStates = [
'GLOBAL_MAX_CONCURRENT_REQ',
'MS_MAX_CONCURRENT_REQ',
'SERVICE_UNAVAILABLE',
'MS_UNAVAILABLE',
'TIMEOUT',
];
if (errorStates.includes(response.userError)) {
throw new errors_js_1.ViesError(response.userError);
}
}
/**
* Makes a request to the VIES API with timeout and retry support
*
* @param country - Two-letter EU country code
* @param vatNumber - VAT number to validate
* @param options - Request options (timeout, retries)
* @returns VIES API response
* @throws {ViesError} On API errors or validation failures
*
* @example
* ```typescript
* const response = await fetchVies('LU', '26375245', { timeout: 5000 });
* ```
*/
function fetchVies(country_1, vatNumber_1) {
return __awaiter(this, arguments, void 0, function* (country, vatNumber, options = {}) {
const { timeout = 10000, retries = 0 } = options;
const url = `https://ec.europa.eu/taxation_customs/vies/rest-api/ms/${country}/vat/${vatNumber}`;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = yield fetch(url, {
method: 'GET',
signal: controller.signal,
headers: {
Accept: 'application/json',
},
});
clearTimeout(timeoutId);
if (!response.ok) {
throw new errors_js_1.ViesError('SERVICE_UNAVAILABLE', `HTTP ${response.status}: ${response.statusText}`);
}
const data = yield response.json();
validateResponse(data);
return data;
}
catch (error) {
clearTimeout(timeoutId);
// Handle abort/timeout
if (error instanceof Error && error.name === 'AbortError') {
throw new errors_js_1.ViesError('TIMEOUT', 'Request timed out');
}
// Propagate ViesError
if (error instanceof errors_js_1.ViesError) {
throw error;
}
// Retry logic for network errors
if (retries > 0 && isNetworkError(error)) {
yield delay(1000); // Simple backoff
return fetchVies(country, vatNumber, { timeout, retries: retries - 1 });
}
// Wrap unknown errors
throw new errors_js_1.ViesError('SERVICE_UNAVAILABLE', error instanceof Error ? error.message : 'Unknown error occurred');
}
});
}
//# sourceMappingURL=request.js.map