@fin.cx/opendata 4.2.0 → 4.3.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/vatid/classes.evatrclient.d.ts +15 -0
- package/dist_ts/vatid/classes.evatrclient.js +169 -0
- package/dist_ts/vatid/classes.vatiderror.d.ts +51 -0
- package/dist_ts/vatid/classes.vatiderror.js +29 -0
- package/dist_ts/vatid/classes.viesclient.d.ts +12 -0
- package/dist_ts/vatid/classes.viesclient.js +118 -0
- package/dist_ts/vatid/constants.d.ts +28 -0
- package/dist_ts/vatid/constants.js +37 -0
- package/dist_ts/vatid/index.d.ts +6 -0
- package/dist_ts/vatid/index.js +10 -0
- package/dist_ts/vatid/interfaces.d.ts +141 -0
- package/dist_ts/vatid/interfaces.js +2 -0
- package/dist_ts/vatid/request.d.ts +16 -0
- package/dist_ts/vatid/request.js +65 -0
- package/dist_ts/vatid/vatid.d.ts +8 -0
- package/dist_ts/vatid/vatid.js +22 -0
- package/package.json +7 -3
- package/readme.md +49 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/vatid/classes.evatrclient.ts +182 -0
- package/ts/vatid/classes.vatiderror.ts +83 -0
- package/ts/vatid/classes.viesclient.ts +123 -0
- package/ts/vatid/constants.ts +40 -0
- package/ts/vatid/index.ts +17 -0
- package/ts/vatid/interfaces.ts +154 -0
- package/ts/vatid/request.ts +77 -0
- package/ts/vatid/vatid.ts +25 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@fin.cx/opendata',
|
|
6
|
-
version: '4.
|
|
6
|
+
version: '4.3.0',
|
|
7
7
|
description: 'Open business and financial data for TypeScript: register lookups on the German register portal (handelsregister.de) without storage, the statutory public holidays of the German federal states, the base rate of § 247 BGB, and stock and crypto prices and fundamentals from several providers.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLG9TQUFvUztDQUNsVCxDQUFBIn0=
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IEvatrConfirmation, IEvatrConfirmationInput, IVatIdClientOptions, IVatIdTraderData } from './interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* The BZSt's confirmation of foreign VAT IDs (§ 18e Nr. 1 UStG) over its eVatR REST API
|
|
4
|
+
* (`https://api.evatr.vies.bzst.de/api-docs`). A simple confirmation says whether a VAT ID is valid
|
|
5
|
+
* when asked; a qualified one also compares the business's name, city, and where given street and
|
|
6
|
+
* postal code with what its member state registered. The BZSt confirms to a business with a German
|
|
7
|
+
* VAT ID of its own, which every request names. Nothing is kept: each answer goes to the caller.
|
|
8
|
+
*/
|
|
9
|
+
export declare class EvatrClient {
|
|
10
|
+
private readonly options;
|
|
11
|
+
constructor(options?: IVatIdClientOptions);
|
|
12
|
+
confirm(inputArg: IEvatrConfirmationInput): Promise<IEvatrConfirmation>;
|
|
13
|
+
}
|
|
14
|
+
/** The business data as a qualified confirmation sends it: trimmed, with the name and the city required. */
|
|
15
|
+
export declare const traderOf: (traderArg: IVatIdTraderData) => IVatIdTraderData | undefined;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { VatIdError } from './classes.vatiderror.js';
|
|
2
|
+
import { evatrBaseUrl, evatrConfirmationPath, evatrStatusCodes } from './constants.js';
|
|
3
|
+
import { postJson, textField } from './request.js';
|
|
4
|
+
import { splitVatId } from './vatid.js';
|
|
5
|
+
/** The status codes that are an answer about the VAT ID asked about, and whether they say it is valid. */
|
|
6
|
+
const ANSWERS = {
|
|
7
|
+
'evatr-0000': true,
|
|
8
|
+
'evatr-2008': true,
|
|
9
|
+
'evatr-2001': false,
|
|
10
|
+
'evatr-2002': false,
|
|
11
|
+
'evatr-2006': false,
|
|
12
|
+
};
|
|
13
|
+
/** What every other status code means for the caller (`VatIdError`). */
|
|
14
|
+
const REFUSALS = {
|
|
15
|
+
'evatr-0001': 'invalid_input',
|
|
16
|
+
'evatr-0002': 'invalid_input',
|
|
17
|
+
'evatr-0003': 'invalid_input',
|
|
18
|
+
'evatr-0004': 'requester_invalid',
|
|
19
|
+
'evatr-0005': 'vat_id_malformed',
|
|
20
|
+
'evatr-0006': 'not_permitted',
|
|
21
|
+
'evatr-0007': 'invalid_input',
|
|
22
|
+
'evatr-0008': 'qualified_limit_reached',
|
|
23
|
+
'evatr-0011': 'unavailable',
|
|
24
|
+
'evatr-0012': 'vat_id_malformed',
|
|
25
|
+
'evatr-0013': 'unavailable',
|
|
26
|
+
'evatr-1001': 'unavailable',
|
|
27
|
+
'evatr-1002': 'unavailable',
|
|
28
|
+
'evatr-1003': 'unavailable',
|
|
29
|
+
'evatr-1004': 'unavailable',
|
|
30
|
+
'evatr-2003': 'vat_id_malformed',
|
|
31
|
+
'evatr-2004': 'unavailable',
|
|
32
|
+
'evatr-2005': 'requester_invalid',
|
|
33
|
+
'evatr-2007': 'member_state_unavailable',
|
|
34
|
+
'evatr-2011': 'unavailable',
|
|
35
|
+
'evatr-3011': 'unavailable',
|
|
36
|
+
};
|
|
37
|
+
const FIELD_RESULTS = ['A', 'B', 'C', 'D'];
|
|
38
|
+
const fieldResult = (bodyArg, keyArg) => {
|
|
39
|
+
const value = textField(bodyArg, keyArg);
|
|
40
|
+
return value !== undefined && FIELD_RESULTS.includes(value) ? value : undefined;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The BZSt's confirmation of foreign VAT IDs (§ 18e Nr. 1 UStG) over its eVatR REST API
|
|
44
|
+
* (`https://api.evatr.vies.bzst.de/api-docs`). A simple confirmation says whether a VAT ID is valid
|
|
45
|
+
* when asked; a qualified one also compares the business's name, city, and where given street and
|
|
46
|
+
* postal code with what its member state registered. The BZSt confirms to a business with a German
|
|
47
|
+
* VAT ID of its own, which every request names. Nothing is kept: each answer goes to the caller.
|
|
48
|
+
*/
|
|
49
|
+
export class EvatrClient {
|
|
50
|
+
options;
|
|
51
|
+
constructor(options = {}) {
|
|
52
|
+
this.options = options;
|
|
53
|
+
}
|
|
54
|
+
async confirm(inputArg) {
|
|
55
|
+
const requester = splitVatId(inputArg.requesterVatId);
|
|
56
|
+
if (!requester || requester.countryCode !== 'DE') {
|
|
57
|
+
throw new VatIdError('invalid_input', 'the requester is named by its German VAT ID', { service: 'bzst-evatr', field: 'requesterVatId' });
|
|
58
|
+
}
|
|
59
|
+
const asked = splitVatId(inputArg.vatId);
|
|
60
|
+
if (!asked) {
|
|
61
|
+
throw new VatIdError('invalid_input', 'the VAT ID asked about starts with no member state\'s code', { service: 'bzst-evatr', field: 'vatId' });
|
|
62
|
+
}
|
|
63
|
+
const trader = inputArg.trader ? traderOf(inputArg.trader) : undefined;
|
|
64
|
+
if (inputArg.trader && !trader) {
|
|
65
|
+
throw new VatIdError('invalid_input', 'a qualified confirmation needs the name and the city', { service: 'bzst-evatr', field: 'trader' });
|
|
66
|
+
}
|
|
67
|
+
const answer = await postJson(this.options, 'bzst-evatr', `${this.options.baseUrl ?? evatrBaseUrl}${evatrConfirmationPath}`, {
|
|
68
|
+
anfragendeUstid: requester.vatId,
|
|
69
|
+
angefragteUstid: asked.vatId,
|
|
70
|
+
...(trader
|
|
71
|
+
? {
|
|
72
|
+
firmenname: trader.name,
|
|
73
|
+
ort: trader.city,
|
|
74
|
+
...(trader.street ? { strasse: trader.street } : {}),
|
|
75
|
+
...(trader.postalCode ? { plz: trader.postalCode } : {}),
|
|
76
|
+
}
|
|
77
|
+
: {}),
|
|
78
|
+
}, inputArg.signal);
|
|
79
|
+
const status = textField(answer.body, 'status');
|
|
80
|
+
if (!status || !evatrStatusCodes.includes(status)) {
|
|
81
|
+
throw new VatIdError('unexpected_answer', `the BZSt answered HTTP ${answer.httpStatus} without a status it documents`, {
|
|
82
|
+
service: 'bzst-evatr',
|
|
83
|
+
httpStatus: answer.httpStatus,
|
|
84
|
+
...(status ? { serviceCode: status } : {}),
|
|
85
|
+
answer: answer.answer,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const code = status;
|
|
89
|
+
const valid = ANSWERS[code];
|
|
90
|
+
if (valid === undefined) {
|
|
91
|
+
throw new VatIdError(REFUSALS[code] ?? 'unexpected_answer', `the BZSt answered ${code}`, {
|
|
92
|
+
service: 'bzst-evatr',
|
|
93
|
+
serviceCode: code,
|
|
94
|
+
httpStatus: answer.httpStatus,
|
|
95
|
+
answer: answer.answer,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const requestedAt = textField(answer.body, 'anfrageZeitpunkt');
|
|
99
|
+
const requestedAtMs = requestedAt ? Date.parse(requestedAt) : Number.NaN;
|
|
100
|
+
if (!requestedAt || Number.isNaN(requestedAtMs)) {
|
|
101
|
+
throw new VatIdError('unexpected_answer', 'the BZSt answered without the moment of the request', {
|
|
102
|
+
service: 'bzst-evatr',
|
|
103
|
+
serviceCode: code,
|
|
104
|
+
httpStatus: answer.httpStatus,
|
|
105
|
+
answer: answer.answer,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
const requestId = textField(answer.body, 'id');
|
|
109
|
+
const validFrom = textField(answer.body, 'gueltigAb');
|
|
110
|
+
const validTo = textField(answer.body, 'gueltigBis');
|
|
111
|
+
const qualified = trader && valid ? qualifiedResultOf(trader, code, answer.body) : undefined;
|
|
112
|
+
if (qualified === null) {
|
|
113
|
+
// a qualified request answered valid without a result for each field sent would read as a simple
|
|
114
|
+
// confirmation; it is refused instead of being passed on as one
|
|
115
|
+
throw new VatIdError('unexpected_answer', `the BZSt answered ${code} to a qualified request without a documented result for each field sent`, {
|
|
116
|
+
service: 'bzst-evatr',
|
|
117
|
+
serviceCode: code,
|
|
118
|
+
httpStatus: answer.httpStatus,
|
|
119
|
+
answer: answer.answer,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
service: 'bzst-evatr',
|
|
124
|
+
...(requestId ? { requestId } : {}),
|
|
125
|
+
requestedAt,
|
|
126
|
+
requestedAtMs,
|
|
127
|
+
status: code,
|
|
128
|
+
valid,
|
|
129
|
+
...(validFrom ? { validFrom } : {}),
|
|
130
|
+
...(validTo ? { validTo } : {}),
|
|
131
|
+
requesterVatId: requester.vatId,
|
|
132
|
+
vatId: asked.vatId,
|
|
133
|
+
...(qualified ? { qualified } : {}),
|
|
134
|
+
answer: answer.answer,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The comparison of a qualified request whose VAT ID is valid: `evatr-2008` says it has a
|
|
140
|
+
* particularity and gives no result (`answered: false`); otherwise every field sent has a documented
|
|
141
|
+
* result (`A`…`D`), or the answer is not one this client reads (`null`). A result the BZSt gives for a
|
|
142
|
+
* field not sent is kept as it is.
|
|
143
|
+
*/
|
|
144
|
+
const qualifiedResultOf = (traderArg, codeArg, bodyArg) => {
|
|
145
|
+
if (codeArg === 'evatr-2008') {
|
|
146
|
+
return { asked: traderArg, answered: false };
|
|
147
|
+
}
|
|
148
|
+
const name = fieldResult(bodyArg, 'ergFirmenname');
|
|
149
|
+
const city = fieldResult(bodyArg, 'ergOrt');
|
|
150
|
+
// a field not sent may still carry its result (`C`, not asked); one sent must
|
|
151
|
+
const street = fieldResult(bodyArg, 'ergStrasse');
|
|
152
|
+
const postalCode = fieldResult(bodyArg, 'ergPlz');
|
|
153
|
+
if (!name || !city || (traderArg.street && !street) || (traderArg.postalCode && !postalCode)) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
return { asked: traderArg, answered: true, name, city, ...(street ? { street } : {}), ...(postalCode ? { postalCode } : {}) };
|
|
157
|
+
};
|
|
158
|
+
/** The business data as a qualified confirmation sends it: trimmed, with the name and the city required. */
|
|
159
|
+
export const traderOf = (traderArg) => {
|
|
160
|
+
const name = traderArg.name.trim();
|
|
161
|
+
const city = traderArg.city.trim();
|
|
162
|
+
if (!name || !city) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
const street = traderArg.street?.trim();
|
|
166
|
+
const postalCode = traderArg.postalCode?.trim();
|
|
167
|
+
return { name, city, ...(street ? { street } : {}), ...(postalCode ? { postalCode } : {}) };
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ldmF0cmNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3ZhdGlkL2NsYXNzZXMuZXZhdHJjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBd0IsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRSxPQUFPLEVBQUUsWUFBWSxFQUFFLHFCQUFxQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFVdkYsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDbkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV4QywwR0FBMEc7QUFDMUcsTUFBTSxPQUFPLEdBQXlEO0lBQ3BFLFlBQVksRUFBRSxJQUFJO0lBQ2xCLFlBQVksRUFBRSxJQUFJO0lBQ2xCLFlBQVksRUFBRSxLQUFLO0lBQ25CLFlBQVksRUFBRSxLQUFLO0lBQ25CLFlBQVksRUFBRSxLQUFLO0NBQ3BCLENBQUM7QUFFRix3RUFBd0U7QUFDeEUsTUFBTSxRQUFRLEdBQWlFO0lBQzdFLFlBQVksRUFBRSxlQUFlO0lBQzdCLFlBQVksRUFBRSxlQUFlO0lBQzdCLFlBQVksRUFBRSxlQUFlO0lBQzdCLFlBQVksRUFBRSxtQkFBbUI7SUFDakMsWUFBWSxFQUFFLGtCQUFrQjtJQUNoQyxZQUFZLEVBQUUsZUFBZTtJQUM3QixZQUFZLEVBQUUsZUFBZTtJQUM3QixZQUFZLEVBQUUseUJBQXlCO0lBQ3ZDLFlBQVksRUFBRSxhQUFhO0lBQzNCLFlBQVksRUFBRSxrQkFBa0I7SUFDaEMsWUFBWSxFQUFFLGFBQWE7SUFDM0IsWUFBWSxFQUFFLGFBQWE7SUFDM0IsWUFBWSxFQUFFLGFBQWE7SUFDM0IsWUFBWSxFQUFFLGFBQWE7SUFDM0IsWUFBWSxFQUFFLGFBQWE7SUFDM0IsWUFBWSxFQUFFLGtCQUFrQjtJQUNoQyxZQUFZLEVBQUUsYUFBYTtJQUMzQixZQUFZ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
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { IVatIdServiceAnswer } from './interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Why a VAT ID could not be confirmed. Every code means that the service gave no answer about the
|
|
4
|
+
* validity of the VAT ID asked about:
|
|
5
|
+
* - `invalid_input`: what was asked is incomplete or not a VAT ID of a member state (checked before
|
|
6
|
+
* sending, or refused by the service: eVatR `evatr-0002`, `evatr-0003`, `evatr-0007`, VIES
|
|
7
|
+
* `INVALID_INPUT`);
|
|
8
|
+
* - `vat_id_malformed`: the service says the VAT ID asked about does not have the form its member
|
|
9
|
+
* state gives (eVatR `evatr-0005`, `evatr-0012`, `evatr-2003`);
|
|
10
|
+
* - `requester_invalid`: the requester's own VAT ID is malformed or not valid (eVatR `evatr-0004`,
|
|
11
|
+
* `evatr-2005`, VIES `INVALID_REQUESTER_INFO`);
|
|
12
|
+
* - `not_permitted`: a German VAT ID asked about by a German one (eVatR `evatr-0006`);
|
|
13
|
+
* - `qualified_limit_reached`: the qualified confirmations of this session are used up (eVatR
|
|
14
|
+
* `evatr-0008`); a simple one is still possible;
|
|
15
|
+
* - `unavailable`: the service cannot answer now (eVatR `evatr-0011`, `-0013`, `-1001`…`-1004`,
|
|
16
|
+
* `-2004`, `-2011`, `-3011`; VIES `SERVICE_UNAVAILABLE`);
|
|
17
|
+
* - `member_state_unavailable`: the member state's system did not answer or failed (eVatR
|
|
18
|
+
* `evatr-2007`; VIES `MS_UNAVAILABLE`, `TIMEOUT`);
|
|
19
|
+
* - `busy`: too many requests at once (VIES `GLOBAL_MAX_CONCURRENT_REQ`, `MS_MAX_CONCURRENT_REQ`
|
|
20
|
+
* and their `_TIME` forms);
|
|
21
|
+
* - `blocked`: the service blocks this address or this VAT ID (VIES `IP_BLOCKED`, `VAT_BLOCKED`);
|
|
22
|
+
* - `unreachable`: no answer arrived — the name, the connection or TLS failed;
|
|
23
|
+
* - `timeout`: the answer did not arrive within the client's time;
|
|
24
|
+
* - `aborted`: the caller's signal ended the request;
|
|
25
|
+
* - `unexpected_answer`: an answer this client cannot read, or a status it does not know.
|
|
26
|
+
*/
|
|
27
|
+
export type TVatIdErrorCode = 'invalid_input' | 'vat_id_malformed' | 'requester_invalid' | 'not_permitted' | 'qualified_limit_reached' | 'unavailable' | 'member_state_unavailable' | 'busy' | 'blocked' | 'unreachable' | 'timeout' | 'aborted' | 'unexpected_answer';
|
|
28
|
+
export interface IVatIdErrorDetails {
|
|
29
|
+
service: 'bzst-evatr' | 'vies';
|
|
30
|
+
/** the service's own code: `evatr-0008`, `MS_UNAVAILABLE` */
|
|
31
|
+
serviceCode?: string;
|
|
32
|
+
/** the HTTP status of the answer, where one arrived */
|
|
33
|
+
httpStatus?: number;
|
|
34
|
+
/** which input a local check refused */
|
|
35
|
+
field?: 'requesterVatId' | 'vatId' | 'trader';
|
|
36
|
+
/** the answer as it arrived, where one did */
|
|
37
|
+
answer?: IVatIdServiceAnswer;
|
|
38
|
+
}
|
|
39
|
+
/** The typed error of the VAT ID clients. */
|
|
40
|
+
export declare class VatIdError extends Error {
|
|
41
|
+
readonly code: TVatIdErrorCode;
|
|
42
|
+
readonly service: IVatIdErrorDetails['service'];
|
|
43
|
+
readonly serviceCode?: string;
|
|
44
|
+
readonly httpStatus?: number;
|
|
45
|
+
readonly field?: IVatIdErrorDetails['field'];
|
|
46
|
+
/** the answer as it arrived, where one did: a refusal, or an answer this client cannot read */
|
|
47
|
+
readonly answer?: IVatIdServiceAnswer;
|
|
48
|
+
constructor(code: TVatIdErrorCode, message: string, detailsArg: IVatIdErrorDetails, options?: {
|
|
49
|
+
cause?: unknown;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** The typed error of the VAT ID clients. */
|
|
2
|
+
export class VatIdError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
service;
|
|
5
|
+
serviceCode;
|
|
6
|
+
httpStatus;
|
|
7
|
+
field;
|
|
8
|
+
/** the answer as it arrived, where one did: a refusal, or an answer this client cannot read */
|
|
9
|
+
answer;
|
|
10
|
+
constructor(code, message, detailsArg, options) {
|
|
11
|
+
super(message, options);
|
|
12
|
+
this.name = 'VatIdError';
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.service = detailsArg.service;
|
|
15
|
+
if (detailsArg.serviceCode !== undefined) {
|
|
16
|
+
this.serviceCode = detailsArg.serviceCode;
|
|
17
|
+
}
|
|
18
|
+
if (detailsArg.httpStatus !== undefined) {
|
|
19
|
+
this.httpStatus = detailsArg.httpStatus;
|
|
20
|
+
}
|
|
21
|
+
if (detailsArg.field !== undefined) {
|
|
22
|
+
this.field = detailsArg.field;
|
|
23
|
+
}
|
|
24
|
+
if (detailsArg.answer !== undefined) {
|
|
25
|
+
this.answer = detailsArg.answer;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy52YXRpZGVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvdmF0aWQvY2xhc3Nlcy52YXRpZGVycm9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXNEQSw2Q0FBNkM7QUFDN0MsTUFBTSxPQUFPLFVBQVcsU0FBUSxLQUFLO0lBQ25CLElBQUksQ0FBa0I7SUFDdEIsT0FBTyxDQUFnQztJQUN2QyxXQUFXLENBQVU7SUFDckIsVUFBVSxDQUFVO0lBQ3BCLEtBQUssQ0FBK0I7SUFDcEQsK0ZBQStGO0lBQy9FLE1BQU0sQ0FBdUI7SUFFN0MsWUFBWSxJQUFxQixFQUFFLE9BQWUsRUFBRSxVQUE4QixFQUFFLE9BQTZCO1FBQy9HLEtBQUssQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDeEIsSUFBSSxDQUFDLElBQUksR0FBRyxZQUFZLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDO1FBQ2xDLElBQUksVUFBVSxDQUFDLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN6QyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUM7UUFDNUMsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLFVBQVUsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN4QyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUM7UUFDMUMsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsS0FBSyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUM7UUFDaEMsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDbEMsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IViesCheck, IViesCheckInput, IVatIdClientOptions } from './interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* The European Commission's VIES over its REST API ("Vies on-the-Web", `swagger_publicVAT.yaml`):
|
|
4
|
+
* whether a VAT ID is valid, and with the business data a comparison of each field. A request that
|
|
5
|
+
* names the requester's own VAT ID gets VIES's request identifier. Errors arrive with HTTP 200 and
|
|
6
|
+
* `actionSucceed: false`; they are thrown as `VatIdError`. Nothing is kept.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ViesClient {
|
|
9
|
+
private readonly options;
|
|
10
|
+
constructor(options?: IVatIdClientOptions);
|
|
11
|
+
check(inputArg: IViesCheckInput): Promise<IViesCheck>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { VatIdError } from './classes.vatiderror.js';
|
|
2
|
+
import { traderOf } from './classes.evatrclient.js';
|
|
3
|
+
import { viesBaseUrl, viesCheckPath } from './constants.js';
|
|
4
|
+
import { postJson, textField } from './request.js';
|
|
5
|
+
import { splitVatId } from './vatid.js';
|
|
6
|
+
/** The error codes of VIES's `errorWrappers`, as its test service answers them (read on 2026-09-27). */
|
|
7
|
+
const REFUSALS = {
|
|
8
|
+
INVALID_INPUT: 'invalid_input',
|
|
9
|
+
INVALID_REQUESTER_INFO: 'requester_invalid',
|
|
10
|
+
SERVICE_UNAVAILABLE: 'unavailable',
|
|
11
|
+
MS_UNAVAILABLE: 'member_state_unavailable',
|
|
12
|
+
TIMEOUT: 'member_state_unavailable',
|
|
13
|
+
VAT_BLOCKED: 'blocked',
|
|
14
|
+
IP_BLOCKED: 'blocked',
|
|
15
|
+
GLOBAL_MAX_CONCURRENT_REQ: 'busy',
|
|
16
|
+
GLOBAL_MAX_CONCURRENT_REQ_TIME: 'busy',
|
|
17
|
+
MS_MAX_CONCURRENT_REQ: 'busy',
|
|
18
|
+
MS_MAX_CONCURRENT_REQ_TIME: 'busy',
|
|
19
|
+
};
|
|
20
|
+
const MATCHES = ['VALID', 'INVALID', 'NOT_PROCESSED'];
|
|
21
|
+
const matchOf = (bodyArg, keyArg) => {
|
|
22
|
+
const value = textField(bodyArg, keyArg);
|
|
23
|
+
return value !== undefined && MATCHES.includes(value) ? value : undefined;
|
|
24
|
+
};
|
|
25
|
+
/** VIES writes `---` where a member state gives no name or address. */
|
|
26
|
+
const givenText = (bodyArg, keyArg) => {
|
|
27
|
+
const value = textField(bodyArg, keyArg)?.trim();
|
|
28
|
+
return value && value !== '---' ? value : undefined;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The European Commission's VIES over its REST API ("Vies on-the-Web", `swagger_publicVAT.yaml`):
|
|
32
|
+
* whether a VAT ID is valid, and with the business data a comparison of each field. A request that
|
|
33
|
+
* names the requester's own VAT ID gets VIES's request identifier. Errors arrive with HTTP 200 and
|
|
34
|
+
* `actionSucceed: false`; they are thrown as `VatIdError`. Nothing is kept.
|
|
35
|
+
*/
|
|
36
|
+
export class ViesClient {
|
|
37
|
+
options;
|
|
38
|
+
constructor(options = {}) {
|
|
39
|
+
this.options = options;
|
|
40
|
+
}
|
|
41
|
+
async check(inputArg) {
|
|
42
|
+
const asked = splitVatId(inputArg.vatId);
|
|
43
|
+
if (!asked) {
|
|
44
|
+
throw new VatIdError('invalid_input', 'the VAT ID asked about starts with no member state\'s code', { service: 'vies', field: 'vatId' });
|
|
45
|
+
}
|
|
46
|
+
const requester = inputArg.requesterVatId === undefined ? undefined : splitVatId(inputArg.requesterVatId);
|
|
47
|
+
if (inputArg.requesterVatId !== undefined && !requester) {
|
|
48
|
+
throw new VatIdError('invalid_input', 'the requester\'s VAT ID starts with no member state\'s code', { service: 'vies', field: 'requesterVatId' });
|
|
49
|
+
}
|
|
50
|
+
const trader = inputArg.trader ? traderOf(inputArg.trader) : undefined;
|
|
51
|
+
if (inputArg.trader && !trader) {
|
|
52
|
+
throw new VatIdError('invalid_input', 'a comparison needs the name and the city', { service: 'vies', field: 'trader' });
|
|
53
|
+
}
|
|
54
|
+
const answer = await postJson(this.options, 'vies', `${this.options.baseUrl ?? viesBaseUrl}${viesCheckPath}`, {
|
|
55
|
+
countryCode: asked.countryCode,
|
|
56
|
+
vatNumber: asked.number,
|
|
57
|
+
...(requester ? { requesterMemberStateCode: requester.countryCode, requesterNumber: requester.number } : {}),
|
|
58
|
+
...(trader
|
|
59
|
+
? {
|
|
60
|
+
traderName: trader.name,
|
|
61
|
+
traderCity: trader.city,
|
|
62
|
+
...(trader.street ? { traderStreet: trader.street } : {}),
|
|
63
|
+
...(trader.postalCode ? { traderPostalCode: trader.postalCode } : {}),
|
|
64
|
+
}
|
|
65
|
+
: {}),
|
|
66
|
+
}, inputArg.signal);
|
|
67
|
+
const body = answer.body;
|
|
68
|
+
const succeeded = body && typeof body === 'object' ? Reflect.get(body, 'actionSucceed') : undefined;
|
|
69
|
+
if (succeeded === false) {
|
|
70
|
+
const wrappers = Reflect.get(body, 'errorWrappers');
|
|
71
|
+
const first = Array.isArray(wrappers) ? wrappers[0] : undefined;
|
|
72
|
+
const serviceCode = textField(first, 'error');
|
|
73
|
+
throw new VatIdError(serviceCode ? (REFUSALS[serviceCode] ?? 'unexpected_answer') : 'unexpected_answer', `VIES answered ${serviceCode ?? 'an error without a code'}`, {
|
|
74
|
+
service: 'vies',
|
|
75
|
+
httpStatus: answer.httpStatus,
|
|
76
|
+
...(serviceCode ? { serviceCode } : {}),
|
|
77
|
+
answer: answer.answer,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const valid = body && typeof body === 'object' ? Reflect.get(body, 'valid') : undefined;
|
|
81
|
+
const requestedAt = textField(body, 'requestDate');
|
|
82
|
+
const requestedAtMs = requestedAt ? Date.parse(requestedAt) : Number.NaN;
|
|
83
|
+
if (answer.httpStatus !== 200 || typeof valid !== 'boolean' || !requestedAt || Number.isNaN(requestedAtMs)) {
|
|
84
|
+
throw new VatIdError('unexpected_answer', `VIES answered HTTP ${answer.httpStatus} in a form this client cannot read`, {
|
|
85
|
+
service: 'vies',
|
|
86
|
+
httpStatus: answer.httpStatus,
|
|
87
|
+
answer: answer.answer,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const requestId = textField(body, 'requestIdentifier');
|
|
91
|
+
const name = givenText(body, 'name') ?? givenText(body, 'traderName');
|
|
92
|
+
const address = givenText(body, 'address');
|
|
93
|
+
const compared = trader
|
|
94
|
+
? {
|
|
95
|
+
asked: trader,
|
|
96
|
+
...optionalMatch('name', matchOf(body, 'traderNameMatch')),
|
|
97
|
+
...optionalMatch('street', matchOf(body, 'traderStreetMatch')),
|
|
98
|
+
...optionalMatch('postalCode', matchOf(body, 'traderPostalCodeMatch')),
|
|
99
|
+
...optionalMatch('city', matchOf(body, 'traderCityMatch')),
|
|
100
|
+
}
|
|
101
|
+
: undefined;
|
|
102
|
+
return {
|
|
103
|
+
service: 'vies',
|
|
104
|
+
valid,
|
|
105
|
+
requestedAt,
|
|
106
|
+
requestedAtMs,
|
|
107
|
+
...(requestId ? { requestId } : {}),
|
|
108
|
+
vatId: asked.vatId,
|
|
109
|
+
...(requester ? { requesterVatId: requester.vatId } : {}),
|
|
110
|
+
...(name ? { name } : {}),
|
|
111
|
+
...(address ? { address } : {}),
|
|
112
|
+
...(compared ? { compared } : {}),
|
|
113
|
+
answer: answer.answer,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const optionalMatch = (keyArg, matchArg) => (matchArg ? { [keyArg]: matchArg } : {});
|
|
118
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy52aWVzY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvdmF0aWQvY2xhc3Nlcy52aWVzY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQXdCLE1BQU0seUJBQXlCLENBQUM7QUFDM0UsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFNUQsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDbkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV4Qyx3R0FBd0c7QUFDeEcsTUFBTSxRQUFRLEdBQThDO0lBQzFELGFBQWEsRUFBRSxlQUFlO0lBQzlCLHNCQUFzQixFQUFFLG1CQUFtQjtJQUMzQyxtQkFBbUIsRUFBRSxhQUFhO0lBQ2xDLGNBQWMsRUFBRSwwQkFBMEI7SUFDMUMsT0FBTyxFQUFFLDBCQUEwQjtJQUNuQyxXQUFXLEVBQUUsU0FBUztJQUN0QixVQUFVLEVBQUUsU0FBUztJQUNyQix5QkFBeUIsRUFBRSxNQUFNO0lBQ2pDLDhCQUE4QixFQUFFLE1BQU07SUFDdEMscUJBQXFCLEVBQUUsTUFBTTtJQUM3QiwwQkFBMEIsRUFBRSxNQUFNO0NBQ25DLENBQUM7QUFFRixNQUFNLE9BQU8sR0FBMEIsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLGVBQWUsQ0FBQyxDQUFDO0FBRTdFLE1BQU0sT0FBTyxHQUFHLENBQUMsT0FBZ0IsRUFBRSxNQUFjLEVBQTBCLEVBQUU7SUFDM0UsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUN6QyxPQUFPLEtBQUssS0FBSyxTQUFTLElBQUssT0FBNkIsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FB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
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The BZSt's eVatR REST API (Bestätigungsverfahren of § 18e UStG), as its OpenAPI document names it
|
|
3
|
+
* (`https://api.evatr.vies.bzst.de/api-docs`, read on 2026-09-27): the server, and the path of a
|
|
4
|
+
* confirmation. The XML-RPC interface the BZSt offered before is obsolete from 30 November 2025.
|
|
5
|
+
*/
|
|
6
|
+
export declare const evatrBaseUrl = "https://api.evatr.vies.bzst.de/app";
|
|
7
|
+
export declare const evatrConfirmationPath = "/v1/abfrage";
|
|
8
|
+
/**
|
|
9
|
+
* The European Commission's "Vies on-the-Web" REST API: the base under which its contract's paths
|
|
10
|
+
* (`swagger_publicVAT.yaml`) answer, read on 2026-09-27 (`/check-status` answered there, and so did
|
|
11
|
+
* `/check-vat-test-service`). The contract itself names no host.
|
|
12
|
+
*/
|
|
13
|
+
export declare const viesBaseUrl = "https://ec.europa.eu/taxation_customs/vies/rest-api";
|
|
14
|
+
export declare const viesCheckPath = "/check-vat-number";
|
|
15
|
+
/** How long one request may take by default, the answer included. */
|
|
16
|
+
export declare const defaultVatIdTimeoutMs = 30000;
|
|
17
|
+
/**
|
|
18
|
+
* The country codes a VAT identification number starts with, as the eVatR API's list of member
|
|
19
|
+
* states gives them (`/v1/info/eu_mitgliedstaaten`, read on 2026-09-27): the 27 member states,
|
|
20
|
+
* Greece as `EL`, and `XI` for Northern Ireland.
|
|
21
|
+
*/
|
|
22
|
+
export declare const vatIdCountryCodes: readonly ["AT", "BE", "BG", "CY", "CZ", "DE", "DK", "EE", "EL", "ES", "FI", "FR", "HR", "HU", "IE", "IT", "LT", "LU", "LV", "MT", "NL", "PL", "PT", "RO", "SE", "SI", "SK", "XI"];
|
|
23
|
+
/**
|
|
24
|
+
* Every status code of the eVatR API with the HTTP status its list of messages gives it
|
|
25
|
+
* (`/v1/info/statusmeldungen`, read on 2026-09-27). The OpenAPI document lists `evatr-0008` under
|
|
26
|
+
* 400 and the list under 403, so the code decides, never the HTTP status.
|
|
27
|
+
*/
|
|
28
|
+
export declare const evatrStatusCodes: readonly ["evatr-0000", "evatr-0001", "evatr-0002", "evatr-0003", "evatr-0004", "evatr-0005", "evatr-0006", "evatr-0007", "evatr-0008", "evatr-0011", "evatr-0012", "evatr-0013", "evatr-1001", "evatr-1002", "evatr-1003", "evatr-1004", "evatr-2001", "evatr-2002", "evatr-2003", "evatr-2004", "evatr-2005", "evatr-2006", "evatr-2007", "evatr-2008", "evatr-2011", "evatr-3011"];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The BZSt's eVatR REST API (Bestätigungsverfahren of § 18e UStG), as its OpenAPI document names it
|
|
3
|
+
* (`https://api.evatr.vies.bzst.de/api-docs`, read on 2026-09-27): the server, and the path of a
|
|
4
|
+
* confirmation. The XML-RPC interface the BZSt offered before is obsolete from 30 November 2025.
|
|
5
|
+
*/
|
|
6
|
+
export const evatrBaseUrl = 'https://api.evatr.vies.bzst.de/app';
|
|
7
|
+
export const evatrConfirmationPath = '/v1/abfrage';
|
|
8
|
+
/**
|
|
9
|
+
* The European Commission's "Vies on-the-Web" REST API: the base under which its contract's paths
|
|
10
|
+
* (`swagger_publicVAT.yaml`) answer, read on 2026-09-27 (`/check-status` answered there, and so did
|
|
11
|
+
* `/check-vat-test-service`). The contract itself names no host.
|
|
12
|
+
*/
|
|
13
|
+
export const viesBaseUrl = 'https://ec.europa.eu/taxation_customs/vies/rest-api';
|
|
14
|
+
export const viesCheckPath = '/check-vat-number';
|
|
15
|
+
/** How long one request may take by default, the answer included. */
|
|
16
|
+
export const defaultVatIdTimeoutMs = 30_000;
|
|
17
|
+
/**
|
|
18
|
+
* The country codes a VAT identification number starts with, as the eVatR API's list of member
|
|
19
|
+
* states gives them (`/v1/info/eu_mitgliedstaaten`, read on 2026-09-27): the 27 member states,
|
|
20
|
+
* Greece as `EL`, and `XI` for Northern Ireland.
|
|
21
|
+
*/
|
|
22
|
+
export const vatIdCountryCodes = [
|
|
23
|
+
'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'EL', 'ES', 'FI', 'FR', 'HR', 'HU',
|
|
24
|
+
'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK', 'XI',
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Every status code of the eVatR API with the HTTP status its list of messages gives it
|
|
28
|
+
* (`/v1/info/statusmeldungen`, read on 2026-09-27). The OpenAPI document lists `evatr-0008` under
|
|
29
|
+
* 400 and the list under 403, so the code decides, never the HTTP status.
|
|
30
|
+
*/
|
|
31
|
+
export const evatrStatusCodes = [
|
|
32
|
+
'evatr-0000', 'evatr-0001', 'evatr-0002', 'evatr-0003', 'evatr-0004', 'evatr-0005', 'evatr-0006',
|
|
33
|
+
'evatr-0007', 'evatr-0008', 'evatr-0011', 'evatr-0012', 'evatr-0013', 'evatr-1001', 'evatr-1002',
|
|
34
|
+
'evatr-1003', 'evatr-1004', 'evatr-2001', 'evatr-2002', 'evatr-2003', 'evatr-2004', 'evatr-2005',
|
|
35
|
+
'evatr-2006', 'evatr-2007', 'evatr-2008', 'evatr-2011', 'evatr-3011',
|
|
36
|
+
];
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvdmF0aWQvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsb0NBQW9DLENBQUM7QUFDakUsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsYUFBYSxDQUFDO0FBRW5EOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcscURBQXFELENBQUM7QUFDakYsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLG1CQUFtQixDQUFDO0FBRWpELHFFQUFxRTtBQUNyRSxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUM7QUFFNUM7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHO0lBQy9CLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJO0lBQ2xGLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJO0NBQzFFLENBQUM7QUFFWDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUc7SUFDOUIsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWTtJQUNoRyxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZO0lBQ2hHLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVk7SUFDaEcsWUFBWSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVk7Q0FDNUQsQ0FBQyJ9
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './interfaces.js';
|
|
2
|
+
export { VatIdError, type IVatIdErrorDetails, type TVatIdErrorCode } from './classes.vatiderror.js';
|
|
3
|
+
export { defaultVatIdTimeoutMs, evatrBaseUrl, evatrConfirmationPath, evatrStatusCodes, vatIdCountryCodes, viesBaseUrl, viesCheckPath, } from './constants.js';
|
|
4
|
+
export { splitVatId } from './vatid.js';
|
|
5
|
+
export { EvatrClient } from './classes.evatrclient.js';
|
|
6
|
+
export { ViesClient } from './classes.viesclient.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// This entry point stands alone: it imports nothing from the rest of the package and has no
|
|
2
|
+
// dependencies. It keeps nothing: every answer goes to the caller, who keeps it as evidence where the
|
|
3
|
+
// law asks for it.
|
|
4
|
+
export * from './interfaces.js';
|
|
5
|
+
export { VatIdError } from './classes.vatiderror.js';
|
|
6
|
+
export { defaultVatIdTimeoutMs, evatrBaseUrl, evatrConfirmationPath, evatrStatusCodes, vatIdCountryCodes, viesBaseUrl, viesCheckPath, } from './constants.js';
|
|
7
|
+
export { splitVatId } from './vatid.js';
|
|
8
|
+
export { EvatrClient } from './classes.evatrclient.js';
|
|
9
|
+
export { ViesClient } from './classes.viesclient.js';
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy92YXRpZC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSw0RkFBNEY7QUFDNUYsc0dBQXNHO0FBQ3RHLG1CQUFtQjtBQUNuQixjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxVQUFVLEVBQWlELE1BQU0seUJBQXlCLENBQUM7QUFDcEcsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixZQUFZLEVBQ1oscUJBQXFCLEVBQ3JCLGdCQUFnQixFQUNoQixpQkFBaUIsRUFDakIsV0FBVyxFQUNYLGFBQWEsR0FDZCxNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDeEMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQyJ9
|