@taxora/sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +436 -0
- package/dist/index.cjs +1046 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +315 -0
- package/dist/index.d.ts +315 -0
- package/dist/index.js +991 -0
- package/dist/index.js.map +1 -0
- package/package.json +72 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1046 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ApiVersion: () => ApiVersion,
|
|
24
|
+
AuthEndpoint: () => AuthEndpoint,
|
|
25
|
+
AuthRetryHttpClient: () => AuthRetryHttpClient,
|
|
26
|
+
AuthenticationException: () => AuthenticationException,
|
|
27
|
+
CompanyAddress: () => CompanyAddress,
|
|
28
|
+
CompanyEndpoint: () => CompanyEndpoint,
|
|
29
|
+
Environment: () => Environment,
|
|
30
|
+
FetchHttpClient: () => FetchHttpClient,
|
|
31
|
+
HttpException: () => HttpException,
|
|
32
|
+
InMemoryTokenStorage: () => InMemoryTokenStorage,
|
|
33
|
+
Language: () => Language,
|
|
34
|
+
LoginIdentifier: () => LoginIdentifier,
|
|
35
|
+
ProviderDocument: () => ProviderDocument,
|
|
36
|
+
ProviderDocumentLine: () => ProviderDocumentLine,
|
|
37
|
+
ScoreBreakdown: () => ScoreBreakdown,
|
|
38
|
+
TaxoraClient: () => TaxoraClient,
|
|
39
|
+
TaxoraClientFactory: () => TaxoraClientFactory,
|
|
40
|
+
TaxoraException: () => TaxoraException,
|
|
41
|
+
Token: () => Token,
|
|
42
|
+
ValidationException: () => ValidationException,
|
|
43
|
+
VatCertificateExport: () => VatCertificateExport,
|
|
44
|
+
VatCollection: () => VatCollection,
|
|
45
|
+
VatEndpoint: () => VatEndpoint,
|
|
46
|
+
VatResource: () => VatResource,
|
|
47
|
+
VatState: () => VatState,
|
|
48
|
+
VatValidationAddressInput: () => VatValidationAddressInput,
|
|
49
|
+
describeVatState: () => describeVatState,
|
|
50
|
+
getBaseUrl: () => getBaseUrl,
|
|
51
|
+
getFailedVatStates: () => getFailedVatStates
|
|
52
|
+
});
|
|
53
|
+
module.exports = __toCommonJS(index_exports);
|
|
54
|
+
|
|
55
|
+
// src/endpoints/AuthEndpoint.ts
|
|
56
|
+
var import_os = require("os");
|
|
57
|
+
|
|
58
|
+
// src/dto/Token.ts
|
|
59
|
+
var Token = class _Token {
|
|
60
|
+
constructor(accessToken, tokenType, expiresAt) {
|
|
61
|
+
this.accessToken = accessToken;
|
|
62
|
+
this.tokenType = tokenType;
|
|
63
|
+
this.expiresAt = expiresAt;
|
|
64
|
+
}
|
|
65
|
+
accessToken;
|
|
66
|
+
tokenType;
|
|
67
|
+
expiresAt;
|
|
68
|
+
isExpired(bufferSeconds = 15) {
|
|
69
|
+
return new Date(Date.now() + bufferSeconds * 1e3) >= this.expiresAt;
|
|
70
|
+
}
|
|
71
|
+
static fromArray(data) {
|
|
72
|
+
let accessToken = String(data["access_token"] ?? "");
|
|
73
|
+
if (accessToken.startsWith("Bearer ")) {
|
|
74
|
+
accessToken = accessToken.slice(7);
|
|
75
|
+
}
|
|
76
|
+
const tokenType = String(data["token_type"] ?? "Bearer");
|
|
77
|
+
const expiresIn = typeof data["expires_in"] === "number" ? data["expires_in"] : 3600;
|
|
78
|
+
const expiresAt = new Date(Date.now() + expiresIn * 1e3);
|
|
79
|
+
return new _Token(accessToken, tokenType, expiresAt);
|
|
80
|
+
}
|
|
81
|
+
toArray() {
|
|
82
|
+
return {
|
|
83
|
+
access_token: this.accessToken,
|
|
84
|
+
token_type: this.tokenType,
|
|
85
|
+
expires_at: this.expiresAt.toISOString()
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/enums/LoginIdentifier.ts
|
|
91
|
+
var LoginIdentifier = {
|
|
92
|
+
EMAIL: "email",
|
|
93
|
+
CLIENT_ID: "client_id"
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// src/exceptions/TaxoraException.ts
|
|
97
|
+
var TaxoraException = class extends Error {
|
|
98
|
+
context;
|
|
99
|
+
constructor(message, context = {}) {
|
|
100
|
+
super(message);
|
|
101
|
+
this.name = "TaxoraException";
|
|
102
|
+
this.context = context;
|
|
103
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// src/exceptions/AuthenticationException.ts
|
|
108
|
+
var AuthenticationException = class extends TaxoraException {
|
|
109
|
+
statusCode = 401;
|
|
110
|
+
constructor(message, context = {}) {
|
|
111
|
+
super(message, context);
|
|
112
|
+
this.name = "AuthenticationException";
|
|
113
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/exceptions/HttpException.ts
|
|
118
|
+
var HttpException = class extends TaxoraException {
|
|
119
|
+
statusCode;
|
|
120
|
+
responseBody;
|
|
121
|
+
constructor(message, statusCode, responseBody, context = {}) {
|
|
122
|
+
super(message, context);
|
|
123
|
+
this.name = "HttpException";
|
|
124
|
+
this.statusCode = statusCode;
|
|
125
|
+
this.responseBody = responseBody;
|
|
126
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
127
|
+
}
|
|
128
|
+
getStatusCode() {
|
|
129
|
+
return this.statusCode;
|
|
130
|
+
}
|
|
131
|
+
getResponseBody() {
|
|
132
|
+
return this.responseBody;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// src/endpoints/AuthEndpoint.ts
|
|
137
|
+
var AuthEndpoint = class {
|
|
138
|
+
constructor(baseUrl, apiKey, tokenStorage, httpClient) {
|
|
139
|
+
this.baseUrl = baseUrl;
|
|
140
|
+
this.apiKey = apiKey;
|
|
141
|
+
this.tokenStorage = tokenStorage;
|
|
142
|
+
this.httpClient = httpClient;
|
|
143
|
+
}
|
|
144
|
+
baseUrl;
|
|
145
|
+
apiKey;
|
|
146
|
+
tokenStorage;
|
|
147
|
+
httpClient;
|
|
148
|
+
async login(identifier, password, device, loginIdentifier = LoginIdentifier.EMAIL) {
|
|
149
|
+
const deviceName = device ?? (0, import_os.hostname)();
|
|
150
|
+
const body = {
|
|
151
|
+
identifier: loginIdentifier,
|
|
152
|
+
password,
|
|
153
|
+
device_name: deviceName
|
|
154
|
+
};
|
|
155
|
+
if (loginIdentifier === LoginIdentifier.CLIENT_ID) {
|
|
156
|
+
body["client_id"] = identifier;
|
|
157
|
+
} else {
|
|
158
|
+
body["email"] = identifier;
|
|
159
|
+
}
|
|
160
|
+
const response = await this.httpClient.request("POST", `${this.baseUrl}/auth/login`, {
|
|
161
|
+
headers: {
|
|
162
|
+
"Content-Type": "application/json",
|
|
163
|
+
"x-api-key": this.apiKey
|
|
164
|
+
},
|
|
165
|
+
body: JSON.stringify(body)
|
|
166
|
+
});
|
|
167
|
+
const responseText = await response.text();
|
|
168
|
+
if (response.status === 401) {
|
|
169
|
+
throw new AuthenticationException("Authentication failed: invalid credentials", {
|
|
170
|
+
status: 401,
|
|
171
|
+
body: responseText
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
throw new HttpException(`HTTP error ${response.status}`, response.status, responseText);
|
|
176
|
+
}
|
|
177
|
+
const data = this.parseResponse(responseText);
|
|
178
|
+
const token = Token.fromArray(data);
|
|
179
|
+
this.tokenStorage.set(token);
|
|
180
|
+
return token;
|
|
181
|
+
}
|
|
182
|
+
async loginWithClientId(clientId, password, device) {
|
|
183
|
+
return this.login(clientId, password, device, LoginIdentifier.CLIENT_ID);
|
|
184
|
+
}
|
|
185
|
+
async refresh() {
|
|
186
|
+
const storedToken = this.tokenStorage.get();
|
|
187
|
+
const headers = {
|
|
188
|
+
"Content-Type": "application/json",
|
|
189
|
+
"x-api-key": this.apiKey
|
|
190
|
+
};
|
|
191
|
+
if (storedToken) {
|
|
192
|
+
headers["Authorization"] = `Bearer ${storedToken.accessToken}`;
|
|
193
|
+
}
|
|
194
|
+
const response = await this.httpClient.request("POST", `${this.baseUrl}/auth/refresh`, { headers });
|
|
195
|
+
const responseText = await response.text();
|
|
196
|
+
if (response.status === 401) {
|
|
197
|
+
throw new AuthenticationException("Token refresh failed: unauthorized", { status: 401, body: responseText });
|
|
198
|
+
}
|
|
199
|
+
if (!response.ok) {
|
|
200
|
+
throw new HttpException(`HTTP error ${response.status}`, response.status, responseText);
|
|
201
|
+
}
|
|
202
|
+
const data = this.parseResponse(responseText);
|
|
203
|
+
const token = Token.fromArray(data);
|
|
204
|
+
this.tokenStorage.set(token);
|
|
205
|
+
return token;
|
|
206
|
+
}
|
|
207
|
+
parseResponse(responseText) {
|
|
208
|
+
let parsed;
|
|
209
|
+
try {
|
|
210
|
+
parsed = JSON.parse(responseText);
|
|
211
|
+
} catch {
|
|
212
|
+
throw new HttpException("Invalid JSON response", 0, responseText);
|
|
213
|
+
}
|
|
214
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
215
|
+
throw new HttpException("Unexpected response format", 0, responseText);
|
|
216
|
+
}
|
|
217
|
+
const obj = parsed;
|
|
218
|
+
if (obj["data"] !== void 0 && typeof obj["data"] === "object" && obj["data"] !== null) {
|
|
219
|
+
return obj["data"];
|
|
220
|
+
}
|
|
221
|
+
return obj;
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// src/endpoints/CompanyEndpoint.ts
|
|
226
|
+
var CompanyEndpoint = class {
|
|
227
|
+
constructor(baseUrl, apiKey, tokenStorage, httpClient) {
|
|
228
|
+
this.baseUrl = baseUrl;
|
|
229
|
+
this.apiKey = apiKey;
|
|
230
|
+
this.tokenStorage = tokenStorage;
|
|
231
|
+
this.httpClient = httpClient;
|
|
232
|
+
}
|
|
233
|
+
baseUrl;
|
|
234
|
+
apiKey;
|
|
235
|
+
tokenStorage;
|
|
236
|
+
httpClient;
|
|
237
|
+
async get() {
|
|
238
|
+
const headers = {
|
|
239
|
+
"Content-Type": "application/json",
|
|
240
|
+
"x-api-key": this.apiKey
|
|
241
|
+
};
|
|
242
|
+
const token = this.tokenStorage.get();
|
|
243
|
+
if (token) {
|
|
244
|
+
headers["Authorization"] = `Bearer ${token.accessToken}`;
|
|
245
|
+
}
|
|
246
|
+
const response = await this.httpClient.request("GET", `${this.baseUrl}/company`, { headers });
|
|
247
|
+
const responseText = await response.text();
|
|
248
|
+
if (!response.ok) {
|
|
249
|
+
throw new HttpException(`HTTP error ${response.status}`, response.status, responseText);
|
|
250
|
+
}
|
|
251
|
+
let parsed;
|
|
252
|
+
try {
|
|
253
|
+
parsed = JSON.parse(responseText);
|
|
254
|
+
} catch {
|
|
255
|
+
throw new HttpException("Invalid JSON response", 0, responseText);
|
|
256
|
+
}
|
|
257
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
258
|
+
throw new HttpException("Unexpected response format", 0, responseText);
|
|
259
|
+
}
|
|
260
|
+
const obj = parsed;
|
|
261
|
+
if (obj["data"] !== void 0 && typeof obj["data"] === "object" && obj["data"] !== null) {
|
|
262
|
+
return obj["data"];
|
|
263
|
+
}
|
|
264
|
+
return obj;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// src/enums/VatState.ts
|
|
269
|
+
var VatState = {
|
|
270
|
+
VALID: "valid",
|
|
271
|
+
INVALID: "invalid",
|
|
272
|
+
FRAUD: "fraud",
|
|
273
|
+
UNKNOWN: "unknown"
|
|
274
|
+
};
|
|
275
|
+
function getFailedVatStates() {
|
|
276
|
+
return [VatState.INVALID, VatState.FRAUD];
|
|
277
|
+
}
|
|
278
|
+
var DESCRIPTIONS = {
|
|
279
|
+
[VatState.VALID]: "The VAT number is valid and active.",
|
|
280
|
+
[VatState.INVALID]: "The VAT number is invalid or not registered.",
|
|
281
|
+
[VatState.FRAUD]: "The VAT number has been flagged as potentially fraudulent.",
|
|
282
|
+
[VatState.UNKNOWN]: "The VAT number state could not be determined."
|
|
283
|
+
};
|
|
284
|
+
function describeVatState(state) {
|
|
285
|
+
return DESCRIPTIONS[state];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/dto/CompanyAddress.ts
|
|
289
|
+
var CompanyAddress = class _CompanyAddress {
|
|
290
|
+
fullAddress;
|
|
291
|
+
name;
|
|
292
|
+
street;
|
|
293
|
+
postalCode;
|
|
294
|
+
city;
|
|
295
|
+
state;
|
|
296
|
+
country;
|
|
297
|
+
raw;
|
|
298
|
+
constructor(props) {
|
|
299
|
+
this.name = props.name ?? null;
|
|
300
|
+
this.street = props.street ?? null;
|
|
301
|
+
this.postalCode = props.postalCode ?? null;
|
|
302
|
+
this.city = props.city ?? null;
|
|
303
|
+
this.state = props.state ?? null;
|
|
304
|
+
this.country = props.country ?? null;
|
|
305
|
+
this.raw = props.raw ?? null;
|
|
306
|
+
this.fullAddress = props.fullAddress ?? this.assembleFullAddress();
|
|
307
|
+
}
|
|
308
|
+
assembleFullAddress() {
|
|
309
|
+
const parts = [this.street, this.postalCode, this.city, this.country].filter(Boolean);
|
|
310
|
+
return parts.length > 0 ? parts.join(", ") : null;
|
|
311
|
+
}
|
|
312
|
+
static from(value) {
|
|
313
|
+
if (value === null || value === void 0) return null;
|
|
314
|
+
if (typeof value === "string") {
|
|
315
|
+
const trimmed = value.trim();
|
|
316
|
+
if (!trimmed) return null;
|
|
317
|
+
try {
|
|
318
|
+
const parsed = JSON.parse(trimmed);
|
|
319
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
320
|
+
return _CompanyAddress.fromArray(parsed, trimmed);
|
|
321
|
+
}
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
324
|
+
return new _CompanyAddress({ raw: trimmed });
|
|
325
|
+
}
|
|
326
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
327
|
+
return _CompanyAddress.fromArray(value, null);
|
|
328
|
+
}
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
static fromArray(data, raw) {
|
|
332
|
+
const get = (key) => {
|
|
333
|
+
const val = data[key] ?? data[key.replace(/_/g, "-")];
|
|
334
|
+
return typeof val === "string" && val.trim() ? val.trim() : null;
|
|
335
|
+
};
|
|
336
|
+
return new _CompanyAddress({
|
|
337
|
+
fullAddress: get("full_address"),
|
|
338
|
+
name: get("name"),
|
|
339
|
+
street: get("street"),
|
|
340
|
+
postalCode: get("postal_code") ?? get("postalCode"),
|
|
341
|
+
city: get("city"),
|
|
342
|
+
state: get("state"),
|
|
343
|
+
country: get("country"),
|
|
344
|
+
raw
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
toArray() {
|
|
348
|
+
return {
|
|
349
|
+
full_address: this.fullAddress,
|
|
350
|
+
name: this.name,
|
|
351
|
+
street: this.street,
|
|
352
|
+
postal_code: this.postalCode,
|
|
353
|
+
city: this.city,
|
|
354
|
+
state: this.state,
|
|
355
|
+
country: this.country
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
toString() {
|
|
359
|
+
return this.fullAddress ?? this.raw ?? "";
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
// src/dto/ScoreBreakdown.ts
|
|
364
|
+
var ScoreBreakdown = class _ScoreBreakdown {
|
|
365
|
+
constructor(stepName, scoreContribution, metadata) {
|
|
366
|
+
this.stepName = stepName;
|
|
367
|
+
this.scoreContribution = scoreContribution;
|
|
368
|
+
this.metadata = metadata;
|
|
369
|
+
}
|
|
370
|
+
stepName;
|
|
371
|
+
scoreContribution;
|
|
372
|
+
metadata;
|
|
373
|
+
static fromArray(data) {
|
|
374
|
+
return new _ScoreBreakdown(
|
|
375
|
+
typeof data["step_name"] === "string" ? data["step_name"] : "",
|
|
376
|
+
typeof data["score_contribution"] === "number" ? data["score_contribution"] : 0,
|
|
377
|
+
data["metadata"] !== null && typeof data["metadata"] === "object" && !Array.isArray(data["metadata"]) ? data["metadata"] : {}
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
toArray() {
|
|
381
|
+
return {
|
|
382
|
+
step_name: this.stepName,
|
|
383
|
+
score_contribution: this.scoreContribution,
|
|
384
|
+
metadata: this.metadata
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// src/dto/ProviderDocumentLine.ts
|
|
390
|
+
var ProviderDocumentLine = class _ProviderDocumentLine {
|
|
391
|
+
constructor(id, vatUid, rowNumber, entryIdentifier, reference, meta) {
|
|
392
|
+
this.id = id;
|
|
393
|
+
this.vatUid = vatUid;
|
|
394
|
+
this.rowNumber = rowNumber;
|
|
395
|
+
this.entryIdentifier = entryIdentifier;
|
|
396
|
+
this.reference = reference;
|
|
397
|
+
this.meta = meta;
|
|
398
|
+
}
|
|
399
|
+
id;
|
|
400
|
+
vatUid;
|
|
401
|
+
rowNumber;
|
|
402
|
+
entryIdentifier;
|
|
403
|
+
reference;
|
|
404
|
+
meta;
|
|
405
|
+
static fromArray(data) {
|
|
406
|
+
if (data === null || data === void 0 || typeof data !== "object" || Array.isArray(data)) {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
const d = data;
|
|
410
|
+
return new _ProviderDocumentLine(
|
|
411
|
+
typeof d["id"] === "number" ? d["id"] : null,
|
|
412
|
+
typeof d["vat_uid"] === "string" ? d["vat_uid"] : null,
|
|
413
|
+
typeof d["row_number"] === "number" ? d["row_number"] : null,
|
|
414
|
+
typeof d["entry_identifier"] === "string" ? d["entry_identifier"] : null,
|
|
415
|
+
typeof d["reference"] === "string" ? d["reference"] : null,
|
|
416
|
+
d["meta"] !== null && typeof d["meta"] === "object" && !Array.isArray(d["meta"]) ? d["meta"] : {}
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
toArray() {
|
|
420
|
+
return {
|
|
421
|
+
id: this.id,
|
|
422
|
+
vat_uid: this.vatUid,
|
|
423
|
+
row_number: this.rowNumber,
|
|
424
|
+
entry_identifier: this.entryIdentifier,
|
|
425
|
+
reference: this.reference,
|
|
426
|
+
meta: this.meta
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
// src/dto/ProviderDocument.ts
|
|
432
|
+
var ProviderDocument = class _ProviderDocument {
|
|
433
|
+
constructor(id, provider, documentType, state, documentDate, mime, size, hash, meta, line) {
|
|
434
|
+
this.id = id;
|
|
435
|
+
this.provider = provider;
|
|
436
|
+
this.documentType = documentType;
|
|
437
|
+
this.state = state;
|
|
438
|
+
this.documentDate = documentDate;
|
|
439
|
+
this.mime = mime;
|
|
440
|
+
this.size = size;
|
|
441
|
+
this.hash = hash;
|
|
442
|
+
this.meta = meta;
|
|
443
|
+
this.line = line;
|
|
444
|
+
}
|
|
445
|
+
id;
|
|
446
|
+
provider;
|
|
447
|
+
documentType;
|
|
448
|
+
state;
|
|
449
|
+
documentDate;
|
|
450
|
+
mime;
|
|
451
|
+
size;
|
|
452
|
+
hash;
|
|
453
|
+
meta;
|
|
454
|
+
line;
|
|
455
|
+
static fromArray(data) {
|
|
456
|
+
if (data === null || data === void 0 || typeof data !== "object" || Array.isArray(data)) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const d = data;
|
|
460
|
+
const documentDate = typeof d["document_date"] === "string" && d["document_date"] ? new Date(d["document_date"]) : null;
|
|
461
|
+
return new _ProviderDocument(
|
|
462
|
+
typeof d["id"] === "number" ? d["id"] : null,
|
|
463
|
+
typeof d["provider"] === "string" ? d["provider"] : null,
|
|
464
|
+
typeof d["document_type"] === "string" ? d["document_type"] : null,
|
|
465
|
+
typeof d["state"] === "string" ? d["state"] : null,
|
|
466
|
+
documentDate,
|
|
467
|
+
typeof d["mime"] === "string" ? d["mime"] : null,
|
|
468
|
+
typeof d["size"] === "number" ? d["size"] : null,
|
|
469
|
+
typeof d["hash"] === "string" ? d["hash"] : null,
|
|
470
|
+
d["meta"] !== null && typeof d["meta"] === "object" && !Array.isArray(d["meta"]) ? d["meta"] : {},
|
|
471
|
+
ProviderDocumentLine.fromArray(d["line"])
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
toArray() {
|
|
475
|
+
return {
|
|
476
|
+
id: this.id,
|
|
477
|
+
provider: this.provider,
|
|
478
|
+
document_type: this.documentType,
|
|
479
|
+
state: this.state,
|
|
480
|
+
document_date: this.documentDate?.toISOString() ?? null,
|
|
481
|
+
mime: this.mime,
|
|
482
|
+
size: this.size,
|
|
483
|
+
hash: this.hash,
|
|
484
|
+
meta: this.meta,
|
|
485
|
+
line: this.line?.toArray() ?? null
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// src/dto/VatResource.ts
|
|
491
|
+
var VatResource = class _VatResource {
|
|
492
|
+
constructor(uuid, vatUid, state, countryCode, companyName, companyAddress, requestedCompanyName, requestedCompanyNameOriginal, requestedInputAddress, checkedAt, score, scoreSource, scoreAttempts, breakdown, environment, provider, usedProviders, providerVatState, providerNote, providerLastCheckedAt, providerDocument) {
|
|
493
|
+
this.uuid = uuid;
|
|
494
|
+
this.vatUid = vatUid;
|
|
495
|
+
this.state = state;
|
|
496
|
+
this.countryCode = countryCode;
|
|
497
|
+
this.companyName = companyName;
|
|
498
|
+
this.companyAddress = companyAddress;
|
|
499
|
+
this.requestedCompanyName = requestedCompanyName;
|
|
500
|
+
this.requestedCompanyNameOriginal = requestedCompanyNameOriginal;
|
|
501
|
+
this.requestedInputAddress = requestedInputAddress;
|
|
502
|
+
this.checkedAt = checkedAt;
|
|
503
|
+
this.score = score;
|
|
504
|
+
this.scoreSource = scoreSource;
|
|
505
|
+
this.scoreAttempts = scoreAttempts;
|
|
506
|
+
this.breakdown = breakdown;
|
|
507
|
+
this.environment = environment;
|
|
508
|
+
this.provider = provider;
|
|
509
|
+
this.usedProviders = usedProviders;
|
|
510
|
+
this.providerVatState = providerVatState;
|
|
511
|
+
this.providerNote = providerNote;
|
|
512
|
+
this.providerLastCheckedAt = providerLastCheckedAt;
|
|
513
|
+
this.providerDocument = providerDocument;
|
|
514
|
+
}
|
|
515
|
+
uuid;
|
|
516
|
+
vatUid;
|
|
517
|
+
state;
|
|
518
|
+
countryCode;
|
|
519
|
+
companyName;
|
|
520
|
+
companyAddress;
|
|
521
|
+
requestedCompanyName;
|
|
522
|
+
requestedCompanyNameOriginal;
|
|
523
|
+
requestedInputAddress;
|
|
524
|
+
checkedAt;
|
|
525
|
+
score;
|
|
526
|
+
scoreSource;
|
|
527
|
+
scoreAttempts;
|
|
528
|
+
breakdown;
|
|
529
|
+
environment;
|
|
530
|
+
provider;
|
|
531
|
+
usedProviders;
|
|
532
|
+
providerVatState;
|
|
533
|
+
providerNote;
|
|
534
|
+
providerLastCheckedAt;
|
|
535
|
+
providerDocument;
|
|
536
|
+
static fromArray(data) {
|
|
537
|
+
const str = (key) => {
|
|
538
|
+
const v = data[key];
|
|
539
|
+
return typeof v === "string" ? v : void 0;
|
|
540
|
+
};
|
|
541
|
+
const stateRaw = str("state");
|
|
542
|
+
const state = stateRaw !== void 0 && Object.values(VatState).includes(stateRaw) ? stateRaw : void 0;
|
|
543
|
+
const checkedAt = str("checked_at") ? new Date(data["checked_at"]) : void 0;
|
|
544
|
+
const providerLastCheckedAt = str("provider_last_checked_at") ? new Date(data["provider_last_checked_at"]) : void 0;
|
|
545
|
+
const breakdown = Array.isArray(data["breakdown"]) ? data["breakdown"].map(ScoreBreakdown.fromArray) : void 0;
|
|
546
|
+
const usedProviders = Array.isArray(data["used_providers"]) ? data["used_providers"].filter((v) => typeof v === "string") : void 0;
|
|
547
|
+
const scoreAttempts = Array.isArray(data["score_attempts"]) ? data["score_attempts"] : void 0;
|
|
548
|
+
const requestedInputAddress = data["requested_input_address"] !== null && typeof data["requested_input_address"] === "object" && !Array.isArray(data["requested_input_address"]) ? data["requested_input_address"] : void 0;
|
|
549
|
+
return new _VatResource(
|
|
550
|
+
str("uuid"),
|
|
551
|
+
str("vat_uid"),
|
|
552
|
+
state,
|
|
553
|
+
str("country_code"),
|
|
554
|
+
str("company_name"),
|
|
555
|
+
CompanyAddress.from(data["company_address"]) ?? void 0,
|
|
556
|
+
str("requested_company_name"),
|
|
557
|
+
str("requested_company_name_original"),
|
|
558
|
+
requestedInputAddress,
|
|
559
|
+
checkedAt,
|
|
560
|
+
typeof data["score"] === "number" ? data["score"] : void 0,
|
|
561
|
+
str("score_source"),
|
|
562
|
+
scoreAttempts,
|
|
563
|
+
breakdown,
|
|
564
|
+
str("environment"),
|
|
565
|
+
str("provider"),
|
|
566
|
+
usedProviders,
|
|
567
|
+
str("provider_vat_state"),
|
|
568
|
+
str("provider_note"),
|
|
569
|
+
providerLastCheckedAt,
|
|
570
|
+
ProviderDocument.fromArray(data["provider_document"]) ?? void 0
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
getBackendLink() {
|
|
574
|
+
if (!this.uuid) return null;
|
|
575
|
+
if (this.environment === "LIVE") {
|
|
576
|
+
return `https://app.taxora.io/vat/history/${this.uuid}`;
|
|
577
|
+
}
|
|
578
|
+
return `https://app.sandbox.taxora.io/vat/history/${this.uuid}`;
|
|
579
|
+
}
|
|
580
|
+
toArray() {
|
|
581
|
+
return {
|
|
582
|
+
uuid: this.uuid,
|
|
583
|
+
vat_uid: this.vatUid,
|
|
584
|
+
state: this.state,
|
|
585
|
+
country_code: this.countryCode,
|
|
586
|
+
company_name: this.companyName,
|
|
587
|
+
company_address: this.companyAddress?.toArray() ?? null,
|
|
588
|
+
requested_company_name: this.requestedCompanyName,
|
|
589
|
+
requested_company_name_original: this.requestedCompanyNameOriginal,
|
|
590
|
+
requested_input_address: this.requestedInputAddress ?? null,
|
|
591
|
+
checked_at: this.checkedAt?.toISOString() ?? null,
|
|
592
|
+
score: this.score ?? null,
|
|
593
|
+
score_source: this.scoreSource ?? null,
|
|
594
|
+
score_attempts: this.scoreAttempts ?? null,
|
|
595
|
+
breakdown: this.breakdown?.map((b) => b.toArray()) ?? null,
|
|
596
|
+
environment: this.environment ?? null,
|
|
597
|
+
provider: this.provider ?? null,
|
|
598
|
+
used_providers: this.usedProviders ?? null,
|
|
599
|
+
provider_vat_state: this.providerVatState ?? null,
|
|
600
|
+
provider_note: this.providerNote ?? null,
|
|
601
|
+
provider_last_checked_at: this.providerLastCheckedAt?.toISOString() ?? null,
|
|
602
|
+
provider_document: this.providerDocument?.toArray() ?? null
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
// src/dto/VatCollection.ts
|
|
608
|
+
var VatCollection = class _VatCollection {
|
|
609
|
+
items;
|
|
610
|
+
self;
|
|
611
|
+
constructor(items, self) {
|
|
612
|
+
this.items = items;
|
|
613
|
+
this.self = self;
|
|
614
|
+
}
|
|
615
|
+
static fromResponse(data) {
|
|
616
|
+
if (Array.isArray(data)) {
|
|
617
|
+
return new _VatCollection(data.map(VatResource.fromArray));
|
|
618
|
+
}
|
|
619
|
+
if (typeof data === "object" && data !== null) {
|
|
620
|
+
const obj = data;
|
|
621
|
+
const items = Array.isArray(obj["data"]) ? obj["data"].map(VatResource.fromArray) : [];
|
|
622
|
+
const self = typeof obj["self"] === "string" ? obj["self"] : void 0;
|
|
623
|
+
return new _VatCollection(items, self);
|
|
624
|
+
}
|
|
625
|
+
return new _VatCollection([]);
|
|
626
|
+
}
|
|
627
|
+
[Symbol.iterator]() {
|
|
628
|
+
return this.items[Symbol.iterator]();
|
|
629
|
+
}
|
|
630
|
+
get length() {
|
|
631
|
+
return this.items.length;
|
|
632
|
+
}
|
|
633
|
+
all() {
|
|
634
|
+
return [...this.items];
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// src/dto/VatCertificateExport.ts
|
|
639
|
+
var VatCertificateExport = class _VatCertificateExport {
|
|
640
|
+
constructor(exportId, message) {
|
|
641
|
+
this.exportId = exportId;
|
|
642
|
+
this.message = message;
|
|
643
|
+
}
|
|
644
|
+
exportId;
|
|
645
|
+
message;
|
|
646
|
+
static fromArray(data) {
|
|
647
|
+
return new _VatCertificateExport(
|
|
648
|
+
typeof data["export_id"] === "string" ? data["export_id"] : "",
|
|
649
|
+
typeof data["message"] === "string" ? data["message"] : void 0
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
toArray() {
|
|
653
|
+
const result = { export_id: this.exportId };
|
|
654
|
+
if (this.message !== void 0) result.message = this.message;
|
|
655
|
+
return result;
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// src/dto/VatValidationAddressInput.ts
|
|
660
|
+
var ALLOWED_KEYS = /* @__PURE__ */ new Set(["address_line_1", "address_line_2", "postal_code", "city", "country_code"]);
|
|
661
|
+
var VatValidationAddressInput = class _VatValidationAddressInput {
|
|
662
|
+
addressLine1;
|
|
663
|
+
addressLine2;
|
|
664
|
+
postalCode;
|
|
665
|
+
city;
|
|
666
|
+
countryCode;
|
|
667
|
+
constructor(props) {
|
|
668
|
+
if (props.addressLine1 !== void 0 && props.addressLine1.length > 255) {
|
|
669
|
+
throw new TaxoraException("addressLine1 must not exceed 255 characters");
|
|
670
|
+
}
|
|
671
|
+
if (props.addressLine2 !== void 0 && props.addressLine2.length > 255) {
|
|
672
|
+
throw new TaxoraException("addressLine2 must not exceed 255 characters");
|
|
673
|
+
}
|
|
674
|
+
if (props.countryCode !== void 0 && props.countryCode.length !== 2) {
|
|
675
|
+
throw new TaxoraException("countryCode must be exactly 2 characters (ISO 3166-1 alpha-2)");
|
|
676
|
+
}
|
|
677
|
+
this.addressLine1 = props.addressLine1;
|
|
678
|
+
this.addressLine2 = props.addressLine2;
|
|
679
|
+
this.postalCode = props.postalCode;
|
|
680
|
+
this.city = props.city;
|
|
681
|
+
this.countryCode = props.countryCode;
|
|
682
|
+
}
|
|
683
|
+
static fromArray(data) {
|
|
684
|
+
for (const key of Object.keys(data)) {
|
|
685
|
+
if (!ALLOWED_KEYS.has(key)) {
|
|
686
|
+
throw new TaxoraException(`Unsupported field: "${key}". Allowed fields: ${[...ALLOWED_KEYS].join(", ")}`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
const getString = (key) => {
|
|
690
|
+
const val = data[key];
|
|
691
|
+
if (typeof val !== "string") return void 0;
|
|
692
|
+
const trimmed = val.trim();
|
|
693
|
+
return trimmed || void 0;
|
|
694
|
+
};
|
|
695
|
+
const countryCode = getString("country_code");
|
|
696
|
+
return new _VatValidationAddressInput({
|
|
697
|
+
addressLine1: getString("address_line_1"),
|
|
698
|
+
addressLine2: getString("address_line_2"),
|
|
699
|
+
postalCode: getString("postal_code"),
|
|
700
|
+
city: getString("city"),
|
|
701
|
+
countryCode: countryCode ? countryCode.toUpperCase() : void 0
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
toArray() {
|
|
705
|
+
const result = {};
|
|
706
|
+
if (this.addressLine1 !== void 0) result["address_line_1"] = this.addressLine1;
|
|
707
|
+
if (this.addressLine2 !== void 0) result["address_line_2"] = this.addressLine2;
|
|
708
|
+
if (this.postalCode !== void 0) result["postal_code"] = this.postalCode;
|
|
709
|
+
if (this.city !== void 0) result["city"] = this.city;
|
|
710
|
+
if (this.countryCode !== void 0) result["country_code"] = this.countryCode;
|
|
711
|
+
return result;
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
|
|
715
|
+
// src/exceptions/ValidationException.ts
|
|
716
|
+
var ValidationException = class extends TaxoraException {
|
|
717
|
+
statusCode = 422;
|
|
718
|
+
errors;
|
|
719
|
+
constructor(message, errors, context = {}) {
|
|
720
|
+
super(message, context);
|
|
721
|
+
this.name = "ValidationException";
|
|
722
|
+
this.errors = errors;
|
|
723
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
724
|
+
}
|
|
725
|
+
getErrors() {
|
|
726
|
+
return this.errors;
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// src/endpoints/VatEndpoint.ts
|
|
731
|
+
var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
732
|
+
var VatEndpoint = class {
|
|
733
|
+
constructor(baseUrl, apiKey, tokenStorage, httpClient) {
|
|
734
|
+
this.baseUrl = baseUrl;
|
|
735
|
+
this.apiKey = apiKey;
|
|
736
|
+
this.tokenStorage = tokenStorage;
|
|
737
|
+
this.httpClient = httpClient;
|
|
738
|
+
}
|
|
739
|
+
baseUrl;
|
|
740
|
+
apiKey;
|
|
741
|
+
tokenStorage;
|
|
742
|
+
httpClient;
|
|
743
|
+
async validate(vatUid, companyName, provider, addressInput) {
|
|
744
|
+
const body = { vat_uid: vatUid };
|
|
745
|
+
if (companyName) body["company_name"] = companyName;
|
|
746
|
+
if (provider) body["source"] = provider;
|
|
747
|
+
if (addressInput) {
|
|
748
|
+
body["address_input"] = addressInput instanceof VatValidationAddressInput ? addressInput.toArray() : addressInput;
|
|
749
|
+
}
|
|
750
|
+
return this.validateWithGatewayRetry(body, 2);
|
|
751
|
+
}
|
|
752
|
+
async validateWithGatewayRetry(body, attemptsLeft) {
|
|
753
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/vat/validate`, body);
|
|
754
|
+
if (response.status === 504) {
|
|
755
|
+
if (attemptsLeft <= 1) {
|
|
756
|
+
const text = await response.text();
|
|
757
|
+
throw new HttpException("VAT validation timed out after multiple attempts", 504, text);
|
|
758
|
+
}
|
|
759
|
+
return this.validateWithGatewayRetry(body, attemptsLeft - 1);
|
|
760
|
+
}
|
|
761
|
+
const data = await this.parseJsonResponse(response);
|
|
762
|
+
return VatResource.fromArray(data);
|
|
763
|
+
}
|
|
764
|
+
async validateMultiple(vatUids, companyNames, provider) {
|
|
765
|
+
const body = { vat_uids: vatUids };
|
|
766
|
+
if (companyNames) body["company_names"] = companyNames;
|
|
767
|
+
if (provider) body["source"] = provider;
|
|
768
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/vat/validate/multiple`, body);
|
|
769
|
+
const data = await this.parseJsonResponse(response);
|
|
770
|
+
return VatCollection.fromResponse(data);
|
|
771
|
+
}
|
|
772
|
+
async validateSchema(vatUid) {
|
|
773
|
+
const body = { vat_uid: vatUid };
|
|
774
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/vat/validate/schema`, body);
|
|
775
|
+
return this.parseJsonResponse(response);
|
|
776
|
+
}
|
|
777
|
+
async state(vatUid) {
|
|
778
|
+
const response = await this.sendRequest("GET", `${this.baseUrl}/vat/state/${encodeURIComponent(vatUid)}`);
|
|
779
|
+
const data = await this.parseJsonResponse(response);
|
|
780
|
+
return VatResource.fromArray(data);
|
|
781
|
+
}
|
|
782
|
+
async history(vatUid) {
|
|
783
|
+
let url = `${this.baseUrl}/vat/history`;
|
|
784
|
+
if (vatUid) url += `?vat_uid=${encodeURIComponent(vatUid)}`;
|
|
785
|
+
const response = await this.sendRequest("GET", url);
|
|
786
|
+
const data = await this.parseJsonResponse(response);
|
|
787
|
+
return VatCollection.fromResponse(data);
|
|
788
|
+
}
|
|
789
|
+
async search(term, perPage) {
|
|
790
|
+
const params = new URLSearchParams();
|
|
791
|
+
if (term) params.set("term", term);
|
|
792
|
+
if (perPage !== void 0) params.set("per_page", String(perPage));
|
|
793
|
+
const queryString = params.toString();
|
|
794
|
+
const url = `${this.baseUrl}/vat/search${queryString ? `?${queryString}` : ""}`;
|
|
795
|
+
const response = await this.sendRequest("GET", url);
|
|
796
|
+
const data = await this.parseJsonResponse(response);
|
|
797
|
+
return VatCollection.fromResponse(data);
|
|
798
|
+
}
|
|
799
|
+
async certificate(uuid, lang) {
|
|
800
|
+
let url = `${this.baseUrl}/vat/certificate/${encodeURIComponent(uuid)}`;
|
|
801
|
+
if (lang) url += `?lang=${lang}`;
|
|
802
|
+
const response = await this.sendBinaryRequest("GET", url);
|
|
803
|
+
const buffer = await response.arrayBuffer();
|
|
804
|
+
return new Uint8Array(buffer);
|
|
805
|
+
}
|
|
806
|
+
async certificatesBulkExport(fromDate, toDate, countries, lang) {
|
|
807
|
+
return this.exportRequest(`${this.baseUrl}/vat/certificates/bulk-export`, fromDate, toDate, countries, lang);
|
|
808
|
+
}
|
|
809
|
+
async certificatesListExport(fromDate, toDate, countries, lang) {
|
|
810
|
+
return this.exportRequest(`${this.baseUrl}/vat/certificates/list-export`, fromDate, toDate, countries, lang);
|
|
811
|
+
}
|
|
812
|
+
async exportRequest(url, fromDate, toDate, countries, lang) {
|
|
813
|
+
const from = this.formatDate(fromDate);
|
|
814
|
+
const to = this.formatDate(toDate);
|
|
815
|
+
const body = { from_date: from, to_date: to };
|
|
816
|
+
if (countries && countries.length > 0) body["countries"] = countries;
|
|
817
|
+
if (lang) body["lang"] = lang;
|
|
818
|
+
const response = await this.sendRequest("POST", url, body);
|
|
819
|
+
const data = await this.parseJsonResponse(response, [200, 202]);
|
|
820
|
+
const exportObj = VatCertificateExport.fromArray(data);
|
|
821
|
+
if (!exportObj.exportId) {
|
|
822
|
+
throw new TaxoraException("Export response is missing export_id");
|
|
823
|
+
}
|
|
824
|
+
return exportObj;
|
|
825
|
+
}
|
|
826
|
+
async downloadBulkExport(exportId) {
|
|
827
|
+
const url = `${this.baseUrl}/vat/certificates/bulk-export/${encodeURIComponent(exportId)}/download`;
|
|
828
|
+
const response = await this.sendBinaryRequest("GET", url);
|
|
829
|
+
const buffer = await response.arrayBuffer();
|
|
830
|
+
return new Uint8Array(buffer);
|
|
831
|
+
}
|
|
832
|
+
buildHeaders() {
|
|
833
|
+
const headers = {
|
|
834
|
+
"Content-Type": "application/json",
|
|
835
|
+
"x-api-key": this.apiKey
|
|
836
|
+
};
|
|
837
|
+
const token = this.tokenStorage.get();
|
|
838
|
+
if (token) {
|
|
839
|
+
headers["Authorization"] = `Bearer ${token.accessToken}`;
|
|
840
|
+
}
|
|
841
|
+
return headers;
|
|
842
|
+
}
|
|
843
|
+
async sendRequest(method, url, body) {
|
|
844
|
+
const options = { headers: this.buildHeaders() };
|
|
845
|
+
if (body) options.body = JSON.stringify(body);
|
|
846
|
+
return this.httpClient.request(method, url, options);
|
|
847
|
+
}
|
|
848
|
+
async sendBinaryRequest(method, url) {
|
|
849
|
+
const headers = this.buildHeaders();
|
|
850
|
+
delete headers["Content-Type"];
|
|
851
|
+
const response = await this.httpClient.request(method, url, { headers });
|
|
852
|
+
if (!response.ok) {
|
|
853
|
+
const text = await response.text();
|
|
854
|
+
throw new HttpException(`HTTP error ${response.status}`, response.status, text);
|
|
855
|
+
}
|
|
856
|
+
return response;
|
|
857
|
+
}
|
|
858
|
+
async parseJsonResponse(response, acceptedStatuses = [200]) {
|
|
859
|
+
const responseText = await response.text();
|
|
860
|
+
if (response.status === 422) {
|
|
861
|
+
let errors = {};
|
|
862
|
+
try {
|
|
863
|
+
const parsed2 = JSON.parse(responseText);
|
|
864
|
+
if (parsed2["errors"] !== null && typeof parsed2["errors"] === "object" && !Array.isArray(parsed2["errors"])) {
|
|
865
|
+
errors = parsed2["errors"];
|
|
866
|
+
}
|
|
867
|
+
} catch {
|
|
868
|
+
}
|
|
869
|
+
throw new ValidationException("Validation failed", errors);
|
|
870
|
+
}
|
|
871
|
+
if (!response.ok && !acceptedStatuses.includes(response.status)) {
|
|
872
|
+
throw new HttpException(`HTTP error ${response.status}`, response.status, responseText);
|
|
873
|
+
}
|
|
874
|
+
let parsed;
|
|
875
|
+
try {
|
|
876
|
+
parsed = JSON.parse(responseText);
|
|
877
|
+
} catch {
|
|
878
|
+
throw new HttpException("Invalid JSON response", 0, responseText);
|
|
879
|
+
}
|
|
880
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
881
|
+
throw new HttpException("Unexpected response format", 0, responseText);
|
|
882
|
+
}
|
|
883
|
+
const obj = parsed;
|
|
884
|
+
if (obj["data"] !== void 0 && (typeof obj["data"] === "object" || Array.isArray(obj["data"]))) {
|
|
885
|
+
return obj["data"];
|
|
886
|
+
}
|
|
887
|
+
return obj;
|
|
888
|
+
}
|
|
889
|
+
formatDate(date) {
|
|
890
|
+
if (date instanceof Date) {
|
|
891
|
+
const year = date.getFullYear();
|
|
892
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
893
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
894
|
+
return `${year}-${month}-${day}`;
|
|
895
|
+
}
|
|
896
|
+
if (!DATE_REGEX.test(date)) {
|
|
897
|
+
throw new TaxoraException(`Invalid date format: "${date}". Expected YYYY-MM-DD.`);
|
|
898
|
+
}
|
|
899
|
+
return date;
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
// src/enums/Environment.ts
|
|
904
|
+
var Environment = {
|
|
905
|
+
SANDBOX: "sandbox",
|
|
906
|
+
PRODUCTION: "production"
|
|
907
|
+
};
|
|
908
|
+
var BASE_URLS = {
|
|
909
|
+
[Environment.SANDBOX]: "https://sandbox.taxora.io/v1",
|
|
910
|
+
[Environment.PRODUCTION]: "https://api.taxora.io/v1"
|
|
911
|
+
};
|
|
912
|
+
function getBaseUrl(environment) {
|
|
913
|
+
return BASE_URLS[environment];
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
// src/http/FetchHttpClient.ts
|
|
917
|
+
var FetchHttpClient = class {
|
|
918
|
+
async request(method, url, options = {}) {
|
|
919
|
+
return fetch(url, { ...options, method });
|
|
920
|
+
}
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
// src/http/InMemoryTokenStorage.ts
|
|
924
|
+
var InMemoryTokenStorage = class {
|
|
925
|
+
token = null;
|
|
926
|
+
get() {
|
|
927
|
+
return this.token;
|
|
928
|
+
}
|
|
929
|
+
set(token) {
|
|
930
|
+
this.token = token;
|
|
931
|
+
}
|
|
932
|
+
clear() {
|
|
933
|
+
this.token = null;
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
// src/http/AuthRetryHttpClient.ts
|
|
938
|
+
var AUTH_PATH_PATTERN = /\/auth\//;
|
|
939
|
+
var AuthRetryHttpClient = class {
|
|
940
|
+
constructor(inner, tokenStorage, refreshFn) {
|
|
941
|
+
this.inner = inner;
|
|
942
|
+
this.tokenStorage = tokenStorage;
|
|
943
|
+
this.refreshFn = refreshFn;
|
|
944
|
+
}
|
|
945
|
+
inner;
|
|
946
|
+
tokenStorage;
|
|
947
|
+
refreshFn;
|
|
948
|
+
async request(method, url, options) {
|
|
949
|
+
if (AUTH_PATH_PATTERN.test(url)) {
|
|
950
|
+
return this.inner.request(method, url, options);
|
|
951
|
+
}
|
|
952
|
+
const currentToken = this.tokenStorage.get();
|
|
953
|
+
if (currentToken?.isExpired()) {
|
|
954
|
+
await this.refreshFn();
|
|
955
|
+
}
|
|
956
|
+
const updatedOptions = this.injectAuthHeader(options);
|
|
957
|
+
const response = await this.inner.request(method, url, updatedOptions);
|
|
958
|
+
if (response.status === 401) {
|
|
959
|
+
await this.refreshFn();
|
|
960
|
+
const retryOptions = this.injectAuthHeader(options);
|
|
961
|
+
const retryResponse = await this.inner.request(method, url, retryOptions);
|
|
962
|
+
if (retryResponse.status === 401) {
|
|
963
|
+
const body = await retryResponse.text();
|
|
964
|
+
throw new AuthenticationException("Authentication failed after token refresh", { status: 401, body });
|
|
965
|
+
}
|
|
966
|
+
return retryResponse;
|
|
967
|
+
}
|
|
968
|
+
return response;
|
|
969
|
+
}
|
|
970
|
+
injectAuthHeader(options) {
|
|
971
|
+
const token = this.tokenStorage.get();
|
|
972
|
+
if (!token) return options ?? {};
|
|
973
|
+
const existing = options?.headers ?? {};
|
|
974
|
+
const headers = { ...existing, Authorization: `Bearer ${token.accessToken}` };
|
|
975
|
+
return { ...options ?? {}, headers };
|
|
976
|
+
}
|
|
977
|
+
};
|
|
978
|
+
|
|
979
|
+
// src/client/TaxoraClient.ts
|
|
980
|
+
var TaxoraClient = class {
|
|
981
|
+
auth;
|
|
982
|
+
vat;
|
|
983
|
+
company;
|
|
984
|
+
baseUrl;
|
|
985
|
+
constructor(options) {
|
|
986
|
+
const environment = options.environment ?? Environment.SANDBOX;
|
|
987
|
+
const tokenStorage = options.tokenStorage ?? new InMemoryTokenStorage();
|
|
988
|
+
const httpClient = options.httpClient ?? new FetchHttpClient();
|
|
989
|
+
this.baseUrl = getBaseUrl(environment);
|
|
990
|
+
this.auth = new AuthEndpoint(this.baseUrl, options.apiKey, tokenStorage, httpClient);
|
|
991
|
+
const retryClient = new AuthRetryHttpClient(httpClient, tokenStorage, () => this.auth.refresh());
|
|
992
|
+
this.vat = new VatEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient);
|
|
993
|
+
this.company = new CompanyEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient);
|
|
994
|
+
}
|
|
995
|
+
};
|
|
996
|
+
|
|
997
|
+
// src/client/TaxoraClientFactory.ts
|
|
998
|
+
var TaxoraClientFactory = class {
|
|
999
|
+
static create(options) {
|
|
1000
|
+
return new TaxoraClient(options);
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
// src/enums/ApiVersion.ts
|
|
1005
|
+
var ApiVersion = {
|
|
1006
|
+
V1: "v1"
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
// src/enums/Language.ts
|
|
1010
|
+
var Language = {
|
|
1011
|
+
ENGLISH: "en",
|
|
1012
|
+
GERMAN: "de"
|
|
1013
|
+
};
|
|
1014
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1015
|
+
0 && (module.exports = {
|
|
1016
|
+
ApiVersion,
|
|
1017
|
+
AuthEndpoint,
|
|
1018
|
+
AuthRetryHttpClient,
|
|
1019
|
+
AuthenticationException,
|
|
1020
|
+
CompanyAddress,
|
|
1021
|
+
CompanyEndpoint,
|
|
1022
|
+
Environment,
|
|
1023
|
+
FetchHttpClient,
|
|
1024
|
+
HttpException,
|
|
1025
|
+
InMemoryTokenStorage,
|
|
1026
|
+
Language,
|
|
1027
|
+
LoginIdentifier,
|
|
1028
|
+
ProviderDocument,
|
|
1029
|
+
ProviderDocumentLine,
|
|
1030
|
+
ScoreBreakdown,
|
|
1031
|
+
TaxoraClient,
|
|
1032
|
+
TaxoraClientFactory,
|
|
1033
|
+
TaxoraException,
|
|
1034
|
+
Token,
|
|
1035
|
+
ValidationException,
|
|
1036
|
+
VatCertificateExport,
|
|
1037
|
+
VatCollection,
|
|
1038
|
+
VatEndpoint,
|
|
1039
|
+
VatResource,
|
|
1040
|
+
VatState,
|
|
1041
|
+
VatValidationAddressInput,
|
|
1042
|
+
describeVatState,
|
|
1043
|
+
getBaseUrl,
|
|
1044
|
+
getFailedVatStates
|
|
1045
|
+
});
|
|
1046
|
+
//# sourceMappingURL=index.cjs.map
|