ksef-client-ts 0.1.1 → 0.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/README.md +13 -9
- package/dist/cli.js +40 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +4502 -3714
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -6
- package/dist/index.d.ts +177 -6
- package/dist/index.js +2640 -1868
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,1951 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
mod
|
|
32
32
|
));
|
|
33
33
|
|
|
34
|
+
// src/config/environments.ts
|
|
35
|
+
var Environment;
|
|
36
|
+
var init_environments = __esm({
|
|
37
|
+
"src/config/environments.ts"() {
|
|
38
|
+
"use strict";
|
|
39
|
+
Environment = {
|
|
40
|
+
TEST: {
|
|
41
|
+
apiUrl: "https://api-test.ksef.mf.gov.pl",
|
|
42
|
+
qrUrl: "https://qr-test.ksef.mf.gov.pl",
|
|
43
|
+
lighthouseUrl: "https://api-latarnia-test.ksef.mf.gov.pl"
|
|
44
|
+
},
|
|
45
|
+
DEMO: {
|
|
46
|
+
apiUrl: "https://api-demo.ksef.mf.gov.pl",
|
|
47
|
+
qrUrl: "https://qr-demo.ksef.mf.gov.pl",
|
|
48
|
+
lighthouseUrl: ""
|
|
49
|
+
},
|
|
50
|
+
PROD: {
|
|
51
|
+
apiUrl: "https://api.ksef.mf.gov.pl",
|
|
52
|
+
qrUrl: "https://qr.ksef.mf.gov.pl",
|
|
53
|
+
lighthouseUrl: "https://api-latarnia.ksef.mf.gov.pl"
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// src/config/options.ts
|
|
60
|
+
function resolveOptions(options = {}) {
|
|
61
|
+
const env = options.environment ? Environment[options.environment] : Environment.TEST;
|
|
62
|
+
return {
|
|
63
|
+
baseUrl: options.baseUrl ?? env.apiUrl,
|
|
64
|
+
baseQrUrl: options.baseQrUrl ?? env.qrUrl,
|
|
65
|
+
lighthouseUrl: options.lighthouseUrl ?? env.lighthouseUrl,
|
|
66
|
+
apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
|
|
67
|
+
timeout: options.timeout ?? DEFAULT_TIMEOUT,
|
|
68
|
+
customHeaders: options.customHeaders ?? {},
|
|
69
|
+
environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST")
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
var DEFAULT_API_VERSION, DEFAULT_TIMEOUT;
|
|
73
|
+
var init_options = __esm({
|
|
74
|
+
"src/config/options.ts"() {
|
|
75
|
+
"use strict";
|
|
76
|
+
init_environments();
|
|
77
|
+
DEFAULT_API_VERSION = "v2";
|
|
78
|
+
DEFAULT_TIMEOUT = 3e4;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// src/config/index.ts
|
|
83
|
+
var init_config = __esm({
|
|
84
|
+
"src/config/index.ts"() {
|
|
85
|
+
"use strict";
|
|
86
|
+
init_environments();
|
|
87
|
+
init_options();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// src/errors/ksef-error.ts
|
|
92
|
+
var KSeFError;
|
|
93
|
+
var init_ksef_error = __esm({
|
|
94
|
+
"src/errors/ksef-error.ts"() {
|
|
95
|
+
"use strict";
|
|
96
|
+
KSeFError = class extends Error {
|
|
97
|
+
constructor(message) {
|
|
98
|
+
super(message);
|
|
99
|
+
this.name = "KSeFError";
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// src/errors/ksef-api-error.ts
|
|
106
|
+
var KSeFApiError;
|
|
107
|
+
var init_ksef_api_error = __esm({
|
|
108
|
+
"src/errors/ksef-api-error.ts"() {
|
|
109
|
+
"use strict";
|
|
110
|
+
init_ksef_error();
|
|
111
|
+
KSeFApiError = class _KSeFApiError extends KSeFError {
|
|
112
|
+
statusCode;
|
|
113
|
+
errorResponse;
|
|
114
|
+
constructor(message, statusCode, errorResponse) {
|
|
115
|
+
super(message);
|
|
116
|
+
this.name = "KSeFApiError";
|
|
117
|
+
this.statusCode = statusCode;
|
|
118
|
+
this.errorResponse = errorResponse;
|
|
119
|
+
}
|
|
120
|
+
static fromResponse(statusCode, body) {
|
|
121
|
+
const details = body?.exception?.exceptionDetailList;
|
|
122
|
+
const message = details?.length ? details.map((d) => d.exceptionDescription ?? "").filter(Boolean).join("; ") || `KSeF API error: HTTP ${statusCode}` : `KSeF API error: HTTP ${statusCode}`;
|
|
123
|
+
return new _KSeFApiError(message, statusCode, body);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// src/errors/ksef-rate-limit-error.ts
|
|
130
|
+
var KSeFRateLimitError;
|
|
131
|
+
var init_ksef_rate_limit_error = __esm({
|
|
132
|
+
"src/errors/ksef-rate-limit-error.ts"() {
|
|
133
|
+
"use strict";
|
|
134
|
+
init_ksef_api_error();
|
|
135
|
+
KSeFRateLimitError = class _KSeFRateLimitError extends KSeFApiError {
|
|
136
|
+
retryAfterSeconds;
|
|
137
|
+
retryAfterDate;
|
|
138
|
+
recommendedDelay;
|
|
139
|
+
constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate) {
|
|
140
|
+
super(message, statusCode, errorResponse);
|
|
141
|
+
this.name = "KSeFRateLimitError";
|
|
142
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
143
|
+
this.retryAfterDate = retryAfterDate;
|
|
144
|
+
this.recommendedDelay = retryAfterSeconds ?? 60;
|
|
145
|
+
}
|
|
146
|
+
static fromRetryAfterHeader(statusCode, retryAfterHeader, body) {
|
|
147
|
+
let retryAfterSeconds;
|
|
148
|
+
let retryAfterDate;
|
|
149
|
+
if (retryAfterHeader) {
|
|
150
|
+
const seconds = Number(retryAfterHeader);
|
|
151
|
+
if (!Number.isNaN(seconds)) {
|
|
152
|
+
retryAfterSeconds = seconds;
|
|
153
|
+
} else {
|
|
154
|
+
const date = new Date(retryAfterHeader);
|
|
155
|
+
if (!Number.isNaN(date.getTime())) {
|
|
156
|
+
retryAfterDate = date;
|
|
157
|
+
retryAfterSeconds = Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1e3));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : "Rate limited by KSeF API";
|
|
162
|
+
return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// src/errors/ksef-unauthorized-error.ts
|
|
169
|
+
var KSeFUnauthorizedError;
|
|
170
|
+
var init_ksef_unauthorized_error = __esm({
|
|
171
|
+
"src/errors/ksef-unauthorized-error.ts"() {
|
|
172
|
+
"use strict";
|
|
173
|
+
init_ksef_error();
|
|
174
|
+
KSeFUnauthorizedError = class extends KSeFError {
|
|
175
|
+
statusCode = 401;
|
|
176
|
+
detail;
|
|
177
|
+
traceId;
|
|
178
|
+
instance;
|
|
179
|
+
constructor(problemDetails) {
|
|
180
|
+
super(problemDetails.detail || "Unauthorized");
|
|
181
|
+
this.name = "KSeFUnauthorizedError";
|
|
182
|
+
this.detail = problemDetails.detail;
|
|
183
|
+
this.traceId = problemDetails.traceId;
|
|
184
|
+
this.instance = problemDetails.instance;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// src/errors/ksef-forbidden-error.ts
|
|
191
|
+
var KSeFForbiddenError;
|
|
192
|
+
var init_ksef_forbidden_error = __esm({
|
|
193
|
+
"src/errors/ksef-forbidden-error.ts"() {
|
|
194
|
+
"use strict";
|
|
195
|
+
init_ksef_error();
|
|
196
|
+
KSeFForbiddenError = class extends KSeFError {
|
|
197
|
+
statusCode = 403;
|
|
198
|
+
detail;
|
|
199
|
+
reasonCode;
|
|
200
|
+
instance;
|
|
201
|
+
security;
|
|
202
|
+
traceId;
|
|
203
|
+
constructor(problemDetails) {
|
|
204
|
+
super(problemDetails.detail || "Forbidden");
|
|
205
|
+
this.name = "KSeFForbiddenError";
|
|
206
|
+
this.detail = problemDetails.detail;
|
|
207
|
+
this.reasonCode = problemDetails.reasonCode;
|
|
208
|
+
this.instance = problemDetails.instance;
|
|
209
|
+
this.security = problemDetails.security;
|
|
210
|
+
this.traceId = problemDetails.traceId;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// src/errors/ksef-auth-status-error.ts
|
|
217
|
+
var KSeFAuthStatusError;
|
|
218
|
+
var init_ksef_auth_status_error = __esm({
|
|
219
|
+
"src/errors/ksef-auth-status-error.ts"() {
|
|
220
|
+
"use strict";
|
|
221
|
+
init_ksef_error();
|
|
222
|
+
KSeFAuthStatusError = class extends KSeFError {
|
|
223
|
+
referenceNumber;
|
|
224
|
+
statusDescription;
|
|
225
|
+
constructor(message, referenceNumber, statusDescription) {
|
|
226
|
+
super(message);
|
|
227
|
+
this.name = "KSeFAuthStatusError";
|
|
228
|
+
this.referenceNumber = referenceNumber;
|
|
229
|
+
this.statusDescription = statusDescription;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// src/errors/ksef-session-expired-error.ts
|
|
236
|
+
var KSeFSessionExpiredError;
|
|
237
|
+
var init_ksef_session_expired_error = __esm({
|
|
238
|
+
"src/errors/ksef-session-expired-error.ts"() {
|
|
239
|
+
"use strict";
|
|
240
|
+
init_ksef_error();
|
|
241
|
+
KSeFSessionExpiredError = class extends KSeFError {
|
|
242
|
+
constructor(message = "KSeF session has expired") {
|
|
243
|
+
super(message);
|
|
244
|
+
this.name = "KSeFSessionExpiredError";
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// src/errors/ksef-validation-error.ts
|
|
251
|
+
var KSeFValidationError;
|
|
252
|
+
var init_ksef_validation_error = __esm({
|
|
253
|
+
"src/errors/ksef-validation-error.ts"() {
|
|
254
|
+
"use strict";
|
|
255
|
+
init_ksef_error();
|
|
256
|
+
KSeFValidationError = class _KSeFValidationError extends KSeFError {
|
|
257
|
+
details;
|
|
258
|
+
constructor(message, details = []) {
|
|
259
|
+
super(message);
|
|
260
|
+
this.name = "KSeFValidationError";
|
|
261
|
+
this.details = details;
|
|
262
|
+
}
|
|
263
|
+
static fromField(field, message) {
|
|
264
|
+
return new _KSeFValidationError(message, [{ field, message }]);
|
|
265
|
+
}
|
|
266
|
+
static fromMessages(messages) {
|
|
267
|
+
const details = messages.map((m) => ({ message: m }));
|
|
268
|
+
return new _KSeFValidationError(messages.join("; "), details);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// src/errors/index.ts
|
|
275
|
+
var init_errors = __esm({
|
|
276
|
+
"src/errors/index.ts"() {
|
|
277
|
+
"use strict";
|
|
278
|
+
init_ksef_error();
|
|
279
|
+
init_ksef_api_error();
|
|
280
|
+
init_ksef_rate_limit_error();
|
|
281
|
+
init_ksef_unauthorized_error();
|
|
282
|
+
init_ksef_forbidden_error();
|
|
283
|
+
init_ksef_auth_status_error();
|
|
284
|
+
init_ksef_session_expired_error();
|
|
285
|
+
init_ksef_validation_error();
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// src/http/route-builder.ts
|
|
290
|
+
var RouteBuilder;
|
|
291
|
+
var init_route_builder = __esm({
|
|
292
|
+
"src/http/route-builder.ts"() {
|
|
293
|
+
"use strict";
|
|
294
|
+
RouteBuilder = class {
|
|
295
|
+
apiVersion;
|
|
296
|
+
constructor(apiVersion) {
|
|
297
|
+
this.apiVersion = apiVersion;
|
|
298
|
+
}
|
|
299
|
+
build(endpoint, apiVersion) {
|
|
300
|
+
const version = apiVersion ?? this.apiVersion;
|
|
301
|
+
return `/${version}/${endpoint}`;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// src/http/rest-request.ts
|
|
308
|
+
var RestRequest;
|
|
309
|
+
var init_rest_request = __esm({
|
|
310
|
+
"src/http/rest-request.ts"() {
|
|
311
|
+
"use strict";
|
|
312
|
+
RestRequest = class _RestRequest {
|
|
313
|
+
method;
|
|
314
|
+
path;
|
|
315
|
+
_body;
|
|
316
|
+
_headers = {};
|
|
317
|
+
_query = [];
|
|
318
|
+
_presigned = false;
|
|
319
|
+
_skipAuthRetry = false;
|
|
320
|
+
constructor(method, path) {
|
|
321
|
+
this.method = method;
|
|
322
|
+
this.path = path;
|
|
323
|
+
}
|
|
324
|
+
static get(path) {
|
|
325
|
+
return new _RestRequest("GET", path);
|
|
326
|
+
}
|
|
327
|
+
static post(path) {
|
|
328
|
+
return new _RestRequest("POST", path);
|
|
329
|
+
}
|
|
330
|
+
static put(path) {
|
|
331
|
+
return new _RestRequest("PUT", path);
|
|
332
|
+
}
|
|
333
|
+
static delete(path) {
|
|
334
|
+
return new _RestRequest("DELETE", path);
|
|
335
|
+
}
|
|
336
|
+
body(data) {
|
|
337
|
+
this._body = data;
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
header(name, value) {
|
|
341
|
+
this._headers[name] = value;
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
headers(headers) {
|
|
345
|
+
Object.assign(this._headers, headers);
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
accessToken(token) {
|
|
349
|
+
this._headers["Authorization"] = `Bearer ${token}`;
|
|
350
|
+
return this;
|
|
351
|
+
}
|
|
352
|
+
query(key, value) {
|
|
353
|
+
this._query.push([key, value]);
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
presigned(flag = true) {
|
|
357
|
+
this._presigned = flag;
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
isPresigned() {
|
|
361
|
+
return this._presigned;
|
|
362
|
+
}
|
|
363
|
+
skipAuthRetry(flag = true) {
|
|
364
|
+
this._skipAuthRetry = flag;
|
|
365
|
+
return this;
|
|
366
|
+
}
|
|
367
|
+
isSkipAuthRetry() {
|
|
368
|
+
return this._skipAuthRetry;
|
|
369
|
+
}
|
|
370
|
+
getBody() {
|
|
371
|
+
return this._body;
|
|
372
|
+
}
|
|
373
|
+
getHeaders() {
|
|
374
|
+
return { ...this._headers };
|
|
375
|
+
}
|
|
376
|
+
getQuery() {
|
|
377
|
+
return [...this._query];
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// src/http/transport.ts
|
|
384
|
+
var defaultTransport;
|
|
385
|
+
var init_transport = __esm({
|
|
386
|
+
"src/http/transport.ts"() {
|
|
387
|
+
"use strict";
|
|
388
|
+
defaultTransport = (url, init) => fetch(url, init);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// src/http/retry-policy.ts
|
|
393
|
+
function defaultRetryPolicy() {
|
|
394
|
+
return {
|
|
395
|
+
maxRetries: 3,
|
|
396
|
+
baseDelayMs: 500,
|
|
397
|
+
maxDelayMs: 3e4,
|
|
398
|
+
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
399
|
+
retryNetworkErrors: true
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function calculateBackoff(attempt, policy) {
|
|
403
|
+
const exponential = policy.baseDelayMs * Math.pow(2, attempt);
|
|
404
|
+
const jitter = Math.random() * policy.baseDelayMs;
|
|
405
|
+
return Math.min(exponential + jitter, policy.maxDelayMs);
|
|
406
|
+
}
|
|
407
|
+
function parseRetryAfter(header) {
|
|
408
|
+
if (!header) return null;
|
|
409
|
+
const seconds = Number(header);
|
|
410
|
+
if (!Number.isNaN(seconds)) {
|
|
411
|
+
return seconds * 1e3;
|
|
412
|
+
}
|
|
413
|
+
const date = new Date(header);
|
|
414
|
+
if (!Number.isNaN(date.getTime())) {
|
|
415
|
+
return Math.max(0, date.getTime() - Date.now());
|
|
416
|
+
}
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
function isRetryableError(error, policy) {
|
|
420
|
+
if (!policy.retryNetworkErrors) return false;
|
|
421
|
+
if (!(error instanceof Error)) return false;
|
|
422
|
+
if (error.name === "AbortError") return true;
|
|
423
|
+
const code = error.code;
|
|
424
|
+
if (code && RETRYABLE_ERROR_CODES.has(code)) return true;
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
427
|
+
function isRetryableStatus(status, policy) {
|
|
428
|
+
return policy.retryableStatusCodes.includes(status);
|
|
429
|
+
}
|
|
430
|
+
function sleep(ms) {
|
|
431
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
432
|
+
}
|
|
433
|
+
var RETRYABLE_ERROR_CODES;
|
|
434
|
+
var init_retry_policy = __esm({
|
|
435
|
+
"src/http/retry-policy.ts"() {
|
|
436
|
+
"use strict";
|
|
437
|
+
RETRYABLE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
438
|
+
"ECONNRESET",
|
|
439
|
+
"ECONNREFUSED",
|
|
440
|
+
"ETIMEDOUT",
|
|
441
|
+
"UND_ERR_CONNECT_TIMEOUT"
|
|
442
|
+
]);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// src/http/presigned-url-policy.ts
|
|
447
|
+
function defaultPresignedUrlPolicy() {
|
|
448
|
+
return {
|
|
449
|
+
allowedHosts: ["*.ksef.mf.gov.pl"],
|
|
450
|
+
requireHttps: true,
|
|
451
|
+
blockRedirectParams: true,
|
|
452
|
+
rejectPrivateIps: true
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
function validatePresignedUrl(url, policy) {
|
|
456
|
+
const parsed = new URL(url);
|
|
457
|
+
if (policy.requireHttps && parsed.protocol !== "https:") {
|
|
458
|
+
throw new KSeFValidationError(`Presigned URL must use HTTPS: ${url}`);
|
|
459
|
+
}
|
|
460
|
+
if (!matchesAllowedHost(parsed.hostname, policy.allowedHosts)) {
|
|
461
|
+
throw new KSeFValidationError(
|
|
462
|
+
`Presigned URL host '${parsed.hostname}' is not in the allowed hosts list`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
if (policy.blockRedirectParams) {
|
|
466
|
+
checkRedirectParams(parsed, url);
|
|
467
|
+
}
|
|
468
|
+
if (policy.rejectPrivateIps) {
|
|
469
|
+
checkPrivateIp(parsed.hostname, url);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
function matchesAllowedHost(hostname, allowedHosts) {
|
|
473
|
+
for (const pattern of allowedHosts) {
|
|
474
|
+
if (pattern.startsWith("*.")) {
|
|
475
|
+
const suffix = pattern.slice(1);
|
|
476
|
+
if (hostname.endsWith(suffix) && hostname.length > suffix.length) {
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
} else if (hostname === pattern) {
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
function checkRedirectParams(parsed, originalUrl) {
|
|
486
|
+
for (const [key] of parsed.searchParams) {
|
|
487
|
+
if (BLOCKED_PARAMS.includes(key.toLowerCase())) {
|
|
488
|
+
throw new KSeFValidationError(
|
|
489
|
+
`Presigned URL contains blocked redirect parameter '${key}': ${originalUrl}`
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function checkPrivateIp(hostname, originalUrl) {
|
|
495
|
+
const host = hostname.startsWith("[") ? hostname.slice(1, -1) : hostname;
|
|
496
|
+
if (isPrivateIPv4(host) || isPrivateIPv6(host)) {
|
|
497
|
+
throw new KSeFValidationError(
|
|
498
|
+
`Presigned URL resolves to a private/reserved IP address '${hostname}': ${originalUrl}`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function isPrivateIPv4(ip) {
|
|
503
|
+
const parts = ip.split(".");
|
|
504
|
+
if (parts.length !== 4) return false;
|
|
505
|
+
const nums = parts.map(Number);
|
|
506
|
+
if (nums.some((n) => Number.isNaN(n))) return false;
|
|
507
|
+
const a = nums[0];
|
|
508
|
+
const b = nums[1];
|
|
509
|
+
if (a === 127) return true;
|
|
510
|
+
if (a === 10) return true;
|
|
511
|
+
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
512
|
+
if (a === 192 && b === 168) return true;
|
|
513
|
+
if (a === 169 && b === 254) return true;
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
function isPrivateIPv6(ip) {
|
|
517
|
+
const lower = ip.toLowerCase();
|
|
518
|
+
if (lower === "::1") return true;
|
|
519
|
+
if (lower.startsWith("fc") || lower.startsWith("fd")) return true;
|
|
520
|
+
if (lower.startsWith("fe8") || lower.startsWith("fe9") || lower.startsWith("fea") || lower.startsWith("feb")) return true;
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
var BLOCKED_PARAMS;
|
|
524
|
+
var init_presigned_url_policy = __esm({
|
|
525
|
+
"src/http/presigned-url-policy.ts"() {
|
|
526
|
+
"use strict";
|
|
527
|
+
init_ksef_validation_error();
|
|
528
|
+
BLOCKED_PARAMS = ["redirect", "callback", "return_url", "next"];
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// src/http/rest-client.ts
|
|
533
|
+
import { consola } from "consola";
|
|
534
|
+
var RestClient;
|
|
535
|
+
var init_rest_client = __esm({
|
|
536
|
+
"src/http/rest-client.ts"() {
|
|
537
|
+
"use strict";
|
|
538
|
+
init_ksef_api_error();
|
|
539
|
+
init_ksef_rate_limit_error();
|
|
540
|
+
init_ksef_unauthorized_error();
|
|
541
|
+
init_ksef_forbidden_error();
|
|
542
|
+
init_route_builder();
|
|
543
|
+
init_transport();
|
|
544
|
+
init_retry_policy();
|
|
545
|
+
init_presigned_url_policy();
|
|
546
|
+
RestClient = class {
|
|
547
|
+
options;
|
|
548
|
+
routeBuilder;
|
|
549
|
+
transport;
|
|
550
|
+
retryPolicy;
|
|
551
|
+
rateLimitPolicy;
|
|
552
|
+
authManager;
|
|
553
|
+
presignedUrlPolicy;
|
|
554
|
+
constructor(options, config) {
|
|
555
|
+
this.options = options;
|
|
556
|
+
this.routeBuilder = new RouteBuilder(options.apiVersion);
|
|
557
|
+
this.transport = config?.transport ?? defaultTransport;
|
|
558
|
+
this.retryPolicy = config?.retryPolicy ?? defaultRetryPolicy();
|
|
559
|
+
this.rateLimitPolicy = config?.rateLimitPolicy ?? null;
|
|
560
|
+
this.authManager = config?.authManager;
|
|
561
|
+
this.presignedUrlPolicy = config?.presignedUrlPolicy;
|
|
562
|
+
}
|
|
563
|
+
async execute(request) {
|
|
564
|
+
const response = await this.sendRequest(request);
|
|
565
|
+
await this.ensureSuccess(response);
|
|
566
|
+
const body = await response.json();
|
|
567
|
+
return { body, headers: response.headers, statusCode: response.status };
|
|
568
|
+
}
|
|
569
|
+
async executeVoid(request) {
|
|
570
|
+
const response = await this.sendRequest(request);
|
|
571
|
+
await this.ensureSuccess(response);
|
|
572
|
+
}
|
|
573
|
+
async executeRaw(request) {
|
|
574
|
+
const response = await this.sendRequest(request);
|
|
575
|
+
await this.ensureSuccess(response);
|
|
576
|
+
const body = await response.arrayBuffer();
|
|
577
|
+
return { body, headers: response.headers, statusCode: response.status };
|
|
578
|
+
}
|
|
579
|
+
async sendRequest(request) {
|
|
580
|
+
const url = this.buildUrl(request);
|
|
581
|
+
if (request.isPresigned() && this.presignedUrlPolicy) {
|
|
582
|
+
validatePresignedUrl(url, this.presignedUrlPolicy);
|
|
583
|
+
}
|
|
584
|
+
if (this.rateLimitPolicy) {
|
|
585
|
+
await this.rateLimitPolicy.acquire(request.path);
|
|
586
|
+
}
|
|
587
|
+
let lastError;
|
|
588
|
+
for (let attempt = 0; attempt <= this.retryPolicy.maxRetries; attempt++) {
|
|
589
|
+
try {
|
|
590
|
+
const response = await this.doRequest(request, url);
|
|
591
|
+
if (response.status === 401 && this.authManager && attempt === 0 && !request.isSkipAuthRetry()) {
|
|
592
|
+
const newToken = await this.authManager.onUnauthorized();
|
|
593
|
+
if (newToken) {
|
|
594
|
+
consola.debug("Auth token refreshed, retrying request");
|
|
595
|
+
return this.doRequest(request, url, newToken);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
if (isRetryableStatus(response.status, this.retryPolicy) && attempt < this.retryPolicy.maxRetries) {
|
|
599
|
+
const is429 = response.status === 429;
|
|
600
|
+
const retryAfterMs = is429 ? parseRetryAfter(response.headers.get("Retry-After")) : null;
|
|
601
|
+
const delayMs = retryAfterMs ?? calculateBackoff(attempt, this.retryPolicy);
|
|
602
|
+
consola.debug(`Retryable ${response.status}, attempt ${attempt + 1}/${this.retryPolicy.maxRetries}, waiting ${Math.round(delayMs)}ms`);
|
|
603
|
+
await sleep(delayMs);
|
|
604
|
+
if (is429 && this.rateLimitPolicy) {
|
|
605
|
+
await this.rateLimitPolicy.acquire(request.path);
|
|
606
|
+
}
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
return response;
|
|
610
|
+
} catch (error) {
|
|
611
|
+
lastError = error;
|
|
612
|
+
if (isRetryableError(error, this.retryPolicy) && attempt < this.retryPolicy.maxRetries) {
|
|
613
|
+
const delayMs = calculateBackoff(attempt, this.retryPolicy);
|
|
614
|
+
consola.debug(`Network error, attempt ${attempt + 1}/${this.retryPolicy.maxRetries}, waiting ${Math.round(delayMs)}ms`);
|
|
615
|
+
await sleep(delayMs);
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
throw lastError;
|
|
622
|
+
}
|
|
623
|
+
async doRequest(request, url, overrideToken) {
|
|
624
|
+
const headers = {
|
|
625
|
+
...this.options.customHeaders,
|
|
626
|
+
...request.getHeaders()
|
|
627
|
+
};
|
|
628
|
+
if (!headers["Authorization"] && this.authManager) {
|
|
629
|
+
const token = overrideToken ?? this.authManager.getAccessToken();
|
|
630
|
+
if (token) {
|
|
631
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const rawBody = request.getBody();
|
|
635
|
+
if (rawBody !== void 0 && !headers["Content-Type"]) {
|
|
636
|
+
headers["Content-Type"] = "application/json";
|
|
637
|
+
}
|
|
638
|
+
let body;
|
|
639
|
+
if (rawBody !== void 0) {
|
|
640
|
+
body = typeof rawBody === "string" ? rawBody : JSON.stringify(rawBody);
|
|
641
|
+
}
|
|
642
|
+
const start = performance.now();
|
|
643
|
+
const response = await this.transport(url, {
|
|
644
|
+
method: request.method,
|
|
645
|
+
headers,
|
|
646
|
+
body,
|
|
647
|
+
signal: AbortSignal.timeout(this.options.timeout)
|
|
648
|
+
});
|
|
649
|
+
const elapsed = Math.round(performance.now() - start);
|
|
650
|
+
consola.debug(`${request.method} ${url} \u2192 ${response.status} (${elapsed}ms)`);
|
|
651
|
+
return response;
|
|
652
|
+
}
|
|
653
|
+
buildUrl(request) {
|
|
654
|
+
const path = this.routeBuilder.build(request.path);
|
|
655
|
+
const base = this.options.baseUrl;
|
|
656
|
+
const url = new URL(`${base}${path}`);
|
|
657
|
+
const query = request.getQuery();
|
|
658
|
+
for (const [key, value] of query) {
|
|
659
|
+
url.searchParams.append(key, value);
|
|
660
|
+
}
|
|
661
|
+
return url.toString();
|
|
662
|
+
}
|
|
663
|
+
async ensureSuccess(response) {
|
|
664
|
+
if (response.ok) return;
|
|
665
|
+
const text = await response.text().catch(() => "");
|
|
666
|
+
const parseJson = () => {
|
|
667
|
+
try {
|
|
668
|
+
return JSON.parse(text);
|
|
669
|
+
} catch {
|
|
670
|
+
return void 0;
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
if (response.status === 429) {
|
|
674
|
+
const parsed = parseJson();
|
|
675
|
+
throw KSeFRateLimitError.fromRetryAfterHeader(
|
|
676
|
+
response.status,
|
|
677
|
+
response.headers.get("Retry-After"),
|
|
678
|
+
parsed
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
if (response.status === 401) {
|
|
682
|
+
const body = parseJson();
|
|
683
|
+
if (body?.detail) {
|
|
684
|
+
throw new KSeFUnauthorizedError(body);
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (response.status === 403) {
|
|
688
|
+
const body = parseJson();
|
|
689
|
+
if (body?.reasonCode) {
|
|
690
|
+
throw new KSeFForbiddenError(body);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
throw KSeFApiError.fromResponse(response.status, parseJson());
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
// src/http/routes.ts
|
|
700
|
+
var Routes;
|
|
701
|
+
var init_routes = __esm({
|
|
702
|
+
"src/http/routes.ts"() {
|
|
703
|
+
"use strict";
|
|
704
|
+
Routes = {
|
|
705
|
+
TestData: {
|
|
706
|
+
createSubject: "testdata/subject",
|
|
707
|
+
removeSubject: "testdata/subject/remove",
|
|
708
|
+
createPerson: "testdata/person",
|
|
709
|
+
removePerson: "testdata/person/remove",
|
|
710
|
+
grantPerms: "testdata/permissions",
|
|
711
|
+
revokePerms: "testdata/permissions/revoke",
|
|
712
|
+
enableAttach: "testdata/attachment",
|
|
713
|
+
disableAttach: "testdata/attachment/revoke",
|
|
714
|
+
changeSessionLimitsInCurrentContext: "testdata/limits/context/session",
|
|
715
|
+
restoreDefaultSessionLimitsInCurrentContext: "testdata/limits/context/session",
|
|
716
|
+
changeCertificatesLimitInCurrentSubject: "testdata/limits/subject/certificate",
|
|
717
|
+
restoreDefaultCertificatesLimitInCurrentSubject: "testdata/limits/subject/certificate",
|
|
718
|
+
rateLimits: "testdata/rate-limits",
|
|
719
|
+
productionRateLimits: "testdata/rate-limits/production",
|
|
720
|
+
blockContext: "testdata/context/block",
|
|
721
|
+
unblockContext: "testdata/context/unblock"
|
|
722
|
+
},
|
|
723
|
+
Limits: {
|
|
724
|
+
currentContext: "limits/context",
|
|
725
|
+
currentSubject: "limits/subject",
|
|
726
|
+
rateLimits: "rate-limits"
|
|
727
|
+
},
|
|
728
|
+
ActiveSessions: {
|
|
729
|
+
session: "auth/sessions",
|
|
730
|
+
delete: (ref) => `auth/sessions/${ref}`,
|
|
731
|
+
currentSession: "auth/sessions/current"
|
|
732
|
+
},
|
|
733
|
+
Authorization: {
|
|
734
|
+
challenge: "auth/challenge",
|
|
735
|
+
xadesSignature: "auth/xades-signature",
|
|
736
|
+
ksefToken: "auth/ksef-token",
|
|
737
|
+
status: (ref) => `auth/${ref}`,
|
|
738
|
+
Token: {
|
|
739
|
+
redeem: "auth/token/redeem",
|
|
740
|
+
refresh: "auth/token/refresh"
|
|
741
|
+
}
|
|
742
|
+
},
|
|
743
|
+
Sessions: {
|
|
744
|
+
root: "sessions",
|
|
745
|
+
byReference: (ref) => `sessions/${ref}`,
|
|
746
|
+
invoices: (ref) => `sessions/${ref}/invoices`,
|
|
747
|
+
invoice: (ref, invoiceRef) => `sessions/${ref}/invoices/${invoiceRef}`,
|
|
748
|
+
failedInvoices: (ref) => `sessions/${ref}/invoices/failed`,
|
|
749
|
+
upoByKsefNumber: (ref, ksefNumber) => `sessions/${ref}/invoices/ksef/${ksefNumber}/upo`,
|
|
750
|
+
upoByInvoiceReference: (ref, invoiceRef) => `sessions/${ref}/invoices/${invoiceRef}/upo`,
|
|
751
|
+
upo: (ref, upoRef) => `sessions/${ref}/upo/${upoRef}`,
|
|
752
|
+
Online: {
|
|
753
|
+
open: "sessions/online",
|
|
754
|
+
invoices: (sessionRef) => `sessions/online/${sessionRef}/invoices`,
|
|
755
|
+
close: (sessionRef) => `sessions/online/${sessionRef}/close`
|
|
756
|
+
},
|
|
757
|
+
Batch: {
|
|
758
|
+
open: "sessions/batch",
|
|
759
|
+
close: (batchRef) => `sessions/batch/${batchRef}/close`
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
Invoices: {
|
|
763
|
+
byKsefNumber: (ksefNumber) => `invoices/ksef/${ksefNumber}`,
|
|
764
|
+
queryMetadata: "invoices/query/metadata",
|
|
765
|
+
exports: "invoices/exports",
|
|
766
|
+
exportByReference: (ref) => `invoices/exports/${ref}`
|
|
767
|
+
},
|
|
768
|
+
Permissions: {
|
|
769
|
+
Grants: {
|
|
770
|
+
persons: "permissions/persons/grants",
|
|
771
|
+
entities: "permissions/entities/grants",
|
|
772
|
+
authorizations: "permissions/authorizations/grants",
|
|
773
|
+
indirect: "permissions/indirect/grants",
|
|
774
|
+
subunits: "permissions/subunits/grants",
|
|
775
|
+
euEntities: "permissions/eu-entities/administration/grants",
|
|
776
|
+
euEntitiesRepresentatives: "permissions/eu-entities/grants"
|
|
777
|
+
},
|
|
778
|
+
Common: {
|
|
779
|
+
grantById: (id) => `permissions/common/grants/${id}`
|
|
780
|
+
},
|
|
781
|
+
Authorizations: {
|
|
782
|
+
grantById: (id) => `permissions/authorizations/grants/${id}`
|
|
783
|
+
},
|
|
784
|
+
Query: {
|
|
785
|
+
personalGrants: "permissions/query/personal/grants",
|
|
786
|
+
personsGrants: "permissions/query/persons/grants",
|
|
787
|
+
subunitsGrants: "permissions/query/subunits/grants",
|
|
788
|
+
entitiesRoles: "permissions/query/entities/roles",
|
|
789
|
+
entitiesGrants: "permissions/query/entities/grants",
|
|
790
|
+
subordinateEntitiesRoles: "permissions/query/subordinate-entities/roles",
|
|
791
|
+
authorizationsGrants: "permissions/query/authorizations/grants",
|
|
792
|
+
euEntitiesGrants: "permissions/query/eu-entities/grants"
|
|
793
|
+
},
|
|
794
|
+
Operations: {
|
|
795
|
+
byReference: (ref) => `permissions/operations/${ref}`
|
|
796
|
+
},
|
|
797
|
+
Attachments: {
|
|
798
|
+
status: "permissions/attachments/status"
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
Certificates: {
|
|
802
|
+
limits: "certificates/limits",
|
|
803
|
+
enrollmentData: "certificates/enrollments/data",
|
|
804
|
+
enrollments: "certificates/enrollments",
|
|
805
|
+
enrollmentStatus: (ref) => `certificates/enrollments/${ref}`,
|
|
806
|
+
retrieve: "certificates/retrieve",
|
|
807
|
+
revoke: (serialNumber) => `certificates/${serialNumber}/revoke`,
|
|
808
|
+
query: "certificates/query"
|
|
809
|
+
},
|
|
810
|
+
Tokens: {
|
|
811
|
+
root: "tokens",
|
|
812
|
+
byReference: (ref) => `tokens/${ref}`
|
|
813
|
+
},
|
|
814
|
+
Peppol: {
|
|
815
|
+
query: "peppol/query"
|
|
816
|
+
},
|
|
817
|
+
Security: {
|
|
818
|
+
publicKeyCertificates: "security/public-key-certificates"
|
|
819
|
+
},
|
|
820
|
+
Lighthouse: {
|
|
821
|
+
status: "status",
|
|
822
|
+
messages: "messages"
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
// src/http/rate-limit-policy.ts
|
|
829
|
+
function defaultRateLimitPolicy() {
|
|
830
|
+
return new RateLimitPolicy({ globalRps: 10 });
|
|
831
|
+
}
|
|
832
|
+
var TokenBucket, RateLimitPolicy;
|
|
833
|
+
var init_rate_limit_policy = __esm({
|
|
834
|
+
"src/http/rate-limit-policy.ts"() {
|
|
835
|
+
"use strict";
|
|
836
|
+
TokenBucket = class {
|
|
837
|
+
tokens;
|
|
838
|
+
maxTokens;
|
|
839
|
+
refillRate;
|
|
840
|
+
// tokens per ms
|
|
841
|
+
lastRefill;
|
|
842
|
+
constructor(rps) {
|
|
843
|
+
this.maxTokens = rps;
|
|
844
|
+
this.tokens = rps;
|
|
845
|
+
this.refillRate = rps / 1e3;
|
|
846
|
+
this.lastRefill = Date.now();
|
|
847
|
+
}
|
|
848
|
+
async acquire() {
|
|
849
|
+
this.refill();
|
|
850
|
+
if (this.tokens >= 1) {
|
|
851
|
+
this.tokens -= 1;
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
const waitMs = Math.ceil((1 - this.tokens) / this.refillRate);
|
|
855
|
+
await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
856
|
+
this.refill();
|
|
857
|
+
this.tokens -= 1;
|
|
858
|
+
}
|
|
859
|
+
refill() {
|
|
860
|
+
const now = Date.now();
|
|
861
|
+
const elapsed = now - this.lastRefill;
|
|
862
|
+
this.tokens = Math.min(this.maxTokens, this.tokens + elapsed * this.refillRate);
|
|
863
|
+
this.lastRefill = now;
|
|
864
|
+
}
|
|
865
|
+
};
|
|
866
|
+
RateLimitPolicy = class {
|
|
867
|
+
globalBucket;
|
|
868
|
+
endpointBuckets = /* @__PURE__ */ new Map();
|
|
869
|
+
endpointLimits;
|
|
870
|
+
chain = Promise.resolve();
|
|
871
|
+
constructor(config) {
|
|
872
|
+
this.globalBucket = new TokenBucket(config.globalRps);
|
|
873
|
+
this.endpointLimits = config.endpointLimits ?? {};
|
|
874
|
+
}
|
|
875
|
+
async acquire(endpoint) {
|
|
876
|
+
return new Promise((resolve, reject) => {
|
|
877
|
+
this.chain = this.chain.then(() => this.doAcquire(endpoint)).then(resolve, reject);
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
async doAcquire(endpoint) {
|
|
881
|
+
await this.globalBucket.acquire();
|
|
882
|
+
const limit = this.endpointLimits[endpoint];
|
|
883
|
+
if (limit !== void 0) {
|
|
884
|
+
let bucket = this.endpointBuckets.get(endpoint);
|
|
885
|
+
if (!bucket) {
|
|
886
|
+
bucket = new TokenBucket(limit);
|
|
887
|
+
this.endpointBuckets.set(endpoint, bucket);
|
|
888
|
+
}
|
|
889
|
+
await bucket.acquire();
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
// src/http/auth-manager.ts
|
|
897
|
+
var DefaultAuthManager;
|
|
898
|
+
var init_auth_manager = __esm({
|
|
899
|
+
"src/http/auth-manager.ts"() {
|
|
900
|
+
"use strict";
|
|
901
|
+
DefaultAuthManager = class {
|
|
902
|
+
token;
|
|
903
|
+
refreshToken;
|
|
904
|
+
refreshFn;
|
|
905
|
+
refreshPromise = null;
|
|
906
|
+
constructor(refreshFn, initialToken) {
|
|
907
|
+
this.refreshFn = refreshFn;
|
|
908
|
+
this.token = initialToken;
|
|
909
|
+
}
|
|
910
|
+
getAccessToken() {
|
|
911
|
+
return this.token;
|
|
912
|
+
}
|
|
913
|
+
setAccessToken(token) {
|
|
914
|
+
this.token = token;
|
|
915
|
+
}
|
|
916
|
+
getRefreshToken() {
|
|
917
|
+
return this.refreshToken;
|
|
918
|
+
}
|
|
919
|
+
setRefreshToken(token) {
|
|
920
|
+
this.refreshToken = token;
|
|
921
|
+
}
|
|
922
|
+
async onUnauthorized() {
|
|
923
|
+
if (this.refreshPromise) return this.refreshPromise;
|
|
924
|
+
this.refreshPromise = this.refreshFn().then((newToken) => {
|
|
925
|
+
this.token = newToken ?? void 0;
|
|
926
|
+
return newToken;
|
|
927
|
+
}).finally(() => {
|
|
928
|
+
this.refreshPromise = null;
|
|
929
|
+
});
|
|
930
|
+
return this.refreshPromise;
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// src/http/ksef-feature.ts
|
|
937
|
+
var KSEF_FEATURE_HEADER, UpoVersion, ENFORCE_XADES_COMPLIANCE;
|
|
938
|
+
var init_ksef_feature = __esm({
|
|
939
|
+
"src/http/ksef-feature.ts"() {
|
|
940
|
+
"use strict";
|
|
941
|
+
KSEF_FEATURE_HEADER = "X-KSeF-Feature";
|
|
942
|
+
UpoVersion = {
|
|
943
|
+
/** UPO v4-2 format (default before 2026-01-05). */
|
|
944
|
+
V4_2: "upo-v4-2",
|
|
945
|
+
/** UPO v4-3 format (default from 2026-01-05, adds InvoicingMode field). */
|
|
946
|
+
V4_3: "upo-v4-3"
|
|
947
|
+
};
|
|
948
|
+
ENFORCE_XADES_COMPLIANCE = "enforce-xades-compliance";
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
// src/services/auth.ts
|
|
953
|
+
var AuthService;
|
|
954
|
+
var init_auth = __esm({
|
|
955
|
+
"src/services/auth.ts"() {
|
|
956
|
+
"use strict";
|
|
957
|
+
init_ksef_feature();
|
|
958
|
+
init_rest_request();
|
|
959
|
+
init_routes();
|
|
960
|
+
AuthService = class {
|
|
961
|
+
restClient;
|
|
962
|
+
constructor(restClient) {
|
|
963
|
+
this.restClient = restClient;
|
|
964
|
+
}
|
|
965
|
+
async getChallenge() {
|
|
966
|
+
const request = RestRequest.post(Routes.Authorization.challenge);
|
|
967
|
+
const response = await this.restClient.execute(request);
|
|
968
|
+
return response.body;
|
|
969
|
+
}
|
|
970
|
+
async submitXadesAuthRequest(signedXml, verifyCertificateChain = false, enforceXadesCompliance = false) {
|
|
971
|
+
const request = RestRequest.post(Routes.Authorization.xadesSignature).body(signedXml).header("Content-Type", "application/xml").query("verifyCertificateChain", String(verifyCertificateChain));
|
|
972
|
+
if (enforceXadesCompliance) {
|
|
973
|
+
request.header(KSEF_FEATURE_HEADER, ENFORCE_XADES_COMPLIANCE);
|
|
974
|
+
}
|
|
975
|
+
const response = await this.restClient.execute(request);
|
|
976
|
+
return response.body;
|
|
977
|
+
}
|
|
978
|
+
async submitKsefTokenAuthRequest(payload) {
|
|
979
|
+
const request = RestRequest.post(Routes.Authorization.ksefToken).body(payload);
|
|
980
|
+
const response = await this.restClient.execute(request);
|
|
981
|
+
return response.body;
|
|
982
|
+
}
|
|
983
|
+
async getAuthStatus(referenceNumber, authToken) {
|
|
984
|
+
const request = RestRequest.get(Routes.Authorization.status(referenceNumber)).accessToken(authToken);
|
|
985
|
+
const response = await this.restClient.execute(request);
|
|
986
|
+
return response.body;
|
|
987
|
+
}
|
|
988
|
+
async getAccessToken(authToken) {
|
|
989
|
+
const request = RestRequest.post(Routes.Authorization.Token.redeem).accessToken(authToken);
|
|
990
|
+
const response = await this.restClient.execute(request);
|
|
991
|
+
return response.body;
|
|
992
|
+
}
|
|
993
|
+
async refreshAccessToken(refreshToken) {
|
|
994
|
+
const request = RestRequest.post(Routes.Authorization.Token.refresh).accessToken(refreshToken).skipAuthRetry();
|
|
995
|
+
const response = await this.restClient.execute(request);
|
|
996
|
+
return response.body;
|
|
997
|
+
}
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
|
|
1002
|
+
// src/services/active-sessions.ts
|
|
1003
|
+
var ActiveSessionsService;
|
|
1004
|
+
var init_active_sessions = __esm({
|
|
1005
|
+
"src/services/active-sessions.ts"() {
|
|
1006
|
+
"use strict";
|
|
1007
|
+
init_rest_request();
|
|
1008
|
+
init_routes();
|
|
1009
|
+
ActiveSessionsService = class {
|
|
1010
|
+
restClient;
|
|
1011
|
+
constructor(restClient) {
|
|
1012
|
+
this.restClient = restClient;
|
|
1013
|
+
}
|
|
1014
|
+
async getActiveSessions(pageSize, continuationToken) {
|
|
1015
|
+
const request = RestRequest.get(Routes.ActiveSessions.session);
|
|
1016
|
+
if (pageSize !== void 0) request.query("pageSize", String(pageSize));
|
|
1017
|
+
if (continuationToken !== void 0) request.header("x-continuation-token", continuationToken);
|
|
1018
|
+
const response = await this.restClient.execute(request);
|
|
1019
|
+
return response.body;
|
|
1020
|
+
}
|
|
1021
|
+
async revokeCurrentSession() {
|
|
1022
|
+
const request = RestRequest.delete(Routes.ActiveSessions.currentSession);
|
|
1023
|
+
await this.restClient.executeVoid(request);
|
|
1024
|
+
}
|
|
1025
|
+
async revokeSession(sessionRef) {
|
|
1026
|
+
const request = RestRequest.delete(Routes.ActiveSessions.delete(sessionRef));
|
|
1027
|
+
await this.restClient.executeVoid(request);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
// src/services/online-session.ts
|
|
1034
|
+
var OnlineSessionService;
|
|
1035
|
+
var init_online_session = __esm({
|
|
1036
|
+
"src/services/online-session.ts"() {
|
|
1037
|
+
"use strict";
|
|
1038
|
+
init_ksef_feature();
|
|
1039
|
+
init_rest_request();
|
|
1040
|
+
init_routes();
|
|
1041
|
+
OnlineSessionService = class {
|
|
1042
|
+
restClient;
|
|
1043
|
+
constructor(restClient) {
|
|
1044
|
+
this.restClient = restClient;
|
|
1045
|
+
}
|
|
1046
|
+
async openSession(request, upoVersion) {
|
|
1047
|
+
const req = RestRequest.post(Routes.Sessions.Online.open).body(request);
|
|
1048
|
+
if (upoVersion) {
|
|
1049
|
+
req.header(KSEF_FEATURE_HEADER, upoVersion);
|
|
1050
|
+
}
|
|
1051
|
+
const response = await this.restClient.execute(req);
|
|
1052
|
+
return response.body;
|
|
1053
|
+
}
|
|
1054
|
+
async sendInvoice(sessionRef, request) {
|
|
1055
|
+
const req = RestRequest.post(Routes.Sessions.Online.invoices(sessionRef)).body(request);
|
|
1056
|
+
const response = await this.restClient.execute(req);
|
|
1057
|
+
return response.body;
|
|
1058
|
+
}
|
|
1059
|
+
async closeSession(sessionRef) {
|
|
1060
|
+
const req = RestRequest.post(Routes.Sessions.Online.close(sessionRef));
|
|
1061
|
+
await this.restClient.executeVoid(req);
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
// src/services/batch-session.ts
|
|
1068
|
+
var BatchSessionService;
|
|
1069
|
+
var init_batch_session = __esm({
|
|
1070
|
+
"src/services/batch-session.ts"() {
|
|
1071
|
+
"use strict";
|
|
1072
|
+
init_ksef_feature();
|
|
1073
|
+
init_rest_request();
|
|
1074
|
+
init_routes();
|
|
1075
|
+
BatchSessionService = class {
|
|
1076
|
+
restClient;
|
|
1077
|
+
constructor(restClient) {
|
|
1078
|
+
this.restClient = restClient;
|
|
1079
|
+
}
|
|
1080
|
+
async openSession(request, upoVersion) {
|
|
1081
|
+
const req = RestRequest.post(Routes.Sessions.Batch.open).body(request);
|
|
1082
|
+
if (upoVersion) {
|
|
1083
|
+
req.header(KSEF_FEATURE_HEADER, upoVersion);
|
|
1084
|
+
}
|
|
1085
|
+
const response = await this.restClient.execute(req);
|
|
1086
|
+
return response.body;
|
|
1087
|
+
}
|
|
1088
|
+
async sendParts(openResponse, parts) {
|
|
1089
|
+
const uploadRequests = openResponse.partUploadRequests;
|
|
1090
|
+
const tasks = parts.map(async (part) => {
|
|
1091
|
+
const uploadReq = uploadRequests.find(
|
|
1092
|
+
(r) => r.ordinalNumber === part.ordinalNumber
|
|
1093
|
+
);
|
|
1094
|
+
if (!uploadReq) {
|
|
1095
|
+
throw new Error(`No upload request found for part ${part.ordinalNumber}`);
|
|
1096
|
+
}
|
|
1097
|
+
const headers = {};
|
|
1098
|
+
for (const [k, v] of Object.entries(uploadReq.headers)) {
|
|
1099
|
+
if (v != null) headers[k] = v;
|
|
1100
|
+
}
|
|
1101
|
+
await fetch(uploadReq.url, {
|
|
1102
|
+
method: uploadReq.method,
|
|
1103
|
+
headers,
|
|
1104
|
+
body: part.data
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
await Promise.all(tasks);
|
|
1108
|
+
}
|
|
1109
|
+
async closeSession(batchRef) {
|
|
1110
|
+
const req = RestRequest.post(Routes.Sessions.Batch.close(batchRef));
|
|
1111
|
+
await this.restClient.executeVoid(req);
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
// src/services/session-status.ts
|
|
1118
|
+
var SessionStatusService;
|
|
1119
|
+
var init_session_status = __esm({
|
|
1120
|
+
"src/services/session-status.ts"() {
|
|
1121
|
+
"use strict";
|
|
1122
|
+
init_rest_request();
|
|
1123
|
+
init_routes();
|
|
1124
|
+
SessionStatusService = class {
|
|
1125
|
+
restClient;
|
|
1126
|
+
constructor(restClient) {
|
|
1127
|
+
this.restClient = restClient;
|
|
1128
|
+
}
|
|
1129
|
+
async getSessions(type, pageSize, continuationToken, filter) {
|
|
1130
|
+
const req = RestRequest.get(Routes.Sessions.root);
|
|
1131
|
+
req.query("sessionType", type);
|
|
1132
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1133
|
+
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
1134
|
+
if (filter) {
|
|
1135
|
+
if (filter.referenceNumber) req.query("referenceNumber", filter.referenceNumber);
|
|
1136
|
+
if (filter.dateCreatedFrom) req.query("dateCreatedFrom", filter.dateCreatedFrom);
|
|
1137
|
+
if (filter.dateCreatedTo) req.query("dateCreatedTo", filter.dateCreatedTo);
|
|
1138
|
+
if (filter.dateClosedFrom) req.query("dateClosedFrom", filter.dateClosedFrom);
|
|
1139
|
+
if (filter.dateClosedTo) req.query("dateClosedTo", filter.dateClosedTo);
|
|
1140
|
+
if (filter.dateModifiedFrom) req.query("dateModifiedFrom", filter.dateModifiedFrom);
|
|
1141
|
+
if (filter.dateModifiedTo) req.query("dateModifiedTo", filter.dateModifiedTo);
|
|
1142
|
+
if (filter.statuses) {
|
|
1143
|
+
for (const status of filter.statuses) {
|
|
1144
|
+
req.query("statuses", status);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
const response = await this.restClient.execute(req);
|
|
1149
|
+
return response.body;
|
|
1150
|
+
}
|
|
1151
|
+
async getSessionStatus(sessionRef) {
|
|
1152
|
+
const req = RestRequest.get(Routes.Sessions.byReference(sessionRef));
|
|
1153
|
+
const response = await this.restClient.execute(req);
|
|
1154
|
+
return response.body;
|
|
1155
|
+
}
|
|
1156
|
+
async getSessionInvoices(sessionRef, pageSize, continuationToken) {
|
|
1157
|
+
const req = RestRequest.get(Routes.Sessions.invoices(sessionRef));
|
|
1158
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1159
|
+
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
1160
|
+
const response = await this.restClient.execute(req);
|
|
1161
|
+
return response.body;
|
|
1162
|
+
}
|
|
1163
|
+
async getSessionInvoice(sessionRef, invoiceRef) {
|
|
1164
|
+
const req = RestRequest.get(Routes.Sessions.invoice(sessionRef, invoiceRef));
|
|
1165
|
+
const response = await this.restClient.execute(req);
|
|
1166
|
+
return response.body;
|
|
1167
|
+
}
|
|
1168
|
+
async getSessionFailedInvoices(sessionRef, pageSize, continuationToken) {
|
|
1169
|
+
const req = RestRequest.get(Routes.Sessions.failedInvoices(sessionRef));
|
|
1170
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1171
|
+
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
1172
|
+
const response = await this.restClient.execute(req);
|
|
1173
|
+
return response.body;
|
|
1174
|
+
}
|
|
1175
|
+
async getInvoiceUpoByKsefNumber(sessionRef, ksefNumber) {
|
|
1176
|
+
const req = RestRequest.get(Routes.Sessions.upoByKsefNumber(sessionRef, ksefNumber));
|
|
1177
|
+
const response = await this.restClient.executeRaw(req);
|
|
1178
|
+
return {
|
|
1179
|
+
upo: new TextDecoder().decode(response.body),
|
|
1180
|
+
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
async getInvoiceUpoByReference(sessionRef, invoiceRef) {
|
|
1184
|
+
const req = RestRequest.get(Routes.Sessions.upoByInvoiceReference(sessionRef, invoiceRef));
|
|
1185
|
+
const response = await this.restClient.executeRaw(req);
|
|
1186
|
+
return {
|
|
1187
|
+
upo: new TextDecoder().decode(response.body),
|
|
1188
|
+
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
async getSessionUpo(sessionRef, upoRef) {
|
|
1192
|
+
const req = RestRequest.get(Routes.Sessions.upo(sessionRef, upoRef));
|
|
1193
|
+
const response = await this.restClient.executeRaw(req);
|
|
1194
|
+
return {
|
|
1195
|
+
upo: new TextDecoder().decode(response.body),
|
|
1196
|
+
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
// src/services/invoice-download.ts
|
|
1204
|
+
var InvoiceDownloadService;
|
|
1205
|
+
var init_invoice_download = __esm({
|
|
1206
|
+
"src/services/invoice-download.ts"() {
|
|
1207
|
+
"use strict";
|
|
1208
|
+
init_rest_request();
|
|
1209
|
+
init_routes();
|
|
1210
|
+
InvoiceDownloadService = class {
|
|
1211
|
+
restClient;
|
|
1212
|
+
constructor(restClient) {
|
|
1213
|
+
this.restClient = restClient;
|
|
1214
|
+
}
|
|
1215
|
+
async getInvoice(ksefNumber) {
|
|
1216
|
+
const req = RestRequest.get(Routes.Invoices.byKsefNumber(ksefNumber));
|
|
1217
|
+
const response = await this.restClient.executeRaw(req);
|
|
1218
|
+
return new TextDecoder().decode(response.body);
|
|
1219
|
+
}
|
|
1220
|
+
async queryInvoiceMetadata(filters, pageOffset, pageSize, sortOrder) {
|
|
1221
|
+
const req = RestRequest.post(Routes.Invoices.queryMetadata).body(filters);
|
|
1222
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1223
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1224
|
+
if (sortOrder !== void 0) req.query("sortOrder", sortOrder);
|
|
1225
|
+
const response = await this.restClient.execute(req);
|
|
1226
|
+
return response.body;
|
|
1227
|
+
}
|
|
1228
|
+
async exportInvoices(request) {
|
|
1229
|
+
const req = RestRequest.post(Routes.Invoices.exports).body(request);
|
|
1230
|
+
const response = await this.restClient.execute(req);
|
|
1231
|
+
return response.body;
|
|
1232
|
+
}
|
|
1233
|
+
async getInvoiceExportStatus(ref) {
|
|
1234
|
+
const req = RestRequest.get(Routes.Invoices.exportByReference(ref));
|
|
1235
|
+
const response = await this.restClient.execute(req);
|
|
1236
|
+
return response.body;
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
|
|
1242
|
+
// src/services/permissions.ts
|
|
1243
|
+
var PermissionsService;
|
|
1244
|
+
var init_permissions = __esm({
|
|
1245
|
+
"src/services/permissions.ts"() {
|
|
1246
|
+
"use strict";
|
|
1247
|
+
init_rest_request();
|
|
1248
|
+
init_routes();
|
|
1249
|
+
PermissionsService = class {
|
|
1250
|
+
restClient;
|
|
1251
|
+
constructor(restClient) {
|
|
1252
|
+
this.restClient = restClient;
|
|
1253
|
+
}
|
|
1254
|
+
// Grant methods
|
|
1255
|
+
async grantPersonPermissions(request) {
|
|
1256
|
+
const req = RestRequest.post(Routes.Permissions.Grants.persons).body(request);
|
|
1257
|
+
const response = await this.restClient.execute(req);
|
|
1258
|
+
return response.body;
|
|
1259
|
+
}
|
|
1260
|
+
async grantEntityPermissions(request) {
|
|
1261
|
+
const req = RestRequest.post(Routes.Permissions.Grants.entities).body(request);
|
|
1262
|
+
const response = await this.restClient.execute(req);
|
|
1263
|
+
return response.body;
|
|
1264
|
+
}
|
|
1265
|
+
async grantAuthorizationPermissions(request) {
|
|
1266
|
+
const req = RestRequest.post(Routes.Permissions.Grants.authorizations).body(request);
|
|
1267
|
+
const response = await this.restClient.execute(req);
|
|
1268
|
+
return response.body;
|
|
1269
|
+
}
|
|
1270
|
+
async grantIndirectPermissions(request) {
|
|
1271
|
+
const req = RestRequest.post(Routes.Permissions.Grants.indirect).body(request);
|
|
1272
|
+
const response = await this.restClient.execute(req);
|
|
1273
|
+
return response.body;
|
|
1274
|
+
}
|
|
1275
|
+
async grantSubunitPermissions(request) {
|
|
1276
|
+
const req = RestRequest.post(Routes.Permissions.Grants.subunits).body(request);
|
|
1277
|
+
const response = await this.restClient.execute(req);
|
|
1278
|
+
return response.body;
|
|
1279
|
+
}
|
|
1280
|
+
async grantEuEntityAdminPermissions(request) {
|
|
1281
|
+
const req = RestRequest.post(Routes.Permissions.Grants.euEntities).body(request);
|
|
1282
|
+
const response = await this.restClient.execute(req);
|
|
1283
|
+
return response.body;
|
|
1284
|
+
}
|
|
1285
|
+
/** @deprecated Use grantEuEntityAdminPermissions instead */
|
|
1286
|
+
async grantEuEntityPermissions(request) {
|
|
1287
|
+
return this.grantEuEntityAdminPermissions(request);
|
|
1288
|
+
}
|
|
1289
|
+
async grantEuEntityRepresentativePermissions(request) {
|
|
1290
|
+
const req = RestRequest.post(Routes.Permissions.Grants.euEntitiesRepresentatives).body(request);
|
|
1291
|
+
const response = await this.restClient.execute(req);
|
|
1292
|
+
return response.body;
|
|
1293
|
+
}
|
|
1294
|
+
// Revoke methods
|
|
1295
|
+
async revokeCommonGrant(grantId) {
|
|
1296
|
+
const req = RestRequest.delete(Routes.Permissions.Common.grantById(grantId));
|
|
1297
|
+
const response = await this.restClient.execute(req);
|
|
1298
|
+
return response.body;
|
|
1299
|
+
}
|
|
1300
|
+
async revokeAuthorizationGrant(grantId) {
|
|
1301
|
+
const req = RestRequest.delete(Routes.Permissions.Authorizations.grantById(grantId));
|
|
1302
|
+
const response = await this.restClient.execute(req);
|
|
1303
|
+
return response.body;
|
|
1304
|
+
}
|
|
1305
|
+
// Search methods
|
|
1306
|
+
async queryPersonalGrants(options, pageOffset, pageSize) {
|
|
1307
|
+
const req = RestRequest.post(Routes.Permissions.Query.personalGrants).body(options ?? {});
|
|
1308
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1309
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1310
|
+
const response = await this.restClient.execute(req);
|
|
1311
|
+
return response.body;
|
|
1312
|
+
}
|
|
1313
|
+
async queryPersonsGrants(options, pageOffset, pageSize) {
|
|
1314
|
+
const req = RestRequest.post(Routes.Permissions.Query.personsGrants).body(options);
|
|
1315
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1316
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1317
|
+
const response = await this.restClient.execute(req);
|
|
1318
|
+
return response.body;
|
|
1319
|
+
}
|
|
1320
|
+
async querySubunitsGrants(options, pageOffset, pageSize) {
|
|
1321
|
+
const req = RestRequest.post(Routes.Permissions.Query.subunitsGrants).body(options ?? {});
|
|
1322
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1323
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1324
|
+
const response = await this.restClient.execute(req);
|
|
1325
|
+
return response.body;
|
|
1326
|
+
}
|
|
1327
|
+
async queryEntitiesRoles(options) {
|
|
1328
|
+
const req = RestRequest.get(Routes.Permissions.Query.entitiesRoles);
|
|
1329
|
+
if (options?.pageOffset !== void 0) req.query("pageOffset", String(options.pageOffset));
|
|
1330
|
+
if (options?.pageSize !== void 0) req.query("pageSize", String(options.pageSize));
|
|
1331
|
+
const response = await this.restClient.execute(req);
|
|
1332
|
+
return response.body;
|
|
1333
|
+
}
|
|
1334
|
+
async queryEntitiesGrants(options, pageOffset, pageSize) {
|
|
1335
|
+
const req = RestRequest.post(Routes.Permissions.Query.entitiesGrants).body(options ?? {});
|
|
1336
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1337
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1338
|
+
const response = await this.restClient.execute(req);
|
|
1339
|
+
return response.body;
|
|
1340
|
+
}
|
|
1341
|
+
async querySubordinateEntitiesRoles(options, pageOffset, pageSize) {
|
|
1342
|
+
const req = RestRequest.post(Routes.Permissions.Query.subordinateEntitiesRoles).body(options ?? {});
|
|
1343
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1344
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1345
|
+
const response = await this.restClient.execute(req);
|
|
1346
|
+
return response.body;
|
|
1347
|
+
}
|
|
1348
|
+
async queryAuthorizationsGrants(options, pageOffset, pageSize) {
|
|
1349
|
+
const req = RestRequest.post(Routes.Permissions.Query.authorizationsGrants).body(options);
|
|
1350
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1351
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1352
|
+
const response = await this.restClient.execute(req);
|
|
1353
|
+
return response.body;
|
|
1354
|
+
}
|
|
1355
|
+
async queryEuEntitiesGrants(options, pageOffset, pageSize) {
|
|
1356
|
+
const req = RestRequest.post(Routes.Permissions.Query.euEntitiesGrants).body(options ?? {});
|
|
1357
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1358
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1359
|
+
const response = await this.restClient.execute(req);
|
|
1360
|
+
return response.body;
|
|
1361
|
+
}
|
|
1362
|
+
// Operation status methods
|
|
1363
|
+
async getOperationStatus(ref) {
|
|
1364
|
+
const req = RestRequest.get(Routes.Permissions.Operations.byReference(ref));
|
|
1365
|
+
const response = await this.restClient.execute(req);
|
|
1366
|
+
return response.body;
|
|
1367
|
+
}
|
|
1368
|
+
async getAttachmentStatus() {
|
|
1369
|
+
const req = RestRequest.get(Routes.Permissions.Attachments.status);
|
|
1370
|
+
const response = await this.restClient.execute(req);
|
|
1371
|
+
return response.body;
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
|
|
1377
|
+
// src/services/tokens.ts
|
|
1378
|
+
var TokenService;
|
|
1379
|
+
var init_tokens = __esm({
|
|
1380
|
+
"src/services/tokens.ts"() {
|
|
1381
|
+
"use strict";
|
|
1382
|
+
init_rest_request();
|
|
1383
|
+
init_routes();
|
|
1384
|
+
TokenService = class {
|
|
1385
|
+
restClient;
|
|
1386
|
+
constructor(restClient) {
|
|
1387
|
+
this.restClient = restClient;
|
|
1388
|
+
}
|
|
1389
|
+
async generateToken(request) {
|
|
1390
|
+
const req = RestRequest.post(Routes.Tokens.root).body(request);
|
|
1391
|
+
const response = await this.restClient.execute(req);
|
|
1392
|
+
return response.body;
|
|
1393
|
+
}
|
|
1394
|
+
async queryTokens(options) {
|
|
1395
|
+
const req = RestRequest.get(Routes.Tokens.root);
|
|
1396
|
+
if (options?.continuationToken !== void 0) req.header("x-continuation-token", options.continuationToken);
|
|
1397
|
+
if (options?.pageSize !== void 0) req.query("pageSize", String(options.pageSize));
|
|
1398
|
+
if (options?.status) {
|
|
1399
|
+
for (const s of options.status) {
|
|
1400
|
+
req.query("status", s);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
if (options?.description !== void 0) req.query("description", options.description);
|
|
1404
|
+
if (options?.authorIdentifier !== void 0) req.query("authorIdentifier", options.authorIdentifier);
|
|
1405
|
+
if (options?.authorIdentifierType !== void 0) req.query("authorIdentifierType", options.authorIdentifierType);
|
|
1406
|
+
const response = await this.restClient.execute(req);
|
|
1407
|
+
return response.body;
|
|
1408
|
+
}
|
|
1409
|
+
async getToken(ref) {
|
|
1410
|
+
const req = RestRequest.get(Routes.Tokens.byReference(ref));
|
|
1411
|
+
const response = await this.restClient.execute(req);
|
|
1412
|
+
return response.body;
|
|
1413
|
+
}
|
|
1414
|
+
async revokeToken(ref) {
|
|
1415
|
+
const req = RestRequest.delete(Routes.Tokens.byReference(ref));
|
|
1416
|
+
await this.restClient.executeVoid(req);
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
});
|
|
1421
|
+
|
|
1422
|
+
// src/services/certificates.ts
|
|
1423
|
+
var CertificateApiService;
|
|
1424
|
+
var init_certificates = __esm({
|
|
1425
|
+
"src/services/certificates.ts"() {
|
|
1426
|
+
"use strict";
|
|
1427
|
+
init_rest_request();
|
|
1428
|
+
init_routes();
|
|
1429
|
+
CertificateApiService = class {
|
|
1430
|
+
restClient;
|
|
1431
|
+
constructor(restClient) {
|
|
1432
|
+
this.restClient = restClient;
|
|
1433
|
+
}
|
|
1434
|
+
async getLimits() {
|
|
1435
|
+
const req = RestRequest.get(Routes.Certificates.limits);
|
|
1436
|
+
const response = await this.restClient.execute(req);
|
|
1437
|
+
return response.body;
|
|
1438
|
+
}
|
|
1439
|
+
async getEnrollmentData() {
|
|
1440
|
+
const req = RestRequest.get(Routes.Certificates.enrollmentData);
|
|
1441
|
+
const response = await this.restClient.execute(req);
|
|
1442
|
+
return response.body;
|
|
1443
|
+
}
|
|
1444
|
+
async enroll(request) {
|
|
1445
|
+
const req = RestRequest.post(Routes.Certificates.enrollments).body(request);
|
|
1446
|
+
const response = await this.restClient.execute(req);
|
|
1447
|
+
return response.body;
|
|
1448
|
+
}
|
|
1449
|
+
async getEnrollmentStatus(ref) {
|
|
1450
|
+
const req = RestRequest.get(Routes.Certificates.enrollmentStatus(ref));
|
|
1451
|
+
const response = await this.restClient.execute(req);
|
|
1452
|
+
return response.body;
|
|
1453
|
+
}
|
|
1454
|
+
async retrieve(request) {
|
|
1455
|
+
const req = RestRequest.post(Routes.Certificates.retrieve).body(request);
|
|
1456
|
+
const response = await this.restClient.execute(req);
|
|
1457
|
+
return response.body;
|
|
1458
|
+
}
|
|
1459
|
+
async revoke(serialNumber, request) {
|
|
1460
|
+
const req = RestRequest.post(Routes.Certificates.revoke(serialNumber)).body(request);
|
|
1461
|
+
await this.restClient.executeVoid(req);
|
|
1462
|
+
}
|
|
1463
|
+
async query(request, pageSize, pageOffset) {
|
|
1464
|
+
const req = RestRequest.post(Routes.Certificates.query).body(request);
|
|
1465
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1466
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1467
|
+
const response = await this.restClient.execute(req);
|
|
1468
|
+
return response.body;
|
|
1469
|
+
}
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1473
|
+
|
|
1474
|
+
// src/services/lighthouse.ts
|
|
1475
|
+
var LighthouseService;
|
|
1476
|
+
var init_lighthouse = __esm({
|
|
1477
|
+
"src/services/lighthouse.ts"() {
|
|
1478
|
+
"use strict";
|
|
1479
|
+
init_errors();
|
|
1480
|
+
LighthouseService = class {
|
|
1481
|
+
lighthouseUrl;
|
|
1482
|
+
timeout;
|
|
1483
|
+
constructor(options) {
|
|
1484
|
+
this.lighthouseUrl = options.lighthouseUrl;
|
|
1485
|
+
this.timeout = options.timeout;
|
|
1486
|
+
}
|
|
1487
|
+
async fetchJson(path) {
|
|
1488
|
+
if (!this.lighthouseUrl) {
|
|
1489
|
+
throw new KSeFError(
|
|
1490
|
+
"Lighthouse API is not available for the DEMO environment. Use TEST or PROD instead."
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
const response = await fetch(`${this.lighthouseUrl}${path}`, {
|
|
1494
|
+
headers: { Accept: "application/json" },
|
|
1495
|
+
signal: AbortSignal.timeout(this.timeout)
|
|
1496
|
+
});
|
|
1497
|
+
if (!response.ok) {
|
|
1498
|
+
const body = await response.text();
|
|
1499
|
+
throw new KSeFError(
|
|
1500
|
+
`Lighthouse ${path} failed: HTTP ${response.status} \u2014 ${body}`
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
return await response.json();
|
|
1504
|
+
}
|
|
1505
|
+
async getStatus() {
|
|
1506
|
+
return this.fetchJson("/status");
|
|
1507
|
+
}
|
|
1508
|
+
async getMessages() {
|
|
1509
|
+
const data = await this.fetchJson("/messages");
|
|
1510
|
+
return data.messages ?? [];
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
});
|
|
1515
|
+
|
|
1516
|
+
// src/services/limits.ts
|
|
1517
|
+
var LimitsService;
|
|
1518
|
+
var init_limits = __esm({
|
|
1519
|
+
"src/services/limits.ts"() {
|
|
1520
|
+
"use strict";
|
|
1521
|
+
init_rest_request();
|
|
1522
|
+
init_routes();
|
|
1523
|
+
LimitsService = class {
|
|
1524
|
+
restClient;
|
|
1525
|
+
constructor(restClient) {
|
|
1526
|
+
this.restClient = restClient;
|
|
1527
|
+
}
|
|
1528
|
+
async getContextLimits() {
|
|
1529
|
+
const req = RestRequest.get(Routes.Limits.currentContext);
|
|
1530
|
+
const response = await this.restClient.execute(req);
|
|
1531
|
+
return response.body;
|
|
1532
|
+
}
|
|
1533
|
+
async getSubjectLimits() {
|
|
1534
|
+
const req = RestRequest.get(Routes.Limits.currentSubject);
|
|
1535
|
+
const response = await this.restClient.execute(req);
|
|
1536
|
+
return response.body;
|
|
1537
|
+
}
|
|
1538
|
+
async getRateLimits() {
|
|
1539
|
+
const req = RestRequest.get(Routes.Limits.rateLimits);
|
|
1540
|
+
const response = await this.restClient.execute(req);
|
|
1541
|
+
return response.body;
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1547
|
+
// src/services/peppol.ts
|
|
1548
|
+
var PeppolService;
|
|
1549
|
+
var init_peppol = __esm({
|
|
1550
|
+
"src/services/peppol.ts"() {
|
|
1551
|
+
"use strict";
|
|
1552
|
+
init_rest_request();
|
|
1553
|
+
init_routes();
|
|
1554
|
+
PeppolService = class {
|
|
1555
|
+
restClient;
|
|
1556
|
+
constructor(restClient) {
|
|
1557
|
+
this.restClient = restClient;
|
|
1558
|
+
}
|
|
1559
|
+
async queryProviders(pageOffset, pageSize) {
|
|
1560
|
+
const req = RestRequest.get(Routes.Peppol.query);
|
|
1561
|
+
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
1562
|
+
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
1563
|
+
const response = await this.restClient.execute(req);
|
|
1564
|
+
return response.body;
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1569
|
+
|
|
1570
|
+
// src/services/test-data.ts
|
|
1571
|
+
var TestDataService;
|
|
1572
|
+
var init_test_data = __esm({
|
|
1573
|
+
"src/services/test-data.ts"() {
|
|
1574
|
+
"use strict";
|
|
1575
|
+
init_rest_request();
|
|
1576
|
+
init_routes();
|
|
1577
|
+
init_ksef_error();
|
|
1578
|
+
TestDataService = class {
|
|
1579
|
+
restClient;
|
|
1580
|
+
environmentName;
|
|
1581
|
+
constructor(restClient, environmentName) {
|
|
1582
|
+
this.restClient = restClient;
|
|
1583
|
+
this.environmentName = environmentName;
|
|
1584
|
+
}
|
|
1585
|
+
ensureTestEnvironment() {
|
|
1586
|
+
if (this.environmentName && this.environmentName !== "TEST") {
|
|
1587
|
+
throw new KSeFError(
|
|
1588
|
+
`Test data APIs are only available on the TEST environment (current: ${this.environmentName})`
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
// Subject management
|
|
1593
|
+
async createSubject(request) {
|
|
1594
|
+
this.ensureTestEnvironment();
|
|
1595
|
+
const req = RestRequest.post(Routes.TestData.createSubject).body(request);
|
|
1596
|
+
await this.restClient.executeVoid(req);
|
|
1597
|
+
}
|
|
1598
|
+
async removeSubject(request) {
|
|
1599
|
+
this.ensureTestEnvironment();
|
|
1600
|
+
const req = RestRequest.post(Routes.TestData.removeSubject).body(request);
|
|
1601
|
+
await this.restClient.executeVoid(req);
|
|
1602
|
+
}
|
|
1603
|
+
// Person management
|
|
1604
|
+
async createPerson(request) {
|
|
1605
|
+
this.ensureTestEnvironment();
|
|
1606
|
+
const req = RestRequest.post(Routes.TestData.createPerson).body(request);
|
|
1607
|
+
await this.restClient.executeVoid(req);
|
|
1608
|
+
}
|
|
1609
|
+
async removePerson(request) {
|
|
1610
|
+
this.ensureTestEnvironment();
|
|
1611
|
+
const req = RestRequest.post(Routes.TestData.removePerson).body(request);
|
|
1612
|
+
await this.restClient.executeVoid(req);
|
|
1613
|
+
}
|
|
1614
|
+
// Permissions
|
|
1615
|
+
async grantPermissions(request) {
|
|
1616
|
+
this.ensureTestEnvironment();
|
|
1617
|
+
const req = RestRequest.post(Routes.TestData.grantPerms).body(request);
|
|
1618
|
+
await this.restClient.executeVoid(req);
|
|
1619
|
+
}
|
|
1620
|
+
async revokePermissions(request) {
|
|
1621
|
+
this.ensureTestEnvironment();
|
|
1622
|
+
const req = RestRequest.post(Routes.TestData.revokePerms).body(request);
|
|
1623
|
+
await this.restClient.executeVoid(req);
|
|
1624
|
+
}
|
|
1625
|
+
// Attachment permissions
|
|
1626
|
+
async enableAttachment(request) {
|
|
1627
|
+
this.ensureTestEnvironment();
|
|
1628
|
+
const req = RestRequest.post(Routes.TestData.enableAttach).body(request);
|
|
1629
|
+
await this.restClient.executeVoid(req);
|
|
1630
|
+
}
|
|
1631
|
+
async disableAttachment(request) {
|
|
1632
|
+
this.ensureTestEnvironment();
|
|
1633
|
+
const req = RestRequest.post(Routes.TestData.disableAttach).body(request);
|
|
1634
|
+
await this.restClient.executeVoid(req);
|
|
1635
|
+
}
|
|
1636
|
+
// Session limits
|
|
1637
|
+
async changeSessionLimits(request) {
|
|
1638
|
+
this.ensureTestEnvironment();
|
|
1639
|
+
const req = RestRequest.post(Routes.TestData.changeSessionLimitsInCurrentContext).body(request);
|
|
1640
|
+
await this.restClient.executeVoid(req);
|
|
1641
|
+
}
|
|
1642
|
+
async restoreDefaultSessionLimits() {
|
|
1643
|
+
this.ensureTestEnvironment();
|
|
1644
|
+
const req = RestRequest.delete(Routes.TestData.restoreDefaultSessionLimitsInCurrentContext);
|
|
1645
|
+
await this.restClient.executeVoid(req);
|
|
1646
|
+
}
|
|
1647
|
+
// Certificate limits
|
|
1648
|
+
async changeCertificatesLimit(request) {
|
|
1649
|
+
this.ensureTestEnvironment();
|
|
1650
|
+
const req = RestRequest.post(Routes.TestData.changeCertificatesLimitInCurrentSubject).body(request);
|
|
1651
|
+
await this.restClient.executeVoid(req);
|
|
1652
|
+
}
|
|
1653
|
+
async restoreDefaultCertificatesLimit() {
|
|
1654
|
+
this.ensureTestEnvironment();
|
|
1655
|
+
const req = RestRequest.delete(Routes.TestData.restoreDefaultCertificatesLimitInCurrentSubject);
|
|
1656
|
+
await this.restClient.executeVoid(req);
|
|
1657
|
+
}
|
|
1658
|
+
// Rate limits
|
|
1659
|
+
async setRateLimits(request) {
|
|
1660
|
+
this.ensureTestEnvironment();
|
|
1661
|
+
const req = RestRequest.post(Routes.TestData.rateLimits).body(request);
|
|
1662
|
+
await this.restClient.executeVoid(req);
|
|
1663
|
+
}
|
|
1664
|
+
async restoreDefaultRateLimits() {
|
|
1665
|
+
this.ensureTestEnvironment();
|
|
1666
|
+
const req = RestRequest.delete(Routes.TestData.rateLimits);
|
|
1667
|
+
await this.restClient.executeVoid(req);
|
|
1668
|
+
}
|
|
1669
|
+
async setProductionRateLimits() {
|
|
1670
|
+
this.ensureTestEnvironment();
|
|
1671
|
+
const req = RestRequest.post(Routes.TestData.productionRateLimits);
|
|
1672
|
+
await this.restClient.executeVoid(req);
|
|
1673
|
+
}
|
|
1674
|
+
// Context blocking
|
|
1675
|
+
async blockContext(request) {
|
|
1676
|
+
this.ensureTestEnvironment();
|
|
1677
|
+
const req = RestRequest.post(Routes.TestData.blockContext).body(request);
|
|
1678
|
+
await this.restClient.executeVoid(req);
|
|
1679
|
+
}
|
|
1680
|
+
async unblockContext(request) {
|
|
1681
|
+
this.ensureTestEnvironment();
|
|
1682
|
+
const req = RestRequest.post(Routes.TestData.unblockContext).body(request);
|
|
1683
|
+
await this.restClient.executeVoid(req);
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
|
|
1689
|
+
// src/crypto/certificate-fetcher.ts
|
|
1690
|
+
var CertificateFetcher;
|
|
1691
|
+
var init_certificate_fetcher = __esm({
|
|
1692
|
+
"src/crypto/certificate-fetcher.ts"() {
|
|
1693
|
+
"use strict";
|
|
1694
|
+
init_rest_request();
|
|
1695
|
+
init_routes();
|
|
1696
|
+
CertificateFetcher = class {
|
|
1697
|
+
restClient;
|
|
1698
|
+
symmetricKeyPem;
|
|
1699
|
+
ksefTokenPem;
|
|
1700
|
+
initialized = false;
|
|
1701
|
+
constructor(restClient) {
|
|
1702
|
+
this.restClient = restClient;
|
|
1703
|
+
}
|
|
1704
|
+
async init() {
|
|
1705
|
+
if (this.initialized) return;
|
|
1706
|
+
await this.fetchCertificates();
|
|
1707
|
+
}
|
|
1708
|
+
async refresh() {
|
|
1709
|
+
this.initialized = false;
|
|
1710
|
+
await this.fetchCertificates();
|
|
1711
|
+
}
|
|
1712
|
+
getSymmetricKeyEncryptionPem() {
|
|
1713
|
+
if (!this.symmetricKeyPem) {
|
|
1714
|
+
throw new Error("CertificateFetcher not initialized. Call init() first.");
|
|
1715
|
+
}
|
|
1716
|
+
return this.symmetricKeyPem;
|
|
1717
|
+
}
|
|
1718
|
+
getKsefTokenEncryptionPem() {
|
|
1719
|
+
if (!this.ksefTokenPem) {
|
|
1720
|
+
throw new Error("CertificateFetcher not initialized. Call init() first.");
|
|
1721
|
+
}
|
|
1722
|
+
return this.ksefTokenPem;
|
|
1723
|
+
}
|
|
1724
|
+
async fetchCertificates() {
|
|
1725
|
+
const request = RestRequest.get(Routes.Security.publicKeyCertificates);
|
|
1726
|
+
const response = await this.restClient.execute(request);
|
|
1727
|
+
const certs = response.body;
|
|
1728
|
+
if (!certs || certs.length === 0) {
|
|
1729
|
+
throw new Error("No public key certificates returned from KSeF API.");
|
|
1730
|
+
}
|
|
1731
|
+
const symmetricCert = certs.find((c) => c.usage.includes("SymmetricKeyEncryption"));
|
|
1732
|
+
if (!symmetricCert) {
|
|
1733
|
+
throw new Error("No SymmetricKeyEncryption certificate found.");
|
|
1734
|
+
}
|
|
1735
|
+
this.symmetricKeyPem = this.derBase64ToPem(symmetricCert.certificate);
|
|
1736
|
+
const tokenCerts = certs.filter((c) => c.usage.includes("KsefTokenEncryption")).sort((a, b) => a.validFrom.localeCompare(b.validFrom));
|
|
1737
|
+
const tokenCert = tokenCerts[0];
|
|
1738
|
+
if (!tokenCert) {
|
|
1739
|
+
throw new Error("No KsefTokenEncryption certificate found.");
|
|
1740
|
+
}
|
|
1741
|
+
this.ksefTokenPem = this.derBase64ToPem(tokenCert.certificate);
|
|
1742
|
+
this.initialized = true;
|
|
1743
|
+
}
|
|
1744
|
+
derBase64ToPem(base64Der) {
|
|
1745
|
+
const lines = [];
|
|
1746
|
+
for (let i = 0; i < base64Der.length; i += 64) {
|
|
1747
|
+
lines.push(base64Der.substring(i, i + 64));
|
|
1748
|
+
}
|
|
1749
|
+
return `-----BEGIN CERTIFICATE-----
|
|
1750
|
+
${lines.join("\n")}
|
|
1751
|
+
-----END CERTIFICATE-----`;
|
|
1752
|
+
}
|
|
1753
|
+
};
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
|
|
1757
|
+
// src/crypto/cryptography-service.ts
|
|
1758
|
+
import * as crypto2 from "crypto";
|
|
1759
|
+
import * as x509 from "@peculiar/x509";
|
|
1760
|
+
function setCryptoProvider() {
|
|
1761
|
+
x509.cryptoProvider.set(crypto2.webcrypto);
|
|
1762
|
+
}
|
|
1763
|
+
function buildX500Name(fields) {
|
|
1764
|
+
const parts = [];
|
|
1765
|
+
if (fields.commonName) parts.push(`CN=${fields.commonName}`);
|
|
1766
|
+
if (fields.givenName) parts.push(`2.5.4.42=${fields.givenName}`);
|
|
1767
|
+
if (fields.surname) parts.push(`2.5.4.4=${fields.surname}`);
|
|
1768
|
+
if (fields.serialNumber) parts.push(`2.5.4.5=${fields.serialNumber}`);
|
|
1769
|
+
if (fields.organizationName) parts.push(`O=${fields.organizationName}`);
|
|
1770
|
+
if (fields.organizationIdentifier) parts.push(`2.5.4.97=${fields.organizationIdentifier}`);
|
|
1771
|
+
if (fields.uniqueIdentifier) parts.push(`2.5.4.45=${fields.uniqueIdentifier}`);
|
|
1772
|
+
if (fields.countryCode) parts.push(`C=${fields.countryCode}`);
|
|
1773
|
+
return parts.join(", ");
|
|
1774
|
+
}
|
|
1775
|
+
function pemEncode(der, label) {
|
|
1776
|
+
const base64 = Buffer.from(der).toString("base64");
|
|
1777
|
+
const lines = [];
|
|
1778
|
+
for (let i = 0; i < base64.length; i += 64) {
|
|
1779
|
+
lines.push(base64.substring(i, i + 64));
|
|
1780
|
+
}
|
|
1781
|
+
return `-----BEGIN ${label}-----
|
|
1782
|
+
${lines.join("\n")}
|
|
1783
|
+
-----END ${label}-----`;
|
|
1784
|
+
}
|
|
1785
|
+
var CryptographyService;
|
|
1786
|
+
var init_cryptography_service = __esm({
|
|
1787
|
+
"src/crypto/cryptography-service.ts"() {
|
|
1788
|
+
"use strict";
|
|
1789
|
+
CryptographyService = class {
|
|
1790
|
+
fetcher;
|
|
1791
|
+
constructor(fetcher) {
|
|
1792
|
+
this.fetcher = fetcher;
|
|
1793
|
+
}
|
|
1794
|
+
/** Initialise the underlying certificate fetcher. */
|
|
1795
|
+
async init() {
|
|
1796
|
+
await this.fetcher.init();
|
|
1797
|
+
}
|
|
1798
|
+
// ---------------------------------------------------------------------------
|
|
1799
|
+
// AES-256-CBC
|
|
1800
|
+
// ---------------------------------------------------------------------------
|
|
1801
|
+
/** Encrypt with AES-256-CBC (PKCS7 padding is automatic in Node). */
|
|
1802
|
+
encryptAES256(content, key, iv) {
|
|
1803
|
+
const cipher = crypto2.createCipheriv("aes-256-cbc", key, iv);
|
|
1804
|
+
return new Uint8Array(Buffer.concat([cipher.update(content), cipher.final()]));
|
|
1805
|
+
}
|
|
1806
|
+
/** Decrypt with AES-256-CBC. */
|
|
1807
|
+
decryptAES256(content, key, iv) {
|
|
1808
|
+
const decipher = crypto2.createDecipheriv("aes-256-cbc", key, iv);
|
|
1809
|
+
return new Uint8Array(Buffer.concat([decipher.update(content), decipher.final()]));
|
|
1810
|
+
}
|
|
1811
|
+
// ---------------------------------------------------------------------------
|
|
1812
|
+
// Encryption data (AES key + IV wrapped with RSA-OAEP)
|
|
1813
|
+
// ---------------------------------------------------------------------------
|
|
1814
|
+
/**
|
|
1815
|
+
* Generate a random AES-256 key and IV, then wrap the key with the
|
|
1816
|
+
* SymmetricKeyEncryption certificate's RSA public key (RSA-OAEP SHA-256).
|
|
1817
|
+
*/
|
|
1818
|
+
getEncryptionData() {
|
|
1819
|
+
const key = crypto2.randomBytes(32);
|
|
1820
|
+
const iv = crypto2.randomBytes(16);
|
|
1821
|
+
const certPem = this.fetcher.getSymmetricKeyEncryptionPem();
|
|
1822
|
+
const encryptedKey = crypto2.publicEncrypt(
|
|
1823
|
+
{
|
|
1824
|
+
key: certPem,
|
|
1825
|
+
oaepHash: "sha256",
|
|
1826
|
+
padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
|
|
1827
|
+
},
|
|
1828
|
+
key
|
|
1829
|
+
);
|
|
1830
|
+
const encryptionInfo = {
|
|
1831
|
+
encryptedSymmetricKey: encryptedKey.toString("base64"),
|
|
1832
|
+
initializationVector: iv.toString("base64")
|
|
1833
|
+
};
|
|
1834
|
+
return {
|
|
1835
|
+
cipherKey: new Uint8Array(key),
|
|
1836
|
+
cipherIv: new Uint8Array(iv),
|
|
1837
|
+
encryptionInfo
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
// ---------------------------------------------------------------------------
|
|
1841
|
+
// KSeF token encryption
|
|
1842
|
+
// ---------------------------------------------------------------------------
|
|
1843
|
+
/**
|
|
1844
|
+
* Encrypt a KSeF token for session authorisation.
|
|
1845
|
+
*
|
|
1846
|
+
* Token payload: `"<token>|<challengeTimestampMs>"`.
|
|
1847
|
+
*
|
|
1848
|
+
* The algorithm is chosen automatically based on the KsefTokenEncryption
|
|
1849
|
+
* certificate's public key type:
|
|
1850
|
+
* - **RSA** — RSA-OAEP with SHA-256
|
|
1851
|
+
* - **EC** — ECDH key-agreement (P-256) + AES-256-GCM
|
|
1852
|
+
*
|
|
1853
|
+
* The EC variant outputs bytes in the Java-compatible format:
|
|
1854
|
+
* `[ephemeralSPKI | nonce(12) | ciphertext+tag]`.
|
|
1855
|
+
*/
|
|
1856
|
+
encryptKsefToken(token, challengeTimestamp) {
|
|
1857
|
+
const timestampMs = new Date(challengeTimestamp).getTime();
|
|
1858
|
+
const plaintext = Buffer.from(`${token}|${timestampMs}`, "utf-8");
|
|
1859
|
+
const certPem = this.fetcher.getKsefTokenEncryptionPem();
|
|
1860
|
+
const cert = new crypto2.X509Certificate(certPem);
|
|
1861
|
+
const publicKey = cert.publicKey;
|
|
1862
|
+
if (publicKey.asymmetricKeyType === "rsa") {
|
|
1863
|
+
return this.encryptRsaOaep(certPem, plaintext);
|
|
1864
|
+
}
|
|
1865
|
+
if (publicKey.asymmetricKeyType === "ec") {
|
|
1866
|
+
return this.encryptEcdhAesGcm(publicKey, plaintext);
|
|
1867
|
+
}
|
|
1868
|
+
throw new Error(`Unsupported key algorithm: ${publicKey.asymmetricKeyType ?? "unknown"}`);
|
|
1869
|
+
}
|
|
1870
|
+
// ---------------------------------------------------------------------------
|
|
1871
|
+
// File metadata
|
|
1872
|
+
// ---------------------------------------------------------------------------
|
|
1873
|
+
/** Compute SHA-256 hash (base64) and byte length. */
|
|
1874
|
+
getFileMetadata(file) {
|
|
1875
|
+
const hash = crypto2.createHash("sha256").update(file).digest("base64");
|
|
1876
|
+
return { hashSHA: hash, fileSize: file.length };
|
|
1877
|
+
}
|
|
1878
|
+
// ---------------------------------------------------------------------------
|
|
1879
|
+
// CSR generation
|
|
1880
|
+
// ---------------------------------------------------------------------------
|
|
1881
|
+
/** Generate an RSA-2048 CSR (PKCS#10, DER) and return it together with the private key PEM. */
|
|
1882
|
+
async generateCsrRsa(fields) {
|
|
1883
|
+
setCryptoProvider();
|
|
1884
|
+
const algorithm = {
|
|
1885
|
+
name: "RSASSA-PKCS1-v1_5",
|
|
1886
|
+
hash: "SHA-256",
|
|
1887
|
+
publicExponent: new Uint8Array([1, 0, 1]),
|
|
1888
|
+
modulusLength: 2048
|
|
1889
|
+
};
|
|
1890
|
+
const keys = await crypto2.webcrypto.subtle.generateKey(
|
|
1891
|
+
algorithm,
|
|
1892
|
+
true,
|
|
1893
|
+
["sign", "verify"]
|
|
1894
|
+
);
|
|
1895
|
+
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
|
|
1896
|
+
name: buildX500Name(fields),
|
|
1897
|
+
keys,
|
|
1898
|
+
signingAlgorithm: algorithm
|
|
1899
|
+
});
|
|
1900
|
+
const csrDer = new Uint8Array(csr.rawData);
|
|
1901
|
+
const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
|
|
1902
|
+
const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
|
|
1903
|
+
return { csrDer, privateKeyPem };
|
|
1904
|
+
}
|
|
1905
|
+
/** Generate an ECDSA P-256 CSR (PKCS#10, DER) and return it together with the private key PEM. */
|
|
1906
|
+
async generateCsrEcdsa(fields) {
|
|
1907
|
+
setCryptoProvider();
|
|
1908
|
+
const algorithm = {
|
|
1909
|
+
name: "ECDSA",
|
|
1910
|
+
namedCurve: "P-256"
|
|
1911
|
+
};
|
|
1912
|
+
const keys = await crypto2.webcrypto.subtle.generateKey(
|
|
1913
|
+
algorithm,
|
|
1914
|
+
true,
|
|
1915
|
+
["sign", "verify"]
|
|
1916
|
+
);
|
|
1917
|
+
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
|
|
1918
|
+
name: buildX500Name(fields),
|
|
1919
|
+
keys,
|
|
1920
|
+
signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
|
|
1921
|
+
});
|
|
1922
|
+
const csrDer = new Uint8Array(csr.rawData);
|
|
1923
|
+
const pkcs8 = await crypto2.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
|
|
1924
|
+
const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
|
|
1925
|
+
return { csrDer, privateKeyPem };
|
|
1926
|
+
}
|
|
1927
|
+
// ---------------------------------------------------------------------------
|
|
1928
|
+
// Key parsing
|
|
1929
|
+
// ---------------------------------------------------------------------------
|
|
1930
|
+
/** Parse a PEM-encoded private key into a Node.js KeyObject. */
|
|
1931
|
+
parsePrivateKey(pem) {
|
|
1932
|
+
return crypto2.createPrivateKey(pem);
|
|
1933
|
+
}
|
|
1934
|
+
// ---------------------------------------------------------------------------
|
|
1935
|
+
// Private helpers
|
|
1936
|
+
// ---------------------------------------------------------------------------
|
|
1937
|
+
/** RSA-OAEP SHA-256 encryption. */
|
|
1938
|
+
encryptRsaOaep(certPem, plaintext) {
|
|
1939
|
+
return new Uint8Array(
|
|
1940
|
+
crypto2.publicEncrypt(
|
|
1941
|
+
{
|
|
1942
|
+
key: certPem,
|
|
1943
|
+
oaepHash: "sha256",
|
|
1944
|
+
padding: crypto2.constants.RSA_PKCS1_OAEP_PADDING
|
|
1945
|
+
},
|
|
1946
|
+
plaintext
|
|
1947
|
+
)
|
|
1948
|
+
);
|
|
1949
|
+
}
|
|
1950
|
+
/**
|
|
1951
|
+
* ECDH (P-256) + AES-256-GCM encryption.
|
|
1952
|
+
*
|
|
1953
|
+
* 1. Generate an ephemeral EC key pair on the same curve (P-256).
|
|
1954
|
+
* 2. Derive a shared secret via ECDH with the receiver's public key.
|
|
1955
|
+
* 3. Use the shared secret (32 bytes) as the AES-256-GCM key.
|
|
1956
|
+
* 4. Encrypt with a random 12-byte nonce.
|
|
1957
|
+
* 5. Output: `[ephemeralSPKI | nonce(12) | ciphertext+tag]`
|
|
1958
|
+
* (Java-compatible — GCM appends the 16-byte tag to the ciphertext).
|
|
1959
|
+
*/
|
|
1960
|
+
encryptEcdhAesGcm(receiverPublicKey, plaintext) {
|
|
1961
|
+
const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto2.generateKeyPairSync("ec", {
|
|
1962
|
+
namedCurve: "prime256v1"
|
|
1963
|
+
});
|
|
1964
|
+
const sharedSecret = crypto2.diffieHellman({
|
|
1965
|
+
privateKey: ephPrivKey,
|
|
1966
|
+
publicKey: receiverPublicKey
|
|
1967
|
+
});
|
|
1968
|
+
const nonce = crypto2.randomBytes(12);
|
|
1969
|
+
const cipher = crypto2.createCipheriv("aes-256-gcm", sharedSecret, nonce);
|
|
1970
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
1971
|
+
const tag = cipher.getAuthTag();
|
|
1972
|
+
const ephemeralSpki = ephPubKey.export({ type: "spki", format: "der" });
|
|
1973
|
+
return new Uint8Array(Buffer.concat([ephemeralSpki, nonce, ciphertext, tag]));
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
}
|
|
1977
|
+
});
|
|
1978
|
+
|
|
34
1979
|
// node_modules/@xmldom/xmldom/lib/conventions.js
|
|
35
1980
|
var require_conventions = __commonJS({
|
|
36
1981
|
"node_modules/@xmldom/xmldom/lib/conventions.js"(exports) {
|
|
@@ -4572,7 +6517,7 @@ var signature_service_exports = {};
|
|
|
4572
6517
|
__export(signature_service_exports, {
|
|
4573
6518
|
SignatureService: () => SignatureService
|
|
4574
6519
|
});
|
|
4575
|
-
import * as
|
|
6520
|
+
import * as crypto3 from "crypto";
|
|
4576
6521
|
import { ExclusiveCanonicalization } from "xml-crypto";
|
|
4577
6522
|
function extractDerFromPem(pem) {
|
|
4578
6523
|
const base64 = pem.replace(/-----BEGIN [A-Z\s]+-----/g, "").replace(/-----END [A-Z\s]+-----/g, "").replace(/\s+/g, "");
|
|
@@ -4591,7 +6536,7 @@ function canonicalize(elem) {
|
|
|
4591
6536
|
function computeRootDigest(doc) {
|
|
4592
6537
|
const root = doc.documentElement;
|
|
4593
6538
|
const canonical = canonicalize(root);
|
|
4594
|
-
return
|
|
6539
|
+
return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
|
|
4595
6540
|
}
|
|
4596
6541
|
function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
|
|
4597
6542
|
const parser = new import_xmldom.DOMParser();
|
|
@@ -4601,7 +6546,7 @@ function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
|
|
|
4601
6546
|
throw new Error("SignedProperties element not found in QualifyingProperties");
|
|
4602
6547
|
}
|
|
4603
6548
|
const canonical = canonicalize(signedProps);
|
|
4604
|
-
return
|
|
6549
|
+
return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
|
|
4605
6550
|
}
|
|
4606
6551
|
function buildSignedInfo(signatureAlgorithm, rootDigest, signedPropertiesDigest) {
|
|
4607
6552
|
return [
|
|
@@ -4632,12 +6577,12 @@ function computeSignatureValue(canonicalSignedInfo, privateKeyPem, isEc) {
|
|
|
4632
6577
|
const data = Buffer.from(canonicalSignedInfo, "utf-8");
|
|
4633
6578
|
let signature;
|
|
4634
6579
|
if (isEc) {
|
|
4635
|
-
signature =
|
|
6580
|
+
signature = crypto3.sign("sha256", data, {
|
|
4636
6581
|
key: privateKeyPem,
|
|
4637
6582
|
dsaEncoding: "ieee-p1363"
|
|
4638
6583
|
});
|
|
4639
6584
|
} else {
|
|
4640
|
-
signature =
|
|
6585
|
+
signature = crypto3.sign("sha256", data, privateKeyPem);
|
|
4641
6586
|
}
|
|
4642
6587
|
return signature.toString("base64");
|
|
4643
6588
|
}
|
|
@@ -4737,11 +6682,11 @@ var init_signature_service = __esm({
|
|
|
4737
6682
|
}
|
|
4738
6683
|
const certDer = extractDerFromPem(certPem);
|
|
4739
6684
|
const certBase64 = certDer.toString("base64");
|
|
4740
|
-
const certDigest =
|
|
4741
|
-
const x5093 = new
|
|
6685
|
+
const certDigest = crypto3.createHash("sha256").update(certDer).digest("base64");
|
|
6686
|
+
const x5093 = new crypto3.X509Certificate(certPem);
|
|
4742
6687
|
const issuerName = normalizeIssuerDn(x5093.issuer);
|
|
4743
6688
|
const serialNumber = hexSerialToDecimal(x5093.serialNumber);
|
|
4744
|
-
const privateKey =
|
|
6689
|
+
const privateKey = crypto3.createPrivateKey(privateKeyPem);
|
|
4745
6690
|
const isEc = privateKey.asymmetricKeyType === "ec";
|
|
4746
6691
|
const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
|
|
4747
6692
|
const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
|
|
@@ -4826,771 +6771,265 @@ var init_pkcs12_loader = __esm({
|
|
|
4826
6771
|
if (!cert) {
|
|
4827
6772
|
throw new Error("PKCS#12 certificate bag is empty.");
|
|
4828
6773
|
}
|
|
4829
|
-
if (!key) {
|
|
4830
|
-
throw new Error("PKCS#12 key bag is empty.");
|
|
4831
|
-
}
|
|
4832
|
-
const certificatePem = pki.certificateToPem(cert);
|
|
4833
|
-
let privateKeyPem;
|
|
4834
|
-
try {
|
|
4835
|
-
privateKeyPem = pki.privateKeyToPem(key);
|
|
4836
|
-
} catch {
|
|
4837
|
-
throw new Error(
|
|
4838
|
-
"Failed to export private key from PKCS#12 to PEM. This can happen with EC keys. Use separate --cert and --key PEM files instead."
|
|
4839
|
-
);
|
|
4840
|
-
}
|
|
4841
|
-
return { certificatePem, privateKeyPem };
|
|
4842
|
-
}
|
|
4843
|
-
};
|
|
4844
|
-
}
|
|
4845
|
-
});
|
|
4846
|
-
|
|
4847
|
-
// src/config/environments.ts
|
|
4848
|
-
var Environment = {
|
|
4849
|
-
TEST: {
|
|
4850
|
-
apiUrl: "https://api-test.ksef.mf.gov.pl",
|
|
4851
|
-
qrUrl: "https://qr-test.ksef.mf.gov.pl",
|
|
4852
|
-
lighthouseUrl: "https://api-latarnia-test.ksef.mf.gov.pl"
|
|
4853
|
-
},
|
|
4854
|
-
DEMO: {
|
|
4855
|
-
apiUrl: "https://api-demo.ksef.mf.gov.pl",
|
|
4856
|
-
qrUrl: "https://qr-demo.ksef.mf.gov.pl",
|
|
4857
|
-
lighthouseUrl: ""
|
|
4858
|
-
},
|
|
4859
|
-
PROD: {
|
|
4860
|
-
apiUrl: "https://api.ksef.mf.gov.pl",
|
|
4861
|
-
qrUrl: "https://qr.ksef.mf.gov.pl",
|
|
4862
|
-
lighthouseUrl: "https://api-latarnia.ksef.mf.gov.pl"
|
|
4863
|
-
}
|
|
4864
|
-
};
|
|
4865
|
-
|
|
4866
|
-
// src/config/options.ts
|
|
4867
|
-
var DEFAULT_API_VERSION = "v2";
|
|
4868
|
-
var DEFAULT_TIMEOUT = 3e4;
|
|
4869
|
-
function resolveOptions(options = {}) {
|
|
4870
|
-
const env = options.environment ? Environment[options.environment] : Environment.TEST;
|
|
4871
|
-
return {
|
|
4872
|
-
baseUrl: options.baseUrl ?? env.apiUrl,
|
|
4873
|
-
baseQrUrl: options.baseQrUrl ?? env.qrUrl,
|
|
4874
|
-
lighthouseUrl: options.lighthouseUrl ?? env.lighthouseUrl,
|
|
4875
|
-
apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
|
|
4876
|
-
timeout: options.timeout ?? DEFAULT_TIMEOUT,
|
|
4877
|
-
customHeaders: options.customHeaders ?? {}
|
|
4878
|
-
};
|
|
4879
|
-
}
|
|
4880
|
-
|
|
4881
|
-
// src/errors/ksef-error.ts
|
|
4882
|
-
var KSeFError = class extends Error {
|
|
4883
|
-
constructor(message) {
|
|
4884
|
-
super(message);
|
|
4885
|
-
this.name = "KSeFError";
|
|
4886
|
-
}
|
|
4887
|
-
};
|
|
4888
|
-
|
|
4889
|
-
// src/errors/ksef-api-error.ts
|
|
4890
|
-
var KSeFApiError = class _KSeFApiError extends KSeFError {
|
|
4891
|
-
statusCode;
|
|
4892
|
-
errorResponse;
|
|
4893
|
-
constructor(message, statusCode, errorResponse) {
|
|
4894
|
-
super(message);
|
|
4895
|
-
this.name = "KSeFApiError";
|
|
4896
|
-
this.statusCode = statusCode;
|
|
4897
|
-
this.errorResponse = errorResponse;
|
|
4898
|
-
}
|
|
4899
|
-
static fromResponse(statusCode, body) {
|
|
4900
|
-
const details = body?.exception?.exceptionDetailList;
|
|
4901
|
-
const message = details?.length ? details.map((d) => d.exceptionDescription ?? "").filter(Boolean).join("; ") || `KSeF API error: HTTP ${statusCode}` : `KSeF API error: HTTP ${statusCode}`;
|
|
4902
|
-
return new _KSeFApiError(message, statusCode, body);
|
|
4903
|
-
}
|
|
4904
|
-
};
|
|
4905
|
-
|
|
4906
|
-
// src/errors/ksef-rate-limit-error.ts
|
|
4907
|
-
var KSeFRateLimitError = class _KSeFRateLimitError extends KSeFApiError {
|
|
4908
|
-
retryAfterSeconds;
|
|
4909
|
-
retryAfterDate;
|
|
4910
|
-
recommendedDelay;
|
|
4911
|
-
constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate) {
|
|
4912
|
-
super(message, statusCode, errorResponse);
|
|
4913
|
-
this.name = "KSeFRateLimitError";
|
|
4914
|
-
this.retryAfterSeconds = retryAfterSeconds;
|
|
4915
|
-
this.retryAfterDate = retryAfterDate;
|
|
4916
|
-
this.recommendedDelay = retryAfterSeconds ?? 60;
|
|
4917
|
-
}
|
|
4918
|
-
static fromRetryAfterHeader(statusCode, retryAfterHeader, body) {
|
|
4919
|
-
let retryAfterSeconds;
|
|
4920
|
-
let retryAfterDate;
|
|
4921
|
-
if (retryAfterHeader) {
|
|
4922
|
-
const seconds = Number(retryAfterHeader);
|
|
4923
|
-
if (!Number.isNaN(seconds)) {
|
|
4924
|
-
retryAfterSeconds = seconds;
|
|
4925
|
-
} else {
|
|
4926
|
-
const date = new Date(retryAfterHeader);
|
|
4927
|
-
if (!Number.isNaN(date.getTime())) {
|
|
4928
|
-
retryAfterDate = date;
|
|
4929
|
-
retryAfterSeconds = Math.max(0, Math.ceil((date.getTime() - Date.now()) / 1e3));
|
|
4930
|
-
}
|
|
4931
|
-
}
|
|
4932
|
-
}
|
|
4933
|
-
const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : "Rate limited by KSeF API";
|
|
4934
|
-
return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate);
|
|
4935
|
-
}
|
|
4936
|
-
};
|
|
4937
|
-
|
|
4938
|
-
// src/errors/ksef-unauthorized-error.ts
|
|
4939
|
-
var KSeFUnauthorizedError = class extends KSeFError {
|
|
4940
|
-
statusCode = 401;
|
|
4941
|
-
detail;
|
|
4942
|
-
traceId;
|
|
4943
|
-
instance;
|
|
4944
|
-
constructor(problemDetails) {
|
|
4945
|
-
super(problemDetails.detail || "Unauthorized");
|
|
4946
|
-
this.name = "KSeFUnauthorizedError";
|
|
4947
|
-
this.detail = problemDetails.detail;
|
|
4948
|
-
this.traceId = problemDetails.traceId;
|
|
4949
|
-
this.instance = problemDetails.instance;
|
|
4950
|
-
}
|
|
4951
|
-
};
|
|
4952
|
-
|
|
4953
|
-
// src/errors/ksef-forbidden-error.ts
|
|
4954
|
-
var KSeFForbiddenError = class extends KSeFError {
|
|
4955
|
-
statusCode = 403;
|
|
4956
|
-
detail;
|
|
4957
|
-
reasonCode;
|
|
4958
|
-
instance;
|
|
4959
|
-
security;
|
|
4960
|
-
traceId;
|
|
4961
|
-
constructor(problemDetails) {
|
|
4962
|
-
super(problemDetails.detail || "Forbidden");
|
|
4963
|
-
this.name = "KSeFForbiddenError";
|
|
4964
|
-
this.detail = problemDetails.detail;
|
|
4965
|
-
this.reasonCode = problemDetails.reasonCode;
|
|
4966
|
-
this.instance = problemDetails.instance;
|
|
4967
|
-
this.security = problemDetails.security;
|
|
4968
|
-
this.traceId = problemDetails.traceId;
|
|
4969
|
-
}
|
|
4970
|
-
};
|
|
4971
|
-
|
|
4972
|
-
// src/errors/ksef-auth-status-error.ts
|
|
4973
|
-
var KSeFAuthStatusError = class extends KSeFError {
|
|
4974
|
-
referenceNumber;
|
|
4975
|
-
statusDescription;
|
|
4976
|
-
constructor(message, referenceNumber, statusDescription) {
|
|
4977
|
-
super(message);
|
|
4978
|
-
this.name = "KSeFAuthStatusError";
|
|
4979
|
-
this.referenceNumber = referenceNumber;
|
|
4980
|
-
this.statusDescription = statusDescription;
|
|
4981
|
-
}
|
|
4982
|
-
};
|
|
4983
|
-
|
|
4984
|
-
// src/errors/ksef-session-expired-error.ts
|
|
4985
|
-
var KSeFSessionExpiredError = class extends KSeFError {
|
|
4986
|
-
constructor(message = "KSeF session has expired") {
|
|
4987
|
-
super(message);
|
|
4988
|
-
this.name = "KSeFSessionExpiredError";
|
|
4989
|
-
}
|
|
4990
|
-
};
|
|
4991
|
-
|
|
4992
|
-
// src/errors/ksef-validation-error.ts
|
|
4993
|
-
var KSeFValidationError = class _KSeFValidationError extends KSeFError {
|
|
4994
|
-
details;
|
|
4995
|
-
constructor(message, details = []) {
|
|
4996
|
-
super(message);
|
|
4997
|
-
this.name = "KSeFValidationError";
|
|
4998
|
-
this.details = details;
|
|
4999
|
-
}
|
|
5000
|
-
static fromField(field, message) {
|
|
5001
|
-
return new _KSeFValidationError(message, [{ field, message }]);
|
|
5002
|
-
}
|
|
5003
|
-
static fromMessages(messages) {
|
|
5004
|
-
const details = messages.map((m) => ({ message: m }));
|
|
5005
|
-
return new _KSeFValidationError(messages.join("; "), details);
|
|
5006
|
-
}
|
|
5007
|
-
};
|
|
5008
|
-
|
|
5009
|
-
// src/http/route-builder.ts
|
|
5010
|
-
var RouteBuilder = class {
|
|
5011
|
-
apiVersion;
|
|
5012
|
-
constructor(apiVersion) {
|
|
5013
|
-
this.apiVersion = apiVersion;
|
|
5014
|
-
}
|
|
5015
|
-
build(endpoint, apiVersion) {
|
|
5016
|
-
const version = apiVersion ?? this.apiVersion;
|
|
5017
|
-
return `/${version}/${endpoint}`;
|
|
5018
|
-
}
|
|
5019
|
-
};
|
|
5020
|
-
|
|
5021
|
-
// src/http/rest-request.ts
|
|
5022
|
-
var RestRequest = class _RestRequest {
|
|
5023
|
-
method;
|
|
5024
|
-
path;
|
|
5025
|
-
_body;
|
|
5026
|
-
_headers = {};
|
|
5027
|
-
_query = [];
|
|
5028
|
-
_presigned = false;
|
|
5029
|
-
_skipAuthRetry = false;
|
|
5030
|
-
constructor(method, path) {
|
|
5031
|
-
this.method = method;
|
|
5032
|
-
this.path = path;
|
|
5033
|
-
}
|
|
5034
|
-
static get(path) {
|
|
5035
|
-
return new _RestRequest("GET", path);
|
|
5036
|
-
}
|
|
5037
|
-
static post(path) {
|
|
5038
|
-
return new _RestRequest("POST", path);
|
|
5039
|
-
}
|
|
5040
|
-
static put(path) {
|
|
5041
|
-
return new _RestRequest("PUT", path);
|
|
5042
|
-
}
|
|
5043
|
-
static delete(path) {
|
|
5044
|
-
return new _RestRequest("DELETE", path);
|
|
5045
|
-
}
|
|
5046
|
-
body(data) {
|
|
5047
|
-
this._body = data;
|
|
5048
|
-
return this;
|
|
5049
|
-
}
|
|
5050
|
-
header(name, value) {
|
|
5051
|
-
this._headers[name] = value;
|
|
5052
|
-
return this;
|
|
5053
|
-
}
|
|
5054
|
-
headers(headers) {
|
|
5055
|
-
Object.assign(this._headers, headers);
|
|
5056
|
-
return this;
|
|
5057
|
-
}
|
|
5058
|
-
accessToken(token) {
|
|
5059
|
-
this._headers["Authorization"] = `Bearer ${token}`;
|
|
5060
|
-
return this;
|
|
5061
|
-
}
|
|
5062
|
-
query(key, value) {
|
|
5063
|
-
this._query.push([key, value]);
|
|
5064
|
-
return this;
|
|
5065
|
-
}
|
|
5066
|
-
presigned(flag = true) {
|
|
5067
|
-
this._presigned = flag;
|
|
5068
|
-
return this;
|
|
5069
|
-
}
|
|
5070
|
-
isPresigned() {
|
|
5071
|
-
return this._presigned;
|
|
5072
|
-
}
|
|
5073
|
-
skipAuthRetry(flag = true) {
|
|
5074
|
-
this._skipAuthRetry = flag;
|
|
5075
|
-
return this;
|
|
5076
|
-
}
|
|
5077
|
-
isSkipAuthRetry() {
|
|
5078
|
-
return this._skipAuthRetry;
|
|
5079
|
-
}
|
|
5080
|
-
getBody() {
|
|
5081
|
-
return this._body;
|
|
5082
|
-
}
|
|
5083
|
-
getHeaders() {
|
|
5084
|
-
return { ...this._headers };
|
|
5085
|
-
}
|
|
5086
|
-
getQuery() {
|
|
5087
|
-
return [...this._query];
|
|
5088
|
-
}
|
|
5089
|
-
};
|
|
5090
|
-
|
|
5091
|
-
// src/http/rest-client.ts
|
|
5092
|
-
import { consola } from "consola";
|
|
5093
|
-
|
|
5094
|
-
// src/http/transport.ts
|
|
5095
|
-
var defaultTransport = (url, init) => fetch(url, init);
|
|
5096
|
-
|
|
5097
|
-
// src/http/retry-policy.ts
|
|
5098
|
-
function defaultRetryPolicy() {
|
|
5099
|
-
return {
|
|
5100
|
-
maxRetries: 3,
|
|
5101
|
-
baseDelayMs: 500,
|
|
5102
|
-
maxDelayMs: 3e4,
|
|
5103
|
-
retryableStatusCodes: [429, 500, 502, 503, 504],
|
|
5104
|
-
retryNetworkErrors: true
|
|
5105
|
-
};
|
|
5106
|
-
}
|
|
5107
|
-
function calculateBackoff(attempt, policy) {
|
|
5108
|
-
const exponential = policy.baseDelayMs * Math.pow(2, attempt);
|
|
5109
|
-
const jitter = Math.random() * policy.baseDelayMs;
|
|
5110
|
-
return Math.min(exponential + jitter, policy.maxDelayMs);
|
|
5111
|
-
}
|
|
5112
|
-
function parseRetryAfter(header) {
|
|
5113
|
-
if (!header) return null;
|
|
5114
|
-
const seconds = Number(header);
|
|
5115
|
-
if (!Number.isNaN(seconds)) {
|
|
5116
|
-
return seconds * 1e3;
|
|
5117
|
-
}
|
|
5118
|
-
const date = new Date(header);
|
|
5119
|
-
if (!Number.isNaN(date.getTime())) {
|
|
5120
|
-
return Math.max(0, date.getTime() - Date.now());
|
|
5121
|
-
}
|
|
5122
|
-
return null;
|
|
5123
|
-
}
|
|
5124
|
-
var RETRYABLE_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
5125
|
-
"ECONNRESET",
|
|
5126
|
-
"ECONNREFUSED",
|
|
5127
|
-
"ETIMEDOUT",
|
|
5128
|
-
"UND_ERR_CONNECT_TIMEOUT"
|
|
5129
|
-
]);
|
|
5130
|
-
function isRetryableError(error, policy) {
|
|
5131
|
-
if (!policy.retryNetworkErrors) return false;
|
|
5132
|
-
if (!(error instanceof Error)) return false;
|
|
5133
|
-
if (error.name === "AbortError") return true;
|
|
5134
|
-
const code = error.code;
|
|
5135
|
-
if (code && RETRYABLE_ERROR_CODES.has(code)) return true;
|
|
5136
|
-
return false;
|
|
5137
|
-
}
|
|
5138
|
-
function isRetryableStatus(status, policy) {
|
|
5139
|
-
return policy.retryableStatusCodes.includes(status);
|
|
5140
|
-
}
|
|
5141
|
-
function sleep(ms) {
|
|
5142
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5143
|
-
}
|
|
5144
|
-
|
|
5145
|
-
// src/http/presigned-url-policy.ts
|
|
5146
|
-
function defaultPresignedUrlPolicy() {
|
|
5147
|
-
return {
|
|
5148
|
-
allowedHosts: ["*.ksef.mf.gov.pl"],
|
|
5149
|
-
requireHttps: true,
|
|
5150
|
-
blockRedirectParams: true,
|
|
5151
|
-
rejectPrivateIps: true
|
|
5152
|
-
};
|
|
5153
|
-
}
|
|
5154
|
-
function validatePresignedUrl(url, policy) {
|
|
5155
|
-
const parsed = new URL(url);
|
|
5156
|
-
if (policy.requireHttps && parsed.protocol !== "https:") {
|
|
5157
|
-
throw new KSeFValidationError(`Presigned URL must use HTTPS: ${url}`);
|
|
5158
|
-
}
|
|
5159
|
-
if (!matchesAllowedHost(parsed.hostname, policy.allowedHosts)) {
|
|
5160
|
-
throw new KSeFValidationError(
|
|
5161
|
-
`Presigned URL host '${parsed.hostname}' is not in the allowed hosts list`
|
|
5162
|
-
);
|
|
5163
|
-
}
|
|
5164
|
-
if (policy.blockRedirectParams) {
|
|
5165
|
-
checkRedirectParams(parsed, url);
|
|
5166
|
-
}
|
|
5167
|
-
if (policy.rejectPrivateIps) {
|
|
5168
|
-
checkPrivateIp(parsed.hostname, url);
|
|
5169
|
-
}
|
|
5170
|
-
}
|
|
5171
|
-
function matchesAllowedHost(hostname, allowedHosts) {
|
|
5172
|
-
for (const pattern of allowedHosts) {
|
|
5173
|
-
if (pattern.startsWith("*.")) {
|
|
5174
|
-
const suffix = pattern.slice(1);
|
|
5175
|
-
if (hostname.endsWith(suffix) && hostname.length > suffix.length) {
|
|
5176
|
-
return true;
|
|
5177
|
-
}
|
|
5178
|
-
} else if (hostname === pattern) {
|
|
5179
|
-
return true;
|
|
5180
|
-
}
|
|
5181
|
-
}
|
|
5182
|
-
return false;
|
|
5183
|
-
}
|
|
5184
|
-
var BLOCKED_PARAMS = ["redirect", "callback", "return_url", "next"];
|
|
5185
|
-
function checkRedirectParams(parsed, originalUrl) {
|
|
5186
|
-
for (const [key] of parsed.searchParams) {
|
|
5187
|
-
if (BLOCKED_PARAMS.includes(key.toLowerCase())) {
|
|
5188
|
-
throw new KSeFValidationError(
|
|
5189
|
-
`Presigned URL contains blocked redirect parameter '${key}': ${originalUrl}`
|
|
5190
|
-
);
|
|
5191
|
-
}
|
|
5192
|
-
}
|
|
5193
|
-
}
|
|
5194
|
-
function checkPrivateIp(hostname, originalUrl) {
|
|
5195
|
-
const host = hostname.startsWith("[") ? hostname.slice(1, -1) : hostname;
|
|
5196
|
-
if (isPrivateIPv4(host) || isPrivateIPv6(host)) {
|
|
5197
|
-
throw new KSeFValidationError(
|
|
5198
|
-
`Presigned URL resolves to a private/reserved IP address '${hostname}': ${originalUrl}`
|
|
5199
|
-
);
|
|
5200
|
-
}
|
|
5201
|
-
}
|
|
5202
|
-
function isPrivateIPv4(ip) {
|
|
5203
|
-
const parts = ip.split(".");
|
|
5204
|
-
if (parts.length !== 4) return false;
|
|
5205
|
-
const nums = parts.map(Number);
|
|
5206
|
-
if (nums.some((n) => Number.isNaN(n))) return false;
|
|
5207
|
-
const a = nums[0];
|
|
5208
|
-
const b = nums[1];
|
|
5209
|
-
if (a === 127) return true;
|
|
5210
|
-
if (a === 10) return true;
|
|
5211
|
-
if (a === 172 && b >= 16 && b <= 31) return true;
|
|
5212
|
-
if (a === 192 && b === 168) return true;
|
|
5213
|
-
if (a === 169 && b === 254) return true;
|
|
5214
|
-
return false;
|
|
5215
|
-
}
|
|
5216
|
-
function isPrivateIPv6(ip) {
|
|
5217
|
-
const lower = ip.toLowerCase();
|
|
5218
|
-
if (lower === "::1") return true;
|
|
5219
|
-
if (lower.startsWith("fc") || lower.startsWith("fd")) return true;
|
|
5220
|
-
if (lower.startsWith("fe8") || lower.startsWith("fe9") || lower.startsWith("fea") || lower.startsWith("feb")) return true;
|
|
5221
|
-
return false;
|
|
5222
|
-
}
|
|
5223
|
-
|
|
5224
|
-
// src/http/rest-client.ts
|
|
5225
|
-
var RestClient = class {
|
|
5226
|
-
options;
|
|
5227
|
-
routeBuilder;
|
|
5228
|
-
transport;
|
|
5229
|
-
retryPolicy;
|
|
5230
|
-
rateLimitPolicy;
|
|
5231
|
-
authManager;
|
|
5232
|
-
presignedUrlPolicy;
|
|
5233
|
-
constructor(options, config) {
|
|
5234
|
-
this.options = options;
|
|
5235
|
-
this.routeBuilder = new RouteBuilder(options.apiVersion);
|
|
5236
|
-
this.transport = config?.transport ?? defaultTransport;
|
|
5237
|
-
this.retryPolicy = config?.retryPolicy ?? defaultRetryPolicy();
|
|
5238
|
-
this.rateLimitPolicy = config?.rateLimitPolicy ?? null;
|
|
5239
|
-
this.authManager = config?.authManager;
|
|
5240
|
-
this.presignedUrlPolicy = config?.presignedUrlPolicy;
|
|
5241
|
-
}
|
|
5242
|
-
async execute(request) {
|
|
5243
|
-
const response = await this.sendRequest(request);
|
|
5244
|
-
await this.ensureSuccess(response);
|
|
5245
|
-
const body = await response.json();
|
|
5246
|
-
return { body, headers: response.headers, statusCode: response.status };
|
|
5247
|
-
}
|
|
5248
|
-
async executeVoid(request) {
|
|
5249
|
-
const response = await this.sendRequest(request);
|
|
5250
|
-
await this.ensureSuccess(response);
|
|
5251
|
-
}
|
|
5252
|
-
async executeRaw(request) {
|
|
5253
|
-
const response = await this.sendRequest(request);
|
|
5254
|
-
await this.ensureSuccess(response);
|
|
5255
|
-
const body = await response.arrayBuffer();
|
|
5256
|
-
return { body, headers: response.headers, statusCode: response.status };
|
|
5257
|
-
}
|
|
5258
|
-
async sendRequest(request) {
|
|
5259
|
-
const url = this.buildUrl(request);
|
|
5260
|
-
if (request.isPresigned() && this.presignedUrlPolicy) {
|
|
5261
|
-
validatePresignedUrl(url, this.presignedUrlPolicy);
|
|
5262
|
-
}
|
|
5263
|
-
if (this.rateLimitPolicy) {
|
|
5264
|
-
await this.rateLimitPolicy.acquire(request.path);
|
|
5265
|
-
}
|
|
5266
|
-
let lastError;
|
|
5267
|
-
for (let attempt = 0; attempt <= this.retryPolicy.maxRetries; attempt++) {
|
|
5268
|
-
try {
|
|
5269
|
-
const response = await this.doRequest(request, url);
|
|
5270
|
-
if (response.status === 401 && this.authManager && attempt === 0 && !request.isSkipAuthRetry()) {
|
|
5271
|
-
const newToken = await this.authManager.onUnauthorized();
|
|
5272
|
-
if (newToken) {
|
|
5273
|
-
consola.debug("Auth token refreshed, retrying request");
|
|
5274
|
-
return this.doRequest(request, url, newToken);
|
|
5275
|
-
}
|
|
5276
|
-
}
|
|
5277
|
-
if (isRetryableStatus(response.status, this.retryPolicy) && attempt < this.retryPolicy.maxRetries) {
|
|
5278
|
-
const is429 = response.status === 429;
|
|
5279
|
-
const retryAfterMs = is429 ? parseRetryAfter(response.headers.get("Retry-After")) : null;
|
|
5280
|
-
const delayMs = retryAfterMs ?? calculateBackoff(attempt, this.retryPolicy);
|
|
5281
|
-
consola.debug(`Retryable ${response.status}, attempt ${attempt + 1}/${this.retryPolicy.maxRetries}, waiting ${Math.round(delayMs)}ms`);
|
|
5282
|
-
await sleep(delayMs);
|
|
5283
|
-
if (is429 && this.rateLimitPolicy) {
|
|
5284
|
-
await this.rateLimitPolicy.acquire(request.path);
|
|
5285
|
-
}
|
|
5286
|
-
continue;
|
|
6774
|
+
if (!key) {
|
|
6775
|
+
throw new Error("PKCS#12 key bag is empty.");
|
|
5287
6776
|
}
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
6777
|
+
const certificatePem = pki.certificateToPem(cert);
|
|
6778
|
+
let privateKeyPem;
|
|
6779
|
+
try {
|
|
6780
|
+
privateKeyPem = pki.privateKeyToPem(key);
|
|
6781
|
+
} catch {
|
|
6782
|
+
throw new Error(
|
|
6783
|
+
"Failed to export private key from PKCS#12 to PEM. This can happen with EC keys. Use separate --cert and --key PEM files instead."
|
|
6784
|
+
);
|
|
5296
6785
|
}
|
|
5297
|
-
|
|
6786
|
+
return { certificatePem, privateKeyPem };
|
|
5298
6787
|
}
|
|
5299
|
-
}
|
|
5300
|
-
throw lastError;
|
|
5301
|
-
}
|
|
5302
|
-
async doRequest(request, url, overrideToken) {
|
|
5303
|
-
const headers = {
|
|
5304
|
-
...this.options.customHeaders,
|
|
5305
|
-
...request.getHeaders()
|
|
5306
6788
|
};
|
|
5307
|
-
if (!headers["Authorization"] && this.authManager) {
|
|
5308
|
-
const token = overrideToken ?? this.authManager.getAccessToken();
|
|
5309
|
-
if (token) {
|
|
5310
|
-
headers["Authorization"] = `Bearer ${token}`;
|
|
5311
|
-
}
|
|
5312
|
-
}
|
|
5313
|
-
const rawBody = request.getBody();
|
|
5314
|
-
if (rawBody !== void 0 && !headers["Content-Type"]) {
|
|
5315
|
-
headers["Content-Type"] = "application/json";
|
|
5316
|
-
}
|
|
5317
|
-
let body;
|
|
5318
|
-
if (rawBody !== void 0) {
|
|
5319
|
-
body = typeof rawBody === "string" ? rawBody : JSON.stringify(rawBody);
|
|
5320
|
-
}
|
|
5321
|
-
const start = performance.now();
|
|
5322
|
-
const response = await this.transport(url, {
|
|
5323
|
-
method: request.method,
|
|
5324
|
-
headers,
|
|
5325
|
-
body,
|
|
5326
|
-
signal: AbortSignal.timeout(this.options.timeout)
|
|
5327
|
-
});
|
|
5328
|
-
const elapsed = Math.round(performance.now() - start);
|
|
5329
|
-
consola.debug(`${request.method} ${url} \u2192 ${response.status} (${elapsed}ms)`);
|
|
5330
|
-
return response;
|
|
5331
|
-
}
|
|
5332
|
-
buildUrl(request) {
|
|
5333
|
-
const path = this.routeBuilder.build(request.path);
|
|
5334
|
-
const base = this.options.baseUrl;
|
|
5335
|
-
const url = new URL(`${base}${path}`);
|
|
5336
|
-
const query = request.getQuery();
|
|
5337
|
-
for (const [key, value] of query) {
|
|
5338
|
-
url.searchParams.append(key, value);
|
|
5339
|
-
}
|
|
5340
|
-
return url.toString();
|
|
5341
6789
|
}
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
|
-
|
|
5349
|
-
|
|
6790
|
+
});
|
|
6791
|
+
|
|
6792
|
+
// src/qr/verification-link-service.ts
|
|
6793
|
+
import crypto5 from "crypto";
|
|
6794
|
+
var VerificationLinkService;
|
|
6795
|
+
var init_verification_link_service = __esm({
|
|
6796
|
+
"src/qr/verification-link-service.ts"() {
|
|
6797
|
+
"use strict";
|
|
6798
|
+
VerificationLinkService = class {
|
|
6799
|
+
constructor(baseQrUrl) {
|
|
6800
|
+
this.baseQrUrl = baseQrUrl;
|
|
5350
6801
|
}
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
throw new KSeFUnauthorizedError(body);
|
|
6802
|
+
/**
|
|
6803
|
+
* Build invoice verification URL (Code I).
|
|
6804
|
+
* Format: {baseQrUrl}/invoice/{NIP}/{DD-MM-YYYY}/{hash_base64url}
|
|
6805
|
+
*/
|
|
6806
|
+
buildInvoiceVerificationUrl(nip, issueDate, invoiceHashBase64) {
|
|
6807
|
+
const date = typeof issueDate === "string" ? new Date(issueDate) : issueDate;
|
|
6808
|
+
const dd = String(date.getUTCDate()).padStart(2, "0");
|
|
6809
|
+
const mm = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
6810
|
+
const yyyy = date.getUTCFullYear();
|
|
6811
|
+
const dateStr = `${dd}-${mm}-${yyyy}`;
|
|
6812
|
+
const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
|
|
6813
|
+
return `${this.baseQrUrl}/invoice/${nip}/${dateStr}/${hashBase64Url}`;
|
|
5364
6814
|
}
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
6815
|
+
/**
|
|
6816
|
+
* Build certificate verification URL (Code II).
|
|
6817
|
+
* Format: {baseQrUrl}/certificate/{contextType}/{contextId}/{sellerNip}/{certSerial}/{hash_base64url}/{signature_base64url}
|
|
6818
|
+
*/
|
|
6819
|
+
buildCertificateVerificationUrl(contextType, contextId, sellerNip, certSerial, invoiceHashBase64, privateKeyPem) {
|
|
6820
|
+
const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
|
|
6821
|
+
const pathWithoutSignature = `${this.baseQrUrl}/certificate/${contextType}/${contextId}/${sellerNip}/${certSerial}/${hashBase64Url}`;
|
|
6822
|
+
const dataToSign = pathWithoutSignature.replace(/^https?:\/\//, "");
|
|
6823
|
+
const key = crypto5.createPrivateKey(privateKeyPem);
|
|
6824
|
+
let signature;
|
|
6825
|
+
if (key.asymmetricKeyType === "rsa") {
|
|
6826
|
+
signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
|
|
6827
|
+
key,
|
|
6828
|
+
padding: crypto5.constants.RSA_PKCS1_PSS_PADDING,
|
|
6829
|
+
saltLength: 32
|
|
6830
|
+
});
|
|
6831
|
+
} else if (key.asymmetricKeyType === "ec") {
|
|
6832
|
+
signature = crypto5.sign("sha256", Buffer.from(dataToSign), {
|
|
6833
|
+
key,
|
|
6834
|
+
dsaEncoding: "ieee-p1363"
|
|
6835
|
+
});
|
|
6836
|
+
} else {
|
|
6837
|
+
throw new Error(`Unsupported key type: ${key.asymmetricKeyType}`);
|
|
6838
|
+
}
|
|
6839
|
+
const signatureBase64Url = signature.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6840
|
+
return `${pathWithoutSignature}/${signatureBase64Url}`;
|
|
5370
6841
|
}
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
};
|
|
5375
|
-
|
|
5376
|
-
// src/http/routes.ts
|
|
5377
|
-
var Routes = {
|
|
5378
|
-
TestData: {
|
|
5379
|
-
createSubject: "testdata/subject",
|
|
5380
|
-
removeSubject: "testdata/subject/remove",
|
|
5381
|
-
createPerson: "testdata/person",
|
|
5382
|
-
removePerson: "testdata/person/remove",
|
|
5383
|
-
grantPerms: "testdata/permissions",
|
|
5384
|
-
revokePerms: "testdata/permissions/revoke",
|
|
5385
|
-
enableAttach: "testdata/attachment",
|
|
5386
|
-
disableAttach: "testdata/attachment/revoke",
|
|
5387
|
-
changeSessionLimitsInCurrentContext: "testdata/limits/context/session",
|
|
5388
|
-
restoreDefaultSessionLimitsInCurrentContext: "testdata/limits/context/session",
|
|
5389
|
-
changeCertificatesLimitInCurrentSubject: "testdata/limits/subject/certificate",
|
|
5390
|
-
restoreDefaultCertificatesLimitInCurrentSubject: "testdata/limits/subject/certificate",
|
|
5391
|
-
rateLimits: "testdata/rate-limits",
|
|
5392
|
-
productionRateLimits: "testdata/rate-limits/production",
|
|
5393
|
-
blockContext: "testdata/context/block",
|
|
5394
|
-
unblockContext: "testdata/context/unblock"
|
|
5395
|
-
},
|
|
5396
|
-
Limits: {
|
|
5397
|
-
currentContext: "limits/context",
|
|
5398
|
-
currentSubject: "limits/subject",
|
|
5399
|
-
rateLimits: "rate-limits"
|
|
5400
|
-
},
|
|
5401
|
-
ActiveSessions: {
|
|
5402
|
-
session: "auth/sessions",
|
|
5403
|
-
delete: (ref) => `auth/sessions/${ref}`,
|
|
5404
|
-
currentSession: "auth/sessions/current"
|
|
5405
|
-
},
|
|
5406
|
-
Authorization: {
|
|
5407
|
-
challenge: "auth/challenge",
|
|
5408
|
-
xadesSignature: "auth/xades-signature",
|
|
5409
|
-
ksefToken: "auth/ksef-token",
|
|
5410
|
-
status: (ref) => `auth/${ref}`,
|
|
5411
|
-
Token: {
|
|
5412
|
-
redeem: "auth/token/redeem",
|
|
5413
|
-
refresh: "auth/token/refresh"
|
|
5414
|
-
}
|
|
5415
|
-
},
|
|
5416
|
-
Sessions: {
|
|
5417
|
-
root: "sessions",
|
|
5418
|
-
byReference: (ref) => `sessions/${ref}`,
|
|
5419
|
-
invoices: (ref) => `sessions/${ref}/invoices`,
|
|
5420
|
-
invoice: (ref, invoiceRef) => `sessions/${ref}/invoices/${invoiceRef}`,
|
|
5421
|
-
failedInvoices: (ref) => `sessions/${ref}/invoices/failed`,
|
|
5422
|
-
upoByKsefNumber: (ref, ksefNumber) => `sessions/${ref}/invoices/ksef/${ksefNumber}/upo`,
|
|
5423
|
-
upoByInvoiceReference: (ref, invoiceRef) => `sessions/${ref}/invoices/${invoiceRef}/upo`,
|
|
5424
|
-
upo: (ref, upoRef) => `sessions/${ref}/upo/${upoRef}`,
|
|
5425
|
-
Online: {
|
|
5426
|
-
open: "sessions/online",
|
|
5427
|
-
invoices: (sessionRef) => `sessions/online/${sessionRef}/invoices`,
|
|
5428
|
-
close: (sessionRef) => `sessions/online/${sessionRef}/close`
|
|
5429
|
-
},
|
|
5430
|
-
Batch: {
|
|
5431
|
-
open: "sessions/batch",
|
|
5432
|
-
close: (batchRef) => `sessions/batch/${batchRef}/close`
|
|
5433
|
-
}
|
|
5434
|
-
},
|
|
5435
|
-
Invoices: {
|
|
5436
|
-
byKsefNumber: (ksefNumber) => `invoices/ksef/${ksefNumber}`,
|
|
5437
|
-
queryMetadata: "invoices/query/metadata",
|
|
5438
|
-
exports: "invoices/exports",
|
|
5439
|
-
exportByReference: (ref) => `invoices/exports/${ref}`
|
|
5440
|
-
},
|
|
5441
|
-
Permissions: {
|
|
5442
|
-
Grants: {
|
|
5443
|
-
persons: "permissions/persons/grants",
|
|
5444
|
-
entities: "permissions/entities/grants",
|
|
5445
|
-
authorizations: "permissions/authorizations/grants",
|
|
5446
|
-
indirect: "permissions/indirect/grants",
|
|
5447
|
-
subunits: "permissions/subunits/grants",
|
|
5448
|
-
euEntities: "permissions/eu-entities/administration/grants",
|
|
5449
|
-
euEntitiesRepresentatives: "permissions/eu-entities/grants"
|
|
5450
|
-
},
|
|
5451
|
-
Common: {
|
|
5452
|
-
grantById: (id) => `permissions/common/grants/${id}`
|
|
5453
|
-
},
|
|
5454
|
-
Authorizations: {
|
|
5455
|
-
grantById: (id) => `permissions/authorizations/grants/${id}`
|
|
5456
|
-
},
|
|
5457
|
-
Query: {
|
|
5458
|
-
personalGrants: "permissions/query/personal/grants",
|
|
5459
|
-
personsGrants: "permissions/query/persons/grants",
|
|
5460
|
-
subunitsGrants: "permissions/query/subunits/grants",
|
|
5461
|
-
entitiesRoles: "permissions/query/entities/roles",
|
|
5462
|
-
entitiesGrants: "permissions/query/entities/grants",
|
|
5463
|
-
subordinateEntitiesRoles: "permissions/query/subordinate-entities/roles",
|
|
5464
|
-
authorizationsGrants: "permissions/query/authorizations/grants",
|
|
5465
|
-
euEntitiesGrants: "permissions/query/eu-entities/grants"
|
|
5466
|
-
},
|
|
5467
|
-
Operations: {
|
|
5468
|
-
byReference: (ref) => `permissions/operations/${ref}`
|
|
5469
|
-
},
|
|
5470
|
-
Attachments: {
|
|
5471
|
-
status: "permissions/attachments/status"
|
|
5472
|
-
}
|
|
5473
|
-
},
|
|
5474
|
-
Certificates: {
|
|
5475
|
-
limits: "certificates/limits",
|
|
5476
|
-
enrollmentData: "certificates/enrollments/data",
|
|
5477
|
-
enrollments: "certificates/enrollments",
|
|
5478
|
-
enrollmentStatus: (ref) => `certificates/enrollments/${ref}`,
|
|
5479
|
-
retrieve: "certificates/retrieve",
|
|
5480
|
-
revoke: (serialNumber) => `certificates/${serialNumber}/revoke`,
|
|
5481
|
-
query: "certificates/query"
|
|
5482
|
-
},
|
|
5483
|
-
Tokens: {
|
|
5484
|
-
root: "tokens",
|
|
5485
|
-
byReference: (ref) => `tokens/${ref}`
|
|
5486
|
-
},
|
|
5487
|
-
Peppol: {
|
|
5488
|
-
query: "peppol/query"
|
|
5489
|
-
},
|
|
5490
|
-
Security: {
|
|
5491
|
-
publicKeyCertificates: "security/public-key-certificates"
|
|
5492
|
-
},
|
|
5493
|
-
Lighthouse: {
|
|
5494
|
-
status: "status",
|
|
5495
|
-
messages: "messages"
|
|
6842
|
+
base64ToBase64Url(base64) {
|
|
6843
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6844
|
+
}
|
|
6845
|
+
};
|
|
5496
6846
|
}
|
|
5497
|
-
};
|
|
6847
|
+
});
|
|
5498
6848
|
|
|
5499
|
-
// src/
|
|
5500
|
-
var
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
6849
|
+
// src/client.ts
|
|
6850
|
+
var client_exports = {};
|
|
6851
|
+
__export(client_exports, {
|
|
6852
|
+
KSeFClient: () => KSeFClient,
|
|
6853
|
+
buildAuthTokenRequestXml: () => buildAuthTokenRequestXml
|
|
6854
|
+
});
|
|
6855
|
+
function buildAuthTokenRequestXml(challenge, nip, subjectIdentifierType = "certificateSubject") {
|
|
6856
|
+
return [
|
|
6857
|
+
'<?xml version="1.0" encoding="utf-8"?>',
|
|
6858
|
+
`<AuthTokenRequest xmlns="${AUTH_TOKEN_REQUEST_NS}">`,
|
|
6859
|
+
`<Challenge>${xmlEscape(challenge)}</Challenge>`,
|
|
6860
|
+
`<ContextIdentifier>`,
|
|
6861
|
+
`<Nip>${xmlEscape(nip)}</Nip>`,
|
|
6862
|
+
`</ContextIdentifier>`,
|
|
6863
|
+
`<SubjectIdentifierType>${xmlEscape(subjectIdentifierType)}</SubjectIdentifierType>`,
|
|
6864
|
+
`</AuthTokenRequest>`
|
|
6865
|
+
].join("");
|
|
6866
|
+
}
|
|
6867
|
+
function xmlEscape(str) {
|
|
6868
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
6869
|
+
}
|
|
6870
|
+
function buildRestClientConfig(options, authManager) {
|
|
6871
|
+
const config = { authManager };
|
|
6872
|
+
if (options?.transport) {
|
|
6873
|
+
config.transport = options.transport;
|
|
5522
6874
|
}
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
const elapsed = now - this.lastRefill;
|
|
5526
|
-
this.tokens = Math.min(this.maxTokens, this.tokens + elapsed * this.refillRate);
|
|
5527
|
-
this.lastRefill = now;
|
|
6875
|
+
if (options?.retry) {
|
|
6876
|
+
config.retryPolicy = { ...defaultRetryPolicy(), ...options.retry };
|
|
5528
6877
|
}
|
|
5529
|
-
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
constructor(config) {
|
|
5536
|
-
this.globalBucket = new TokenBucket(config.globalRps);
|
|
5537
|
-
this.endpointLimits = config.endpointLimits ?? {};
|
|
5538
|
-
}
|
|
5539
|
-
async acquire(endpoint) {
|
|
5540
|
-
return new Promise((resolve, reject) => {
|
|
5541
|
-
this.chain = this.chain.then(() => this.doAcquire(endpoint)).then(resolve, reject);
|
|
6878
|
+
if (options?.rateLimit === null) {
|
|
6879
|
+
config.rateLimitPolicy = null;
|
|
6880
|
+
} else if (options?.rateLimit) {
|
|
6881
|
+
config.rateLimitPolicy = new RateLimitPolicy({
|
|
6882
|
+
globalRps: options.rateLimit.globalRps ?? 10,
|
|
6883
|
+
endpointLimits: options.rateLimit.endpointLimits
|
|
5542
6884
|
});
|
|
5543
6885
|
}
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
bucket = new TokenBucket(limit);
|
|
5551
|
-
this.endpointBuckets.set(endpoint, bucket);
|
|
5552
|
-
}
|
|
5553
|
-
await bucket.acquire();
|
|
5554
|
-
}
|
|
6886
|
+
if (options?.presignedUrlHosts) {
|
|
6887
|
+
const base = defaultPresignedUrlPolicy();
|
|
6888
|
+
config.presignedUrlPolicy = {
|
|
6889
|
+
...base,
|
|
6890
|
+
allowedHosts: [...base.allowedHosts, ...options.presignedUrlHosts]
|
|
6891
|
+
};
|
|
5555
6892
|
}
|
|
5556
|
-
|
|
5557
|
-
function defaultRateLimitPolicy() {
|
|
5558
|
-
return new RateLimitPolicy({ globalRps: 10 });
|
|
6893
|
+
return config;
|
|
5559
6894
|
}
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5568
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
5572
|
-
|
|
5573
|
-
|
|
5574
|
-
|
|
5575
|
-
|
|
5576
|
-
|
|
5577
|
-
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
6895
|
+
var KSeFClient, AUTH_TOKEN_REQUEST_NS;
|
|
6896
|
+
var init_client = __esm({
|
|
6897
|
+
"src/client.ts"() {
|
|
6898
|
+
"use strict";
|
|
6899
|
+
init_config();
|
|
6900
|
+
init_rest_client();
|
|
6901
|
+
init_retry_policy();
|
|
6902
|
+
init_rate_limit_policy();
|
|
6903
|
+
init_presigned_url_policy();
|
|
6904
|
+
init_auth_manager();
|
|
6905
|
+
init_auth();
|
|
6906
|
+
init_active_sessions();
|
|
6907
|
+
init_online_session();
|
|
6908
|
+
init_batch_session();
|
|
6909
|
+
init_session_status();
|
|
6910
|
+
init_invoice_download();
|
|
6911
|
+
init_permissions();
|
|
6912
|
+
init_tokens();
|
|
6913
|
+
init_certificates();
|
|
6914
|
+
init_lighthouse();
|
|
6915
|
+
init_limits();
|
|
6916
|
+
init_peppol();
|
|
6917
|
+
init_test_data();
|
|
6918
|
+
init_certificate_fetcher();
|
|
6919
|
+
init_cryptography_service();
|
|
6920
|
+
init_verification_link_service();
|
|
6921
|
+
KSeFClient = class {
|
|
6922
|
+
auth;
|
|
6923
|
+
activeSessions;
|
|
6924
|
+
onlineSession;
|
|
6925
|
+
batchSession;
|
|
6926
|
+
sessionStatus;
|
|
6927
|
+
invoices;
|
|
6928
|
+
permissions;
|
|
6929
|
+
tokens;
|
|
6930
|
+
certificates;
|
|
6931
|
+
lighthouse;
|
|
6932
|
+
limits;
|
|
6933
|
+
peppol;
|
|
6934
|
+
testData;
|
|
6935
|
+
crypto;
|
|
6936
|
+
qr;
|
|
6937
|
+
options;
|
|
6938
|
+
authManager;
|
|
6939
|
+
constructor(options) {
|
|
6940
|
+
this.options = resolveOptions(options);
|
|
6941
|
+
const authManager = options?.authManager ?? new DefaultAuthManager(async () => {
|
|
6942
|
+
const rt = this.authManager.getRefreshToken();
|
|
6943
|
+
if (!rt) return null;
|
|
6944
|
+
const res = await this.auth.refreshAccessToken(rt);
|
|
6945
|
+
return res.accessToken.token;
|
|
6946
|
+
});
|
|
6947
|
+
this.authManager = authManager;
|
|
6948
|
+
const restClientConfig = buildRestClientConfig(options, authManager);
|
|
6949
|
+
const restClient = new RestClient(this.options, restClientConfig);
|
|
6950
|
+
const fetcher = new CertificateFetcher(restClient);
|
|
6951
|
+
this.crypto = new CryptographyService(fetcher);
|
|
6952
|
+
this.auth = new AuthService(restClient);
|
|
6953
|
+
this.activeSessions = new ActiveSessionsService(restClient);
|
|
6954
|
+
this.onlineSession = new OnlineSessionService(restClient);
|
|
6955
|
+
this.batchSession = new BatchSessionService(restClient);
|
|
6956
|
+
this.sessionStatus = new SessionStatusService(restClient);
|
|
6957
|
+
this.invoices = new InvoiceDownloadService(restClient);
|
|
6958
|
+
this.permissions = new PermissionsService(restClient);
|
|
6959
|
+
this.tokens = new TokenService(restClient);
|
|
6960
|
+
this.certificates = new CertificateApiService(restClient);
|
|
6961
|
+
this.lighthouse = new LighthouseService(this.options);
|
|
6962
|
+
this.limits = new LimitsService(restClient);
|
|
6963
|
+
this.peppol = new PeppolService(restClient);
|
|
6964
|
+
this.testData = new TestDataService(restClient, this.options.environmentName);
|
|
6965
|
+
this.qr = new VerificationLinkService(this.options.baseQrUrl);
|
|
6966
|
+
}
|
|
6967
|
+
async loginWithToken(token, nip) {
|
|
6968
|
+
const challenge = await this.auth.getChallenge();
|
|
6969
|
+
await this.crypto.init();
|
|
6970
|
+
const encryptedToken = this.crypto.encryptKsefToken(token, challenge.timestamp);
|
|
6971
|
+
const submitResult = await this.auth.submitKsefTokenAuthRequest({
|
|
6972
|
+
challenge: challenge.challenge,
|
|
6973
|
+
contextIdentifier: { type: "Nip", value: nip },
|
|
6974
|
+
encryptedToken: Buffer.from(encryptedToken).toString("base64")
|
|
6975
|
+
});
|
|
6976
|
+
const authToken = submitResult.authenticationToken.token;
|
|
6977
|
+
await this.awaitAuthReady(submitResult.referenceNumber, authToken);
|
|
6978
|
+
const tokens = await this.auth.getAccessToken(authToken);
|
|
6979
|
+
this.authManager.setAccessToken(tokens.accessToken.token);
|
|
6980
|
+
this.authManager.setRefreshToken(tokens.refreshToken.token);
|
|
6981
|
+
}
|
|
6982
|
+
async loginWithCertificate(certPem, keyPem, nip) {
|
|
6983
|
+
const challenge = await this.auth.getChallenge();
|
|
6984
|
+
const authRequestXml = buildAuthTokenRequestXml(challenge.challenge, nip);
|
|
6985
|
+
const { SignatureService: SignatureService2 } = await Promise.resolve().then(() => (init_signature_service(), signature_service_exports));
|
|
6986
|
+
const signedXml = SignatureService2.sign(authRequestXml, certPem, keyPem);
|
|
6987
|
+
const submitResult = await this.auth.submitXadesAuthRequest(signedXml);
|
|
6988
|
+
const authToken = submitResult.authenticationToken.token;
|
|
6989
|
+
await this.awaitAuthReady(submitResult.referenceNumber, authToken);
|
|
6990
|
+
const tokens = await this.auth.getAccessToken(authToken);
|
|
6991
|
+
this.authManager.setAccessToken(tokens.accessToken.token);
|
|
6992
|
+
this.authManager.setRefreshToken(tokens.refreshToken.token);
|
|
6993
|
+
}
|
|
6994
|
+
async loginWithPkcs12(p12, password, nip) {
|
|
6995
|
+
const { Pkcs12Loader: Pkcs12Loader2 } = await Promise.resolve().then(() => (init_pkcs12_loader(), pkcs12_loader_exports));
|
|
6996
|
+
const { certificatePem, privateKeyPem } = Pkcs12Loader2.load(p12, password);
|
|
6997
|
+
await this.loginWithCertificate(certificatePem, privateKeyPem, nip);
|
|
6998
|
+
}
|
|
6999
|
+
async awaitAuthReady(referenceNumber, authToken) {
|
|
7000
|
+
for (let i = 0; i < 30; i++) {
|
|
7001
|
+
const status = await this.auth.getAuthStatus(referenceNumber, authToken);
|
|
7002
|
+
if (status.status.code === 200) return;
|
|
7003
|
+
if (status.status.code !== 100) {
|
|
7004
|
+
throw new Error(`Authentication failed with status ${status.status.code}: ${status.status.description}`);
|
|
7005
|
+
}
|
|
7006
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
7007
|
+
}
|
|
7008
|
+
}
|
|
7009
|
+
async logout() {
|
|
7010
|
+
this.authManager.setAccessToken(void 0);
|
|
7011
|
+
this.authManager.setRefreshToken(void 0);
|
|
7012
|
+
}
|
|
7013
|
+
};
|
|
7014
|
+
AUTH_TOKEN_REQUEST_NS = "http://ksef.mf.gov.pl/auth/token/2.0";
|
|
5592
7015
|
}
|
|
5593
|
-
};
|
|
7016
|
+
});
|
|
7017
|
+
|
|
7018
|
+
// src/index.ts
|
|
7019
|
+
init_config();
|
|
7020
|
+
init_errors();
|
|
7021
|
+
|
|
7022
|
+
// src/http/index.ts
|
|
7023
|
+
init_route_builder();
|
|
7024
|
+
init_rest_request();
|
|
7025
|
+
init_rest_client();
|
|
7026
|
+
init_routes();
|
|
7027
|
+
init_transport();
|
|
7028
|
+
init_retry_policy();
|
|
7029
|
+
init_rate_limit_policy();
|
|
7030
|
+
init_auth_manager();
|
|
7031
|
+
init_presigned_url_policy();
|
|
7032
|
+
init_ksef_feature();
|
|
5594
7033
|
|
|
5595
7034
|
// src/validation/patterns.ts
|
|
5596
7035
|
var NIP_PATTERN_CORE = "[1-9]((\\d[1-9])|([1-9]\\d))\\d{7}";
|
|
@@ -5602,681 +7041,127 @@ var InternalId = /^[1-9]((\d[1-9])|([1-9]\d))\d{7}-\d{5}$/;
|
|
|
5602
7041
|
var PeppolId = /^P[A-Z]{2}[0-9]{6}$/;
|
|
5603
7042
|
var ReferenceNumber = /^(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-Z]{2})-([0-9A-F]{10})-([0-9A-F]{10})-([0-9A-F]{2})$/;
|
|
5604
7043
|
var KsefNumber = /^([1-9](\d[1-9]|[1-9]\d)\d{7})-(20[2-9][0-9]|2[1-9]\d{2}|[3-9]\d{3})(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])-([0-9A-F]{6})-?([0-9A-F]{6})-([0-9A-F]{2})$/;
|
|
5605
|
-
var KsefNumberV35 = /^([1-9]((\d[1-9])|([1-9]\d))\d{7}|M\d{9}|[A-Z]{3}\d{7})-(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-F]{6})([0-9A-F]{6})-([0-9A-F]{2})$/;
|
|
5606
|
-
var KsefNumberV36 = /^([1-9]((\d[1-9])|([1-9]\d))\d{7}|M\d{9}|[A-Z]{3}\d{7})-(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-F]{6})-([0-9A-F]{6})-([0-9A-F]{2})$/;
|
|
5607
|
-
var CertificateName = /^[a-zA-Z0-9_\- ąćęłńóśźżĄĆĘŁŃÓŚŹŻ]+$/;
|
|
5608
|
-
var Pesel = /^\d{2}(?:0[1-9]|1[0-2]|2[1-9]|3[0-2]|4[1-9]|5[0-2]|6[1-9]|7[0-2]|8[1-9]|9[0-2])\d{7}$/;
|
|
5609
|
-
var CertificateFingerprint = /^[0-9A-F]{64}$/;
|
|
5610
|
-
var Base64String = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
5611
|
-
var Ip4Address = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
5612
|
-
var Ip4Range = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}-((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
5613
|
-
var Ip4Mask = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}\/(0|[1-9]|1[0-9]|2[0-9]|3[0-2])$/;
|
|
5614
|
-
var Sha256Base64 = /^[A-Za-z0-9+/]{43}=$/;
|
|
5615
|
-
var NIP_WEIGHTS = [6, 5, 7, 2, 3, 4, 5, 6, 7];
|
|
5616
|
-
var PESEL_WEIGHTS = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
let
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
}
|
|
5626
|
-
function isValidVatUe(value) {
|
|
5627
|
-
return VatUe.test(value);
|
|
5628
|
-
}
|
|
5629
|
-
function isValidNipVatUe(value) {
|
|
5630
|
-
return NipVatUe.test(value);
|
|
5631
|
-
}
|
|
5632
|
-
function isValidInternalId(value) {
|
|
5633
|
-
return InternalId.test(value);
|
|
5634
|
-
}
|
|
5635
|
-
function isValidPeppolId(value) {
|
|
5636
|
-
return PeppolId.test(value);
|
|
5637
|
-
}
|
|
5638
|
-
function isValidReferenceNumber(value) {
|
|
5639
|
-
return ReferenceNumber.test(value);
|
|
5640
|
-
}
|
|
5641
|
-
function isValidKsefNumber(value) {
|
|
5642
|
-
return KsefNumber.test(value);
|
|
5643
|
-
}
|
|
5644
|
-
function isValidPesel(value) {
|
|
5645
|
-
if (!Pesel.test(value)) return false;
|
|
5646
|
-
let sum = 0;
|
|
5647
|
-
for (let i = 0; i < 10; i++) {
|
|
5648
|
-
sum += Number(value[i]) * PESEL_WEIGHTS[i];
|
|
5649
|
-
}
|
|
5650
|
-
const checksum = (10 - sum % 10) % 10;
|
|
5651
|
-
return checksum === Number(value[10]);
|
|
5652
|
-
}
|
|
5653
|
-
function isValidCertificateName(value) {
|
|
5654
|
-
return CertificateName.test(value);
|
|
5655
|
-
}
|
|
5656
|
-
function isValidCertificateFingerprint(value) {
|
|
5657
|
-
return CertificateFingerprint.test(value);
|
|
5658
|
-
}
|
|
5659
|
-
function isValidBase64(value) {
|
|
5660
|
-
return Base64String.test(value);
|
|
5661
|
-
}
|
|
5662
|
-
function isValidIp4Address(value) {
|
|
5663
|
-
return Ip4Address.test(value);
|
|
5664
|
-
}
|
|
5665
|
-
function isValidSha256Base64(value) {
|
|
5666
|
-
return Sha256Base64.test(value);
|
|
5667
|
-
}
|
|
5668
|
-
|
|
5669
|
-
// src/validation/constraints.ts
|
|
5670
|
-
var REQUIRED_CHALLENGE_LENGTH = 36;
|
|
5671
|
-
var CERTIFICATE_NAME_MIN_LENGTH = 5;
|
|
5672
|
-
var CERTIFICATE_NAME_MAX_LENGTH = 100;
|
|
5673
|
-
var SUBUNIT_NAME_MIN_LENGTH = 5;
|
|
5674
|
-
var SUBUNIT_NAME_MAX_LENGTH = 256;
|
|
5675
|
-
var PERMISSION_DESCRIPTION_MIN_LENGTH = 5;
|
|
5676
|
-
var PERMISSION_DESCRIPTION_MAX_LENGTH = 256;
|
|
5677
|
-
|
|
5678
|
-
// src/services/auth.ts
|
|
5679
|
-
var AuthService = class {
|
|
5680
|
-
restClient;
|
|
5681
|
-
constructor(restClient) {
|
|
5682
|
-
this.restClient = restClient;
|
|
5683
|
-
}
|
|
5684
|
-
async getChallenge() {
|
|
5685
|
-
const request = RestRequest.post(Routes.Authorization.challenge);
|
|
5686
|
-
const response = await this.restClient.execute(request);
|
|
5687
|
-
return response.body;
|
|
5688
|
-
}
|
|
5689
|
-
async submitXadesAuthRequest(signedXml, verifyCertificateChain = false) {
|
|
5690
|
-
const request = RestRequest.post(Routes.Authorization.xadesSignature).body(signedXml).header("Content-Type", "application/xml").query("verifyCertificateChain", String(verifyCertificateChain));
|
|
5691
|
-
const response = await this.restClient.execute(request);
|
|
5692
|
-
return response.body;
|
|
5693
|
-
}
|
|
5694
|
-
async submitKsefTokenAuthRequest(payload) {
|
|
5695
|
-
const request = RestRequest.post(Routes.Authorization.ksefToken).body(payload);
|
|
5696
|
-
const response = await this.restClient.execute(request);
|
|
5697
|
-
return response.body;
|
|
5698
|
-
}
|
|
5699
|
-
async getAuthStatus(referenceNumber, authToken) {
|
|
5700
|
-
const request = RestRequest.get(Routes.Authorization.status(referenceNumber)).accessToken(authToken);
|
|
5701
|
-
const response = await this.restClient.execute(request);
|
|
5702
|
-
return response.body;
|
|
5703
|
-
}
|
|
5704
|
-
async getAccessToken(authToken) {
|
|
5705
|
-
const request = RestRequest.post(Routes.Authorization.Token.redeem).accessToken(authToken);
|
|
5706
|
-
const response = await this.restClient.execute(request);
|
|
5707
|
-
return response.body;
|
|
5708
|
-
}
|
|
5709
|
-
async refreshAccessToken(refreshToken) {
|
|
5710
|
-
const request = RestRequest.post(Routes.Authorization.Token.refresh).accessToken(refreshToken).skipAuthRetry();
|
|
5711
|
-
const response = await this.restClient.execute(request);
|
|
5712
|
-
return response.body;
|
|
5713
|
-
}
|
|
5714
|
-
};
|
|
5715
|
-
|
|
5716
|
-
// src/services/active-sessions.ts
|
|
5717
|
-
var ActiveSessionsService = class {
|
|
5718
|
-
restClient;
|
|
5719
|
-
constructor(restClient) {
|
|
5720
|
-
this.restClient = restClient;
|
|
5721
|
-
}
|
|
5722
|
-
async getActiveSessions(pageSize, continuationToken) {
|
|
5723
|
-
const request = RestRequest.get(Routes.ActiveSessions.session);
|
|
5724
|
-
if (pageSize !== void 0) request.query("pageSize", String(pageSize));
|
|
5725
|
-
if (continuationToken !== void 0) request.header("x-continuation-token", continuationToken);
|
|
5726
|
-
const response = await this.restClient.execute(request);
|
|
5727
|
-
return response.body;
|
|
5728
|
-
}
|
|
5729
|
-
async revokeCurrentSession() {
|
|
5730
|
-
const request = RestRequest.delete(Routes.ActiveSessions.currentSession);
|
|
5731
|
-
await this.restClient.executeVoid(request);
|
|
5732
|
-
}
|
|
5733
|
-
async revokeSession(sessionRef) {
|
|
5734
|
-
const request = RestRequest.delete(Routes.ActiveSessions.delete(sessionRef));
|
|
5735
|
-
await this.restClient.executeVoid(request);
|
|
5736
|
-
}
|
|
5737
|
-
};
|
|
5738
|
-
|
|
5739
|
-
// src/services/online-session.ts
|
|
5740
|
-
var OnlineSessionService = class {
|
|
5741
|
-
restClient;
|
|
5742
|
-
constructor(restClient) {
|
|
5743
|
-
this.restClient = restClient;
|
|
5744
|
-
}
|
|
5745
|
-
async openSession(request, upoVersion) {
|
|
5746
|
-
const req = RestRequest.post(Routes.Sessions.Online.open).body(request);
|
|
5747
|
-
if (upoVersion) {
|
|
5748
|
-
req.header("X-KSeF-Feature", upoVersion);
|
|
5749
|
-
}
|
|
5750
|
-
const response = await this.restClient.execute(req);
|
|
5751
|
-
return response.body;
|
|
5752
|
-
}
|
|
5753
|
-
async sendInvoice(sessionRef, request) {
|
|
5754
|
-
const req = RestRequest.post(Routes.Sessions.Online.invoices(sessionRef)).body(request);
|
|
5755
|
-
const response = await this.restClient.execute(req);
|
|
5756
|
-
return response.body;
|
|
5757
|
-
}
|
|
5758
|
-
async closeSession(sessionRef) {
|
|
5759
|
-
const req = RestRequest.post(Routes.Sessions.Online.close(sessionRef));
|
|
5760
|
-
await this.restClient.executeVoid(req);
|
|
5761
|
-
}
|
|
5762
|
-
};
|
|
5763
|
-
|
|
5764
|
-
// src/services/batch-session.ts
|
|
5765
|
-
var BatchSessionService = class {
|
|
5766
|
-
restClient;
|
|
5767
|
-
constructor(restClient) {
|
|
5768
|
-
this.restClient = restClient;
|
|
5769
|
-
}
|
|
5770
|
-
async openSession(request, upoVersion) {
|
|
5771
|
-
const req = RestRequest.post(Routes.Sessions.Batch.open).body(request);
|
|
5772
|
-
if (upoVersion) {
|
|
5773
|
-
req.header("X-KSeF-Feature", upoVersion);
|
|
5774
|
-
}
|
|
5775
|
-
const response = await this.restClient.execute(req);
|
|
5776
|
-
return response.body;
|
|
5777
|
-
}
|
|
5778
|
-
async sendParts(openResponse, parts) {
|
|
5779
|
-
const uploadRequests = openResponse.partUploadRequests;
|
|
5780
|
-
const tasks = parts.map(async (part) => {
|
|
5781
|
-
const uploadReq = uploadRequests.find(
|
|
5782
|
-
(r) => r.ordinalNumber === part.ordinalNumber
|
|
5783
|
-
);
|
|
5784
|
-
if (!uploadReq) {
|
|
5785
|
-
throw new Error(`No upload request found for part ${part.ordinalNumber}`);
|
|
5786
|
-
}
|
|
5787
|
-
const headers = {};
|
|
5788
|
-
for (const [k, v] of Object.entries(uploadReq.headers)) {
|
|
5789
|
-
if (v != null) headers[k] = v;
|
|
5790
|
-
}
|
|
5791
|
-
await fetch(uploadReq.url, {
|
|
5792
|
-
method: uploadReq.method,
|
|
5793
|
-
headers,
|
|
5794
|
-
body: part.data
|
|
5795
|
-
});
|
|
5796
|
-
});
|
|
5797
|
-
await Promise.all(tasks);
|
|
5798
|
-
}
|
|
5799
|
-
async closeSession(batchRef) {
|
|
5800
|
-
const req = RestRequest.post(Routes.Sessions.Batch.close(batchRef));
|
|
5801
|
-
await this.restClient.executeVoid(req);
|
|
5802
|
-
}
|
|
5803
|
-
};
|
|
5804
|
-
|
|
5805
|
-
// src/services/session-status.ts
|
|
5806
|
-
var SessionStatusService = class {
|
|
5807
|
-
restClient;
|
|
5808
|
-
constructor(restClient) {
|
|
5809
|
-
this.restClient = restClient;
|
|
5810
|
-
}
|
|
5811
|
-
async getSessions(type, pageSize, continuationToken, filter) {
|
|
5812
|
-
const req = RestRequest.get(Routes.Sessions.root);
|
|
5813
|
-
req.query("sessionType", type);
|
|
5814
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5815
|
-
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
5816
|
-
if (filter) {
|
|
5817
|
-
if (filter.referenceNumber) req.query("referenceNumber", filter.referenceNumber);
|
|
5818
|
-
if (filter.dateCreatedFrom) req.query("dateCreatedFrom", filter.dateCreatedFrom);
|
|
5819
|
-
if (filter.dateCreatedTo) req.query("dateCreatedTo", filter.dateCreatedTo);
|
|
5820
|
-
if (filter.dateClosedFrom) req.query("dateClosedFrom", filter.dateClosedFrom);
|
|
5821
|
-
if (filter.dateClosedTo) req.query("dateClosedTo", filter.dateClosedTo);
|
|
5822
|
-
if (filter.dateModifiedFrom) req.query("dateModifiedFrom", filter.dateModifiedFrom);
|
|
5823
|
-
if (filter.dateModifiedTo) req.query("dateModifiedTo", filter.dateModifiedTo);
|
|
5824
|
-
if (filter.statuses) {
|
|
5825
|
-
for (const status of filter.statuses) {
|
|
5826
|
-
req.query("statuses", status);
|
|
5827
|
-
}
|
|
5828
|
-
}
|
|
5829
|
-
}
|
|
5830
|
-
const response = await this.restClient.execute(req);
|
|
5831
|
-
return response.body;
|
|
5832
|
-
}
|
|
5833
|
-
async getSessionStatus(sessionRef) {
|
|
5834
|
-
const req = RestRequest.get(Routes.Sessions.byReference(sessionRef));
|
|
5835
|
-
const response = await this.restClient.execute(req);
|
|
5836
|
-
return response.body;
|
|
5837
|
-
}
|
|
5838
|
-
async getSessionInvoices(sessionRef, pageSize, continuationToken) {
|
|
5839
|
-
const req = RestRequest.get(Routes.Sessions.invoices(sessionRef));
|
|
5840
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5841
|
-
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
5842
|
-
const response = await this.restClient.execute(req);
|
|
5843
|
-
return response.body;
|
|
5844
|
-
}
|
|
5845
|
-
async getSessionInvoice(sessionRef, invoiceRef) {
|
|
5846
|
-
const req = RestRequest.get(Routes.Sessions.invoice(sessionRef, invoiceRef));
|
|
5847
|
-
const response = await this.restClient.execute(req);
|
|
5848
|
-
return response.body;
|
|
5849
|
-
}
|
|
5850
|
-
async getSessionFailedInvoices(sessionRef, pageSize, continuationToken) {
|
|
5851
|
-
const req = RestRequest.get(Routes.Sessions.failedInvoices(sessionRef));
|
|
5852
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5853
|
-
if (continuationToken !== void 0) req.header("x-continuation-token", continuationToken);
|
|
5854
|
-
const response = await this.restClient.execute(req);
|
|
5855
|
-
return response.body;
|
|
5856
|
-
}
|
|
5857
|
-
async getInvoiceUpoByKsefNumber(sessionRef, ksefNumber) {
|
|
5858
|
-
const req = RestRequest.get(Routes.Sessions.upoByKsefNumber(sessionRef, ksefNumber));
|
|
5859
|
-
const response = await this.restClient.executeRaw(req);
|
|
5860
|
-
return {
|
|
5861
|
-
upo: new TextDecoder().decode(response.body),
|
|
5862
|
-
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
5863
|
-
};
|
|
5864
|
-
}
|
|
5865
|
-
async getInvoiceUpoByReference(sessionRef, invoiceRef) {
|
|
5866
|
-
const req = RestRequest.get(Routes.Sessions.upoByInvoiceReference(sessionRef, invoiceRef));
|
|
5867
|
-
const response = await this.restClient.executeRaw(req);
|
|
5868
|
-
return {
|
|
5869
|
-
upo: new TextDecoder().decode(response.body),
|
|
5870
|
-
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
5871
|
-
};
|
|
5872
|
-
}
|
|
5873
|
-
async getSessionUpo(sessionRef, upoRef) {
|
|
5874
|
-
const req = RestRequest.get(Routes.Sessions.upo(sessionRef, upoRef));
|
|
5875
|
-
const response = await this.restClient.executeRaw(req);
|
|
5876
|
-
return {
|
|
5877
|
-
upo: new TextDecoder().decode(response.body),
|
|
5878
|
-
hash: response.headers.get("x-ms-meta-hash") ?? void 0
|
|
5879
|
-
};
|
|
5880
|
-
}
|
|
5881
|
-
};
|
|
5882
|
-
|
|
5883
|
-
// src/services/invoice-download.ts
|
|
5884
|
-
var InvoiceDownloadService = class {
|
|
5885
|
-
restClient;
|
|
5886
|
-
constructor(restClient) {
|
|
5887
|
-
this.restClient = restClient;
|
|
5888
|
-
}
|
|
5889
|
-
async getInvoice(ksefNumber) {
|
|
5890
|
-
const req = RestRequest.get(Routes.Invoices.byKsefNumber(ksefNumber));
|
|
5891
|
-
const response = await this.restClient.executeRaw(req);
|
|
5892
|
-
return new TextDecoder().decode(response.body);
|
|
5893
|
-
}
|
|
5894
|
-
async queryInvoiceMetadata(filters, pageOffset, pageSize, sortOrder) {
|
|
5895
|
-
const req = RestRequest.post(Routes.Invoices.queryMetadata).body(filters);
|
|
5896
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
5897
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5898
|
-
if (sortOrder !== void 0) req.query("sortOrder", sortOrder);
|
|
5899
|
-
const response = await this.restClient.execute(req);
|
|
5900
|
-
return response.body;
|
|
5901
|
-
}
|
|
5902
|
-
async exportInvoices(request) {
|
|
5903
|
-
const req = RestRequest.post(Routes.Invoices.exports).body(request);
|
|
5904
|
-
const response = await this.restClient.execute(req);
|
|
5905
|
-
return response.body;
|
|
5906
|
-
}
|
|
5907
|
-
async getInvoiceExportStatus(ref) {
|
|
5908
|
-
const req = RestRequest.get(Routes.Invoices.exportByReference(ref));
|
|
5909
|
-
const response = await this.restClient.execute(req);
|
|
5910
|
-
return response.body;
|
|
5911
|
-
}
|
|
5912
|
-
};
|
|
5913
|
-
|
|
5914
|
-
// src/services/permissions.ts
|
|
5915
|
-
var PermissionsService = class {
|
|
5916
|
-
restClient;
|
|
5917
|
-
constructor(restClient) {
|
|
5918
|
-
this.restClient = restClient;
|
|
5919
|
-
}
|
|
5920
|
-
// Grant methods
|
|
5921
|
-
async grantPersonPermissions(request) {
|
|
5922
|
-
const req = RestRequest.post(Routes.Permissions.Grants.persons).body(request);
|
|
5923
|
-
const response = await this.restClient.execute(req);
|
|
5924
|
-
return response.body;
|
|
5925
|
-
}
|
|
5926
|
-
async grantEntityPermissions(request) {
|
|
5927
|
-
const req = RestRequest.post(Routes.Permissions.Grants.entities).body(request);
|
|
5928
|
-
const response = await this.restClient.execute(req);
|
|
5929
|
-
return response.body;
|
|
5930
|
-
}
|
|
5931
|
-
async grantAuthorizationPermissions(request) {
|
|
5932
|
-
const req = RestRequest.post(Routes.Permissions.Grants.authorizations).body(request);
|
|
5933
|
-
const response = await this.restClient.execute(req);
|
|
5934
|
-
return response.body;
|
|
5935
|
-
}
|
|
5936
|
-
async grantIndirectPermissions(request) {
|
|
5937
|
-
const req = RestRequest.post(Routes.Permissions.Grants.indirect).body(request);
|
|
5938
|
-
const response = await this.restClient.execute(req);
|
|
5939
|
-
return response.body;
|
|
5940
|
-
}
|
|
5941
|
-
async grantSubunitPermissions(request) {
|
|
5942
|
-
const req = RestRequest.post(Routes.Permissions.Grants.subunits).body(request);
|
|
5943
|
-
const response = await this.restClient.execute(req);
|
|
5944
|
-
return response.body;
|
|
5945
|
-
}
|
|
5946
|
-
async grantEuEntityAdminPermissions(request) {
|
|
5947
|
-
const req = RestRequest.post(Routes.Permissions.Grants.euEntities).body(request);
|
|
5948
|
-
const response = await this.restClient.execute(req);
|
|
5949
|
-
return response.body;
|
|
5950
|
-
}
|
|
5951
|
-
/** @deprecated Use grantEuEntityAdminPermissions instead */
|
|
5952
|
-
async grantEuEntityPermissions(request) {
|
|
5953
|
-
return this.grantEuEntityAdminPermissions(request);
|
|
5954
|
-
}
|
|
5955
|
-
async grantEuEntityRepresentativePermissions(request) {
|
|
5956
|
-
const req = RestRequest.post(Routes.Permissions.Grants.euEntitiesRepresentatives).body(request);
|
|
5957
|
-
const response = await this.restClient.execute(req);
|
|
5958
|
-
return response.body;
|
|
5959
|
-
}
|
|
5960
|
-
// Revoke methods
|
|
5961
|
-
async revokeCommonGrant(grantId) {
|
|
5962
|
-
const req = RestRequest.delete(Routes.Permissions.Common.grantById(grantId));
|
|
5963
|
-
const response = await this.restClient.execute(req);
|
|
5964
|
-
return response.body;
|
|
5965
|
-
}
|
|
5966
|
-
async revokeAuthorizationGrant(grantId) {
|
|
5967
|
-
const req = RestRequest.delete(Routes.Permissions.Authorizations.grantById(grantId));
|
|
5968
|
-
const response = await this.restClient.execute(req);
|
|
5969
|
-
return response.body;
|
|
5970
|
-
}
|
|
5971
|
-
// Search methods
|
|
5972
|
-
async queryPersonalGrants(options, pageOffset, pageSize) {
|
|
5973
|
-
const req = RestRequest.post(Routes.Permissions.Query.personalGrants).body(options ?? {});
|
|
5974
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
5975
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5976
|
-
const response = await this.restClient.execute(req);
|
|
5977
|
-
return response.body;
|
|
5978
|
-
}
|
|
5979
|
-
async queryPersonsGrants(options, pageOffset, pageSize) {
|
|
5980
|
-
const req = RestRequest.post(Routes.Permissions.Query.personsGrants).body(options);
|
|
5981
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
5982
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5983
|
-
const response = await this.restClient.execute(req);
|
|
5984
|
-
return response.body;
|
|
5985
|
-
}
|
|
5986
|
-
async querySubunitsGrants(options, pageOffset, pageSize) {
|
|
5987
|
-
const req = RestRequest.post(Routes.Permissions.Query.subunitsGrants).body(options ?? {});
|
|
5988
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
5989
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
5990
|
-
const response = await this.restClient.execute(req);
|
|
5991
|
-
return response.body;
|
|
5992
|
-
}
|
|
5993
|
-
async queryEntitiesRoles(options) {
|
|
5994
|
-
const req = RestRequest.get(Routes.Permissions.Query.entitiesRoles);
|
|
5995
|
-
if (options?.pageOffset !== void 0) req.query("pageOffset", String(options.pageOffset));
|
|
5996
|
-
if (options?.pageSize !== void 0) req.query("pageSize", String(options.pageSize));
|
|
5997
|
-
const response = await this.restClient.execute(req);
|
|
5998
|
-
return response.body;
|
|
5999
|
-
}
|
|
6000
|
-
async queryEntitiesGrants(options, pageOffset, pageSize) {
|
|
6001
|
-
const req = RestRequest.post(Routes.Permissions.Query.entitiesGrants).body(options ?? {});
|
|
6002
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6003
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6004
|
-
const response = await this.restClient.execute(req);
|
|
6005
|
-
return response.body;
|
|
6006
|
-
}
|
|
6007
|
-
async querySubordinateEntitiesRoles(options, pageOffset, pageSize) {
|
|
6008
|
-
const req = RestRequest.post(Routes.Permissions.Query.subordinateEntitiesRoles).body(options ?? {});
|
|
6009
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6010
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6011
|
-
const response = await this.restClient.execute(req);
|
|
6012
|
-
return response.body;
|
|
6013
|
-
}
|
|
6014
|
-
async queryAuthorizationsGrants(options, pageOffset, pageSize) {
|
|
6015
|
-
const req = RestRequest.post(Routes.Permissions.Query.authorizationsGrants).body(options);
|
|
6016
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6017
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6018
|
-
const response = await this.restClient.execute(req);
|
|
6019
|
-
return response.body;
|
|
6020
|
-
}
|
|
6021
|
-
async queryEuEntitiesGrants(options, pageOffset, pageSize) {
|
|
6022
|
-
const req = RestRequest.post(Routes.Permissions.Query.euEntitiesGrants).body(options ?? {});
|
|
6023
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6024
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6025
|
-
const response = await this.restClient.execute(req);
|
|
6026
|
-
return response.body;
|
|
6027
|
-
}
|
|
6028
|
-
// Operation status methods
|
|
6029
|
-
async getOperationStatus(ref) {
|
|
6030
|
-
const req = RestRequest.get(Routes.Permissions.Operations.byReference(ref));
|
|
6031
|
-
const response = await this.restClient.execute(req);
|
|
6032
|
-
return response.body;
|
|
6033
|
-
}
|
|
6034
|
-
async getAttachmentStatus() {
|
|
6035
|
-
const req = RestRequest.get(Routes.Permissions.Attachments.status);
|
|
6036
|
-
const response = await this.restClient.execute(req);
|
|
6037
|
-
return response.body;
|
|
6038
|
-
}
|
|
6039
|
-
};
|
|
6040
|
-
|
|
6041
|
-
// src/services/tokens.ts
|
|
6042
|
-
var TokenService = class {
|
|
6043
|
-
restClient;
|
|
6044
|
-
constructor(restClient) {
|
|
6045
|
-
this.restClient = restClient;
|
|
6046
|
-
}
|
|
6047
|
-
async generateToken(request) {
|
|
6048
|
-
const req = RestRequest.post(Routes.Tokens.root).body(request);
|
|
6049
|
-
const response = await this.restClient.execute(req);
|
|
6050
|
-
return response.body;
|
|
6051
|
-
}
|
|
6052
|
-
async queryTokens(options) {
|
|
6053
|
-
const req = RestRequest.get(Routes.Tokens.root);
|
|
6054
|
-
if (options?.continuationToken !== void 0) req.header("x-continuation-token", options.continuationToken);
|
|
6055
|
-
if (options?.pageSize !== void 0) req.query("pageSize", String(options.pageSize));
|
|
6056
|
-
if (options?.status) {
|
|
6057
|
-
for (const s of options.status) {
|
|
6058
|
-
req.query("status", s);
|
|
6059
|
-
}
|
|
6060
|
-
}
|
|
6061
|
-
if (options?.description !== void 0) req.query("description", options.description);
|
|
6062
|
-
if (options?.authorIdentifier !== void 0) req.query("authorIdentifier", options.authorIdentifier);
|
|
6063
|
-
if (options?.authorIdentifierType !== void 0) req.query("authorIdentifierType", options.authorIdentifierType);
|
|
6064
|
-
const response = await this.restClient.execute(req);
|
|
6065
|
-
return response.body;
|
|
6066
|
-
}
|
|
6067
|
-
async getToken(ref) {
|
|
6068
|
-
const req = RestRequest.get(Routes.Tokens.byReference(ref));
|
|
6069
|
-
const response = await this.restClient.execute(req);
|
|
6070
|
-
return response.body;
|
|
6071
|
-
}
|
|
6072
|
-
async revokeToken(ref) {
|
|
6073
|
-
const req = RestRequest.delete(Routes.Tokens.byReference(ref));
|
|
6074
|
-
await this.restClient.executeVoid(req);
|
|
6075
|
-
}
|
|
6076
|
-
};
|
|
6077
|
-
|
|
6078
|
-
// src/services/certificates.ts
|
|
6079
|
-
var CertificateApiService = class {
|
|
6080
|
-
restClient;
|
|
6081
|
-
constructor(restClient) {
|
|
6082
|
-
this.restClient = restClient;
|
|
6083
|
-
}
|
|
6084
|
-
async getLimits() {
|
|
6085
|
-
const req = RestRequest.get(Routes.Certificates.limits);
|
|
6086
|
-
const response = await this.restClient.execute(req);
|
|
6087
|
-
return response.body;
|
|
6088
|
-
}
|
|
6089
|
-
async getEnrollmentData() {
|
|
6090
|
-
const req = RestRequest.get(Routes.Certificates.enrollmentData);
|
|
6091
|
-
const response = await this.restClient.execute(req);
|
|
6092
|
-
return response.body;
|
|
6093
|
-
}
|
|
6094
|
-
async enroll(request) {
|
|
6095
|
-
const req = RestRequest.post(Routes.Certificates.enrollments).body(request);
|
|
6096
|
-
const response = await this.restClient.execute(req);
|
|
6097
|
-
return response.body;
|
|
6098
|
-
}
|
|
6099
|
-
async getEnrollmentStatus(ref) {
|
|
6100
|
-
const req = RestRequest.get(Routes.Certificates.enrollmentStatus(ref));
|
|
6101
|
-
const response = await this.restClient.execute(req);
|
|
6102
|
-
return response.body;
|
|
6103
|
-
}
|
|
6104
|
-
async retrieve(request) {
|
|
6105
|
-
const req = RestRequest.post(Routes.Certificates.retrieve).body(request);
|
|
6106
|
-
const response = await this.restClient.execute(req);
|
|
6107
|
-
return response.body;
|
|
6108
|
-
}
|
|
6109
|
-
async revoke(serialNumber, request) {
|
|
6110
|
-
const req = RestRequest.post(Routes.Certificates.revoke(serialNumber)).body(request);
|
|
6111
|
-
await this.restClient.executeVoid(req);
|
|
6112
|
-
}
|
|
6113
|
-
async query(request, pageSize, pageOffset) {
|
|
6114
|
-
const req = RestRequest.post(Routes.Certificates.query).body(request);
|
|
6115
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6116
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6117
|
-
const response = await this.restClient.execute(req);
|
|
6118
|
-
return response.body;
|
|
6119
|
-
}
|
|
6120
|
-
};
|
|
6121
|
-
|
|
6122
|
-
// src/services/lighthouse.ts
|
|
6123
|
-
var LighthouseService = class {
|
|
6124
|
-
lighthouseUrl;
|
|
6125
|
-
timeout;
|
|
6126
|
-
constructor(options) {
|
|
6127
|
-
this.lighthouseUrl = options.lighthouseUrl;
|
|
6128
|
-
this.timeout = options.timeout;
|
|
6129
|
-
}
|
|
6130
|
-
async fetchJson(path) {
|
|
6131
|
-
if (!this.lighthouseUrl) {
|
|
6132
|
-
throw new KSeFError(
|
|
6133
|
-
"Lighthouse API is not available for the DEMO environment. Use TEST or PROD instead."
|
|
6134
|
-
);
|
|
6135
|
-
}
|
|
6136
|
-
const response = await fetch(`${this.lighthouseUrl}${path}`, {
|
|
6137
|
-
headers: { Accept: "application/json" },
|
|
6138
|
-
signal: AbortSignal.timeout(this.timeout)
|
|
6139
|
-
});
|
|
6140
|
-
if (!response.ok) {
|
|
6141
|
-
const body = await response.text();
|
|
6142
|
-
throw new KSeFError(
|
|
6143
|
-
`Lighthouse ${path} failed: HTTP ${response.status} \u2014 ${body}`
|
|
6144
|
-
);
|
|
7044
|
+
var KsefNumberV35 = /^([1-9]((\d[1-9])|([1-9]\d))\d{7}|M\d{9}|[A-Z]{3}\d{7})-(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-F]{6})([0-9A-F]{6})-([0-9A-F]{2})$/;
|
|
7045
|
+
var KsefNumberV36 = /^([1-9]((\d[1-9])|([1-9]\d))\d{7}|M\d{9}|[A-Z]{3}\d{7})-(20[2-9][0-9]|2[1-9][0-9]{2}|[3-9][0-9]{3})(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])-([0-9A-F]{6})-([0-9A-F]{6})-([0-9A-F]{2})$/;
|
|
7046
|
+
var CertificateName = /^[a-zA-Z0-9_\- ąćęłńóśźżĄĆĘŁŃÓŚŹŻ]+$/;
|
|
7047
|
+
var Pesel = /^\d{2}(?:0[1-9]|1[0-2]|2[1-9]|3[0-2]|4[1-9]|5[0-2]|6[1-9]|7[0-2]|8[1-9]|9[0-2])\d{7}$/;
|
|
7048
|
+
var CertificateFingerprint = /^[0-9A-F]{64}$/;
|
|
7049
|
+
var Base64String = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
7050
|
+
var Ip4Address = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
7051
|
+
var Ip4Range = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}-((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
|
7052
|
+
var Ip4Mask = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}\/(0|[1-9]|1[0-9]|2[0-9]|3[0-2])$/;
|
|
7053
|
+
var Sha256Base64 = /^[A-Za-z0-9+/]{43}=$/;
|
|
7054
|
+
var NIP_WEIGHTS = [6, 5, 7, 2, 3, 4, 5, 6, 7];
|
|
7055
|
+
var PESEL_WEIGHTS = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
|
|
7056
|
+
var CRC8_POLY = 7;
|
|
7057
|
+
function computeCrc8Hex(data) {
|
|
7058
|
+
let crc = 0;
|
|
7059
|
+
const bytes = new TextEncoder().encode(data);
|
|
7060
|
+
for (const byte of bytes) {
|
|
7061
|
+
crc ^= byte;
|
|
7062
|
+
for (let i = 0; i < 8; i++) {
|
|
7063
|
+
crc = (crc & 128) !== 0 ? (crc << 1 ^ CRC8_POLY) & 255 : crc << 1 & 255;
|
|
6145
7064
|
}
|
|
6146
|
-
return await response.json();
|
|
6147
7065
|
}
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
7066
|
+
return crc.toString(16).toUpperCase().padStart(2, "0");
|
|
7067
|
+
}
|
|
7068
|
+
function isValidNip(value) {
|
|
7069
|
+
if (!Nip.test(value)) return false;
|
|
7070
|
+
let sum = 0;
|
|
7071
|
+
for (let i = 0; i < 9; i++) {
|
|
7072
|
+
sum += Number(value[i]) * NIP_WEIGHTS[i];
|
|
6154
7073
|
}
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
7074
|
+
const checksum = sum % 11;
|
|
7075
|
+
return checksum !== 10 && checksum === Number(value[9]);
|
|
7076
|
+
}
|
|
7077
|
+
function isValidVatUe(value) {
|
|
7078
|
+
return VatUe.test(value);
|
|
7079
|
+
}
|
|
7080
|
+
function isValidNipVatUe(value) {
|
|
7081
|
+
return NipVatUe.test(value);
|
|
7082
|
+
}
|
|
7083
|
+
function isValidInternalId(value) {
|
|
7084
|
+
return InternalId.test(value);
|
|
7085
|
+
}
|
|
7086
|
+
function isValidPeppolId(value) {
|
|
7087
|
+
return PeppolId.test(value);
|
|
7088
|
+
}
|
|
7089
|
+
function isValidReferenceNumber(value) {
|
|
7090
|
+
return ReferenceNumber.test(value);
|
|
7091
|
+
}
|
|
7092
|
+
function isValidKsefNumber(value) {
|
|
7093
|
+
if (!KsefNumber.test(value)) return false;
|
|
7094
|
+
let normalized = value;
|
|
7095
|
+
if (value.length === 36) {
|
|
7096
|
+
const parts = value.split("-");
|
|
7097
|
+
if (parts.length === 5) normalized = `${parts[0]}-${parts[1]}-${parts[2]}${parts[3]}-${parts[4]}`;
|
|
7098
|
+
else return false;
|
|
7099
|
+
}
|
|
7100
|
+
if (normalized.length !== 35) return false;
|
|
7101
|
+
return computeCrc8Hex(normalized.slice(0, 32)) === normalized.slice(-2);
|
|
7102
|
+
}
|
|
7103
|
+
function isValidKsefNumberV35(value) {
|
|
7104
|
+
if (!KsefNumberV35.test(value)) return false;
|
|
7105
|
+
return computeCrc8Hex(value.slice(0, 32)) === value.slice(-2);
|
|
7106
|
+
}
|
|
7107
|
+
function isValidKsefNumberV36(value) {
|
|
7108
|
+
if (!KsefNumberV36.test(value)) return false;
|
|
7109
|
+
const parts = value.split("-");
|
|
7110
|
+
if (parts.length !== 5) return false;
|
|
7111
|
+
const normalized = `${parts[0]}-${parts[1]}-${parts[2]}${parts[3]}-${parts[4]}`;
|
|
7112
|
+
return computeCrc8Hex(normalized.slice(0, 32)) === normalized.slice(-2);
|
|
7113
|
+
}
|
|
7114
|
+
function isValidPesel(value) {
|
|
7115
|
+
if (!Pesel.test(value)) return false;
|
|
7116
|
+
let sum = 0;
|
|
7117
|
+
for (let i = 0; i < 10; i++) {
|
|
7118
|
+
sum += Number(value[i]) * PESEL_WEIGHTS[i];
|
|
6177
7119
|
}
|
|
6178
|
-
|
|
7120
|
+
const checksum = (10 - sum % 10) % 10;
|
|
7121
|
+
return checksum === Number(value[10]);
|
|
7122
|
+
}
|
|
7123
|
+
function isValidCertificateName(value) {
|
|
7124
|
+
return CertificateName.test(value);
|
|
7125
|
+
}
|
|
7126
|
+
function isValidCertificateFingerprint(value) {
|
|
7127
|
+
return CertificateFingerprint.test(value);
|
|
7128
|
+
}
|
|
7129
|
+
function isValidBase64(value) {
|
|
7130
|
+
return Base64String.test(value);
|
|
7131
|
+
}
|
|
7132
|
+
function isValidIp4Address(value) {
|
|
7133
|
+
return Ip4Address.test(value);
|
|
7134
|
+
}
|
|
7135
|
+
function isValidSha256Base64(value) {
|
|
7136
|
+
return Sha256Base64.test(value);
|
|
7137
|
+
}
|
|
6179
7138
|
|
|
6180
|
-
// src/
|
|
6181
|
-
var
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
|
|
6189
|
-
if (pageSize !== void 0) req.query("pageSize", String(pageSize));
|
|
6190
|
-
const response = await this.restClient.execute(req);
|
|
6191
|
-
return response.body;
|
|
6192
|
-
}
|
|
6193
|
-
};
|
|
7139
|
+
// src/validation/constraints.ts
|
|
7140
|
+
var REQUIRED_CHALLENGE_LENGTH = 36;
|
|
7141
|
+
var CERTIFICATE_NAME_MIN_LENGTH = 5;
|
|
7142
|
+
var CERTIFICATE_NAME_MAX_LENGTH = 100;
|
|
7143
|
+
var SUBUNIT_NAME_MIN_LENGTH = 5;
|
|
7144
|
+
var SUBUNIT_NAME_MAX_LENGTH = 256;
|
|
7145
|
+
var PERMISSION_DESCRIPTION_MIN_LENGTH = 5;
|
|
7146
|
+
var PERMISSION_DESCRIPTION_MAX_LENGTH = 256;
|
|
6194
7147
|
|
|
6195
|
-
// src/services/
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
}
|
|
6210
|
-
// Person management
|
|
6211
|
-
async createPerson(request) {
|
|
6212
|
-
const req = RestRequest.post(Routes.TestData.createPerson).body(request);
|
|
6213
|
-
await this.restClient.executeVoid(req);
|
|
6214
|
-
}
|
|
6215
|
-
async removePerson(request) {
|
|
6216
|
-
const req = RestRequest.post(Routes.TestData.removePerson).body(request);
|
|
6217
|
-
await this.restClient.executeVoid(req);
|
|
6218
|
-
}
|
|
6219
|
-
// Permissions
|
|
6220
|
-
async grantPermissions(request) {
|
|
6221
|
-
const req = RestRequest.post(Routes.TestData.grantPerms).body(request);
|
|
6222
|
-
await this.restClient.executeVoid(req);
|
|
6223
|
-
}
|
|
6224
|
-
async revokePermissions(request) {
|
|
6225
|
-
const req = RestRequest.post(Routes.TestData.revokePerms).body(request);
|
|
6226
|
-
await this.restClient.executeVoid(req);
|
|
6227
|
-
}
|
|
6228
|
-
// Attachment permissions
|
|
6229
|
-
async enableAttachment(request) {
|
|
6230
|
-
const req = RestRequest.post(Routes.TestData.enableAttach).body(request);
|
|
6231
|
-
await this.restClient.executeVoid(req);
|
|
6232
|
-
}
|
|
6233
|
-
async disableAttachment(request) {
|
|
6234
|
-
const req = RestRequest.post(Routes.TestData.disableAttach).body(request);
|
|
6235
|
-
await this.restClient.executeVoid(req);
|
|
6236
|
-
}
|
|
6237
|
-
// Session limits
|
|
6238
|
-
async changeSessionLimits(request) {
|
|
6239
|
-
const req = RestRequest.post(Routes.TestData.changeSessionLimitsInCurrentContext).body(request);
|
|
6240
|
-
await this.restClient.executeVoid(req);
|
|
6241
|
-
}
|
|
6242
|
-
async restoreDefaultSessionLimits() {
|
|
6243
|
-
const req = RestRequest.delete(Routes.TestData.restoreDefaultSessionLimitsInCurrentContext);
|
|
6244
|
-
await this.restClient.executeVoid(req);
|
|
6245
|
-
}
|
|
6246
|
-
// Certificate limits
|
|
6247
|
-
async changeCertificatesLimit(request) {
|
|
6248
|
-
const req = RestRequest.post(Routes.TestData.changeCertificatesLimitInCurrentSubject).body(request);
|
|
6249
|
-
await this.restClient.executeVoid(req);
|
|
6250
|
-
}
|
|
6251
|
-
async restoreDefaultCertificatesLimit() {
|
|
6252
|
-
const req = RestRequest.delete(Routes.TestData.restoreDefaultCertificatesLimitInCurrentSubject);
|
|
6253
|
-
await this.restClient.executeVoid(req);
|
|
6254
|
-
}
|
|
6255
|
-
// Rate limits
|
|
6256
|
-
async setRateLimits(request) {
|
|
6257
|
-
const req = RestRequest.post(Routes.TestData.rateLimits).body(request);
|
|
6258
|
-
await this.restClient.executeVoid(req);
|
|
6259
|
-
}
|
|
6260
|
-
async restoreDefaultRateLimits() {
|
|
6261
|
-
const req = RestRequest.delete(Routes.TestData.rateLimits);
|
|
6262
|
-
await this.restClient.executeVoid(req);
|
|
6263
|
-
}
|
|
6264
|
-
async setProductionRateLimits() {
|
|
6265
|
-
const req = RestRequest.post(Routes.TestData.productionRateLimits);
|
|
6266
|
-
await this.restClient.executeVoid(req);
|
|
6267
|
-
}
|
|
6268
|
-
// Context blocking
|
|
6269
|
-
async blockContext(request) {
|
|
6270
|
-
const req = RestRequest.post(Routes.TestData.blockContext).body(request);
|
|
6271
|
-
await this.restClient.executeVoid(req);
|
|
6272
|
-
}
|
|
6273
|
-
async unblockContext(request) {
|
|
6274
|
-
const req = RestRequest.post(Routes.TestData.unblockContext).body(request);
|
|
6275
|
-
await this.restClient.executeVoid(req);
|
|
6276
|
-
}
|
|
6277
|
-
};
|
|
7148
|
+
// src/services/index.ts
|
|
7149
|
+
init_auth();
|
|
7150
|
+
init_active_sessions();
|
|
7151
|
+
init_online_session();
|
|
7152
|
+
init_batch_session();
|
|
7153
|
+
init_session_status();
|
|
7154
|
+
init_invoice_download();
|
|
7155
|
+
init_permissions();
|
|
7156
|
+
init_tokens();
|
|
7157
|
+
init_certificates();
|
|
7158
|
+
init_lighthouse();
|
|
7159
|
+
init_limits();
|
|
7160
|
+
init_peppol();
|
|
7161
|
+
init_test_data();
|
|
6278
7162
|
|
|
6279
7163
|
// src/builders/auth-token-request.ts
|
|
7164
|
+
init_ksef_validation_error();
|
|
6280
7165
|
var AuthTokenRequestBuilder = class {
|
|
6281
7166
|
challenge;
|
|
6282
7167
|
contextIdentifier;
|
|
@@ -6330,6 +7215,7 @@ var AuthTokenRequestBuilder = class {
|
|
|
6330
7215
|
};
|
|
6331
7216
|
|
|
6332
7217
|
// src/builders/auth-ksef-token-request.ts
|
|
7218
|
+
init_ksef_validation_error();
|
|
6333
7219
|
var AuthKsefTokenRequestBuilder = class {
|
|
6334
7220
|
challenge;
|
|
6335
7221
|
contextIdentifier;
|
|
@@ -6383,6 +7269,7 @@ var AuthKsefTokenRequestBuilder = class {
|
|
|
6383
7269
|
};
|
|
6384
7270
|
|
|
6385
7271
|
// src/builders/invoice-query-filter.ts
|
|
7272
|
+
init_ksef_validation_error();
|
|
6386
7273
|
var InvoiceQueryFilterBuilder = class {
|
|
6387
7274
|
subjectType;
|
|
6388
7275
|
dateRange;
|
|
@@ -6479,6 +7366,7 @@ var InvoiceQueryFilterBuilder = class {
|
|
|
6479
7366
|
};
|
|
6480
7367
|
|
|
6481
7368
|
// src/builders/permissions/person-permission.ts
|
|
7369
|
+
init_ksef_validation_error();
|
|
6482
7370
|
var PersonPermissionGrantBuilder = class {
|
|
6483
7371
|
subjectIdentifier;
|
|
6484
7372
|
permissions = [];
|
|
@@ -6527,6 +7415,7 @@ var PersonPermissionGrantBuilder = class {
|
|
|
6527
7415
|
};
|
|
6528
7416
|
|
|
6529
7417
|
// src/builders/permissions/entity-permission.ts
|
|
7418
|
+
init_ksef_validation_error();
|
|
6530
7419
|
var EntityPermissionGrantBuilder = class {
|
|
6531
7420
|
nip;
|
|
6532
7421
|
permissions = [];
|
|
@@ -6575,6 +7464,7 @@ var EntityPermissionGrantBuilder = class {
|
|
|
6575
7464
|
};
|
|
6576
7465
|
|
|
6577
7466
|
// src/builders/permissions/authorization-permission.ts
|
|
7467
|
+
init_ksef_validation_error();
|
|
6578
7468
|
var AuthorizationPermissionGrantBuilder = class {
|
|
6579
7469
|
_subjectIdentifier;
|
|
6580
7470
|
_permission;
|
|
@@ -6618,292 +7508,86 @@ var AuthorizationPermissionGrantBuilder = class {
|
|
|
6618
7508
|
}
|
|
6619
7509
|
};
|
|
6620
7510
|
|
|
6621
|
-
// src/
|
|
6622
|
-
|
|
6623
|
-
restClient;
|
|
6624
|
-
symmetricKeyPem;
|
|
6625
|
-
ksefTokenPem;
|
|
6626
|
-
initialized = false;
|
|
6627
|
-
constructor(restClient) {
|
|
6628
|
-
this.restClient = restClient;
|
|
6629
|
-
}
|
|
6630
|
-
async init() {
|
|
6631
|
-
if (this.initialized) return;
|
|
6632
|
-
await this.fetchCertificates();
|
|
6633
|
-
}
|
|
6634
|
-
async refresh() {
|
|
6635
|
-
this.initialized = false;
|
|
6636
|
-
await this.fetchCertificates();
|
|
6637
|
-
}
|
|
6638
|
-
getSymmetricKeyEncryptionPem() {
|
|
6639
|
-
if (!this.symmetricKeyPem) {
|
|
6640
|
-
throw new Error("CertificateFetcher not initialized. Call init() first.");
|
|
6641
|
-
}
|
|
6642
|
-
return this.symmetricKeyPem;
|
|
6643
|
-
}
|
|
6644
|
-
getKsefTokenEncryptionPem() {
|
|
6645
|
-
if (!this.ksefTokenPem) {
|
|
6646
|
-
throw new Error("CertificateFetcher not initialized. Call init() first.");
|
|
6647
|
-
}
|
|
6648
|
-
return this.ksefTokenPem;
|
|
6649
|
-
}
|
|
6650
|
-
async fetchCertificates() {
|
|
6651
|
-
const request = RestRequest.get(Routes.Security.publicKeyCertificates);
|
|
6652
|
-
const response = await this.restClient.execute(request);
|
|
6653
|
-
const certs = response.body;
|
|
6654
|
-
if (!certs || certs.length === 0) {
|
|
6655
|
-
throw new Error("No public key certificates returned from KSeF API.");
|
|
6656
|
-
}
|
|
6657
|
-
const symmetricCert = certs.find((c) => c.usage.includes("SymmetricKeyEncryption"));
|
|
6658
|
-
if (!symmetricCert) {
|
|
6659
|
-
throw new Error("No SymmetricKeyEncryption certificate found.");
|
|
6660
|
-
}
|
|
6661
|
-
this.symmetricKeyPem = this.derBase64ToPem(symmetricCert.certificate);
|
|
6662
|
-
const tokenCerts = certs.filter((c) => c.usage.includes("KsefTokenEncryption")).sort((a, b) => a.validFrom.localeCompare(b.validFrom));
|
|
6663
|
-
const tokenCert = tokenCerts[0];
|
|
6664
|
-
if (!tokenCert) {
|
|
6665
|
-
throw new Error("No KsefTokenEncryption certificate found.");
|
|
6666
|
-
}
|
|
6667
|
-
this.ksefTokenPem = this.derBase64ToPem(tokenCert.certificate);
|
|
6668
|
-
this.initialized = true;
|
|
6669
|
-
}
|
|
6670
|
-
derBase64ToPem(base64Der) {
|
|
6671
|
-
const lines = [];
|
|
6672
|
-
for (let i = 0; i < base64Der.length; i += 64) {
|
|
6673
|
-
lines.push(base64Der.substring(i, i + 64));
|
|
6674
|
-
}
|
|
6675
|
-
return `-----BEGIN CERTIFICATE-----
|
|
6676
|
-
${lines.join("\n")}
|
|
6677
|
-
-----END CERTIFICATE-----`;
|
|
6678
|
-
}
|
|
6679
|
-
};
|
|
6680
|
-
|
|
6681
|
-
// src/crypto/cryptography-service.ts
|
|
7511
|
+
// src/builders/batch-file.ts
|
|
7512
|
+
init_ksef_validation_error();
|
|
6682
7513
|
import * as crypto from "crypto";
|
|
6683
|
-
|
|
6684
|
-
var
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
this.fetcher = fetcher;
|
|
6688
|
-
}
|
|
6689
|
-
/** Initialise the underlying certificate fetcher. */
|
|
6690
|
-
async init() {
|
|
6691
|
-
await this.fetcher.init();
|
|
6692
|
-
}
|
|
6693
|
-
// ---------------------------------------------------------------------------
|
|
6694
|
-
// AES-256-CBC
|
|
6695
|
-
// ---------------------------------------------------------------------------
|
|
6696
|
-
/** Encrypt with AES-256-CBC (PKCS7 padding is automatic in Node). */
|
|
6697
|
-
encryptAES256(content, key, iv) {
|
|
6698
|
-
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
|
6699
|
-
return new Uint8Array(Buffer.concat([cipher.update(content), cipher.final()]));
|
|
6700
|
-
}
|
|
6701
|
-
/** Decrypt with AES-256-CBC. */
|
|
6702
|
-
decryptAES256(content, key, iv) {
|
|
6703
|
-
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
|
6704
|
-
return new Uint8Array(Buffer.concat([decipher.update(content), decipher.final()]));
|
|
6705
|
-
}
|
|
6706
|
-
// ---------------------------------------------------------------------------
|
|
6707
|
-
// Encryption data (AES key + IV wrapped with RSA-OAEP)
|
|
6708
|
-
// ---------------------------------------------------------------------------
|
|
6709
|
-
/**
|
|
6710
|
-
* Generate a random AES-256 key and IV, then wrap the key with the
|
|
6711
|
-
* SymmetricKeyEncryption certificate's RSA public key (RSA-OAEP SHA-256).
|
|
6712
|
-
*/
|
|
6713
|
-
getEncryptionData() {
|
|
6714
|
-
const key = crypto.randomBytes(32);
|
|
6715
|
-
const iv = crypto.randomBytes(16);
|
|
6716
|
-
const certPem = this.fetcher.getSymmetricKeyEncryptionPem();
|
|
6717
|
-
const encryptedKey = crypto.publicEncrypt(
|
|
6718
|
-
{
|
|
6719
|
-
key: certPem,
|
|
6720
|
-
oaepHash: "sha256",
|
|
6721
|
-
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
|
|
6722
|
-
},
|
|
6723
|
-
key
|
|
6724
|
-
);
|
|
6725
|
-
const encryptionInfo = {
|
|
6726
|
-
encryptedSymmetricKey: encryptedKey.toString("base64"),
|
|
6727
|
-
initializationVector: iv.toString("base64")
|
|
6728
|
-
};
|
|
6729
|
-
return {
|
|
6730
|
-
cipherKey: new Uint8Array(key),
|
|
6731
|
-
cipherIv: new Uint8Array(iv),
|
|
6732
|
-
encryptionInfo
|
|
6733
|
-
};
|
|
6734
|
-
}
|
|
6735
|
-
// ---------------------------------------------------------------------------
|
|
6736
|
-
// KSeF token encryption
|
|
6737
|
-
// ---------------------------------------------------------------------------
|
|
7514
|
+
var BATCH_MAX_PART_SIZE = 1e8;
|
|
7515
|
+
var BATCH_MAX_TOTAL_SIZE = 5e9;
|
|
7516
|
+
var BATCH_MAX_PARTS = 50;
|
|
7517
|
+
var BatchFileBuilder = class {
|
|
6738
7518
|
/**
|
|
6739
|
-
*
|
|
6740
|
-
*
|
|
6741
|
-
* Token payload: `"<token>|<challengeTimestampMs>"`.
|
|
6742
|
-
*
|
|
6743
|
-
* The algorithm is chosen automatically based on the KsefTokenEncryption
|
|
6744
|
-
* certificate's public key type:
|
|
6745
|
-
* - **RSA** — RSA-OAEP with SHA-256
|
|
6746
|
-
* - **EC** — ECDH key-agreement (P-256) + AES-256-GCM
|
|
7519
|
+
* Build batch file metadata and encrypted parts from a raw ZIP.
|
|
6747
7520
|
*
|
|
6748
|
-
*
|
|
6749
|
-
*
|
|
7521
|
+
* @param zipBytes - Unencrypted ZIP data
|
|
7522
|
+
* @param encryptFn - AES-256-CBC encryption function (called per part)
|
|
7523
|
+
* @param options - Optional configuration
|
|
6750
7524
|
*/
|
|
6751
|
-
|
|
6752
|
-
const
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
const cert = new crypto.X509Certificate(certPem);
|
|
6756
|
-
const publicKey = cert.publicKey;
|
|
6757
|
-
if (publicKey.asymmetricKeyType === "rsa") {
|
|
6758
|
-
return this.encryptRsaOaep(certPem, plaintext);
|
|
7525
|
+
static build(zipBytes, encryptFn, options) {
|
|
7526
|
+
const maxPartSize = options?.maxPartSize ?? BATCH_MAX_PART_SIZE;
|
|
7527
|
+
if (maxPartSize <= 0) {
|
|
7528
|
+
throw new KSeFValidationError("maxPartSize must be a positive number");
|
|
6759
7529
|
}
|
|
6760
|
-
if (
|
|
6761
|
-
|
|
7530
|
+
if (zipBytes.length === 0) {
|
|
7531
|
+
throw new KSeFValidationError("ZIP data must not be empty");
|
|
6762
7532
|
}
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
};
|
|
6785
|
-
const keys = await crypto.webcrypto.subtle.generateKey(
|
|
6786
|
-
algorithm,
|
|
6787
|
-
true,
|
|
6788
|
-
["sign", "verify"]
|
|
6789
|
-
);
|
|
6790
|
-
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
|
|
6791
|
-
name: buildX500Name(fields),
|
|
6792
|
-
keys,
|
|
6793
|
-
signingAlgorithm: algorithm
|
|
7533
|
+
if (zipBytes.length > BATCH_MAX_TOTAL_SIZE) {
|
|
7534
|
+
throw new KSeFValidationError(
|
|
7535
|
+
`ZIP size ${zipBytes.length} exceeds maximum of ${BATCH_MAX_TOTAL_SIZE} bytes (5 GB)`
|
|
7536
|
+
);
|
|
7537
|
+
}
|
|
7538
|
+
const rawParts = splitBuffer(zipBytes, maxPartSize);
|
|
7539
|
+
if (rawParts.length > BATCH_MAX_PARTS) {
|
|
7540
|
+
throw new KSeFValidationError(
|
|
7541
|
+
`Data requires ${rawParts.length} parts, exceeding maximum of ${BATCH_MAX_PARTS}`
|
|
7542
|
+
);
|
|
7543
|
+
}
|
|
7544
|
+
const zipHash = sha256Base64(zipBytes);
|
|
7545
|
+
const encryptedParts = [];
|
|
7546
|
+
const fileParts = rawParts.map((raw, i) => {
|
|
7547
|
+
const encrypted = encryptFn(raw);
|
|
7548
|
+
encryptedParts.push(encrypted);
|
|
7549
|
+
return {
|
|
7550
|
+
ordinalNumber: i + 1,
|
|
7551
|
+
fileSize: encrypted.length,
|
|
7552
|
+
fileHash: sha256Base64(encrypted)
|
|
7553
|
+
};
|
|
6794
7554
|
});
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
setCryptoProvider();
|
|
6803
|
-
const algorithm = {
|
|
6804
|
-
name: "ECDSA",
|
|
6805
|
-
namedCurve: "P-256"
|
|
7555
|
+
return {
|
|
7556
|
+
batchFile: {
|
|
7557
|
+
fileSize: zipBytes.length,
|
|
7558
|
+
fileHash: zipHash,
|
|
7559
|
+
fileParts
|
|
7560
|
+
},
|
|
7561
|
+
encryptedParts
|
|
6806
7562
|
};
|
|
6807
|
-
const keys = await crypto.webcrypto.subtle.generateKey(
|
|
6808
|
-
algorithm,
|
|
6809
|
-
true,
|
|
6810
|
-
["sign", "verify"]
|
|
6811
|
-
);
|
|
6812
|
-
const csr = await x509.Pkcs10CertificateRequestGenerator.create({
|
|
6813
|
-
name: buildX500Name(fields),
|
|
6814
|
-
keys,
|
|
6815
|
-
signingAlgorithm: { name: "ECDSA", hash: "SHA-256" }
|
|
6816
|
-
});
|
|
6817
|
-
const csrDer = new Uint8Array(csr.rawData);
|
|
6818
|
-
const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
|
|
6819
|
-
const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
|
|
6820
|
-
return { csrDer, privateKeyPem };
|
|
6821
|
-
}
|
|
6822
|
-
// ---------------------------------------------------------------------------
|
|
6823
|
-
// Key parsing
|
|
6824
|
-
// ---------------------------------------------------------------------------
|
|
6825
|
-
/** Parse a PEM-encoded private key into a Node.js KeyObject. */
|
|
6826
|
-
parsePrivateKey(pem) {
|
|
6827
|
-
return crypto.createPrivateKey(pem);
|
|
6828
|
-
}
|
|
6829
|
-
// ---------------------------------------------------------------------------
|
|
6830
|
-
// Private helpers
|
|
6831
|
-
// ---------------------------------------------------------------------------
|
|
6832
|
-
/** RSA-OAEP SHA-256 encryption. */
|
|
6833
|
-
encryptRsaOaep(certPem, plaintext) {
|
|
6834
|
-
return new Uint8Array(
|
|
6835
|
-
crypto.publicEncrypt(
|
|
6836
|
-
{
|
|
6837
|
-
key: certPem,
|
|
6838
|
-
oaepHash: "sha256",
|
|
6839
|
-
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
|
|
6840
|
-
},
|
|
6841
|
-
plaintext
|
|
6842
|
-
)
|
|
6843
|
-
);
|
|
6844
|
-
}
|
|
6845
|
-
/**
|
|
6846
|
-
* ECDH (P-256) + AES-256-GCM encryption.
|
|
6847
|
-
*
|
|
6848
|
-
* 1. Generate an ephemeral EC key pair on the same curve (P-256).
|
|
6849
|
-
* 2. Derive a shared secret via ECDH with the receiver's public key.
|
|
6850
|
-
* 3. Use the shared secret (32 bytes) as the AES-256-GCM key.
|
|
6851
|
-
* 4. Encrypt with a random 12-byte nonce.
|
|
6852
|
-
* 5. Output: `[ephemeralSPKI | nonce(12) | ciphertext+tag]`
|
|
6853
|
-
* (Java-compatible — GCM appends the 16-byte tag to the ciphertext).
|
|
6854
|
-
*/
|
|
6855
|
-
encryptEcdhAesGcm(receiverPublicKey, plaintext) {
|
|
6856
|
-
const { privateKey: ephPrivKey, publicKey: ephPubKey } = crypto.generateKeyPairSync("ec", {
|
|
6857
|
-
namedCurve: "prime256v1"
|
|
6858
|
-
});
|
|
6859
|
-
const sharedSecret = crypto.diffieHellman({
|
|
6860
|
-
privateKey: ephPrivKey,
|
|
6861
|
-
publicKey: receiverPublicKey
|
|
6862
|
-
});
|
|
6863
|
-
const nonce = crypto.randomBytes(12);
|
|
6864
|
-
const cipher = crypto.createCipheriv("aes-256-gcm", sharedSecret, nonce);
|
|
6865
|
-
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
6866
|
-
const tag = cipher.getAuthTag();
|
|
6867
|
-
const ephemeralSpki = ephPubKey.export({ type: "spki", format: "der" });
|
|
6868
|
-
return new Uint8Array(Buffer.concat([ephemeralSpki, nonce, ciphertext, tag]));
|
|
6869
7563
|
}
|
|
6870
7564
|
};
|
|
6871
|
-
function
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
7565
|
+
function splitBuffer(data, maxPartSize) {
|
|
7566
|
+
if (data.length <= maxPartSize) {
|
|
7567
|
+
return [data];
|
|
7568
|
+
}
|
|
6875
7569
|
const parts = [];
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
if (fields.surname) parts.push(`2.5.4.4=${fields.surname}`);
|
|
6879
|
-
if (fields.serialNumber) parts.push(`2.5.4.5=${fields.serialNumber}`);
|
|
6880
|
-
if (fields.organizationName) parts.push(`O=${fields.organizationName}`);
|
|
6881
|
-
if (fields.organizationIdentifier) parts.push(`2.5.4.97=${fields.organizationIdentifier}`);
|
|
6882
|
-
if (fields.uniqueIdentifier) parts.push(`2.5.4.45=${fields.uniqueIdentifier}`);
|
|
6883
|
-
if (fields.countryCode) parts.push(`C=${fields.countryCode}`);
|
|
6884
|
-
return parts.join(", ");
|
|
6885
|
-
}
|
|
6886
|
-
function pemEncode(der, label) {
|
|
6887
|
-
const base64 = Buffer.from(der).toString("base64");
|
|
6888
|
-
const lines = [];
|
|
6889
|
-
for (let i = 0; i < base64.length; i += 64) {
|
|
6890
|
-
lines.push(base64.substring(i, i + 64));
|
|
7570
|
+
for (let offset = 0; offset < data.length; offset += maxPartSize) {
|
|
7571
|
+
parts.push(data.subarray(offset, Math.min(offset + maxPartSize, data.length)));
|
|
6891
7572
|
}
|
|
6892
|
-
return
|
|
6893
|
-
|
|
6894
|
-
|
|
7573
|
+
return parts;
|
|
7574
|
+
}
|
|
7575
|
+
function sha256Base64(data) {
|
|
7576
|
+
return crypto.createHash("sha256").update(data).digest("base64");
|
|
6895
7577
|
}
|
|
6896
7578
|
|
|
6897
7579
|
// src/crypto/index.ts
|
|
7580
|
+
init_certificate_fetcher();
|
|
7581
|
+
init_cryptography_service();
|
|
6898
7582
|
init_signature_service();
|
|
6899
7583
|
|
|
6900
7584
|
// src/crypto/certificate-service.ts
|
|
6901
|
-
import * as
|
|
7585
|
+
import * as crypto4 from "crypto";
|
|
6902
7586
|
import * as x5092 from "@peculiar/x509";
|
|
6903
7587
|
var CertificateService = class {
|
|
6904
7588
|
static getSha256Fingerprint(certPem) {
|
|
6905
7589
|
const der = extractDerFromPem2(certPem);
|
|
6906
|
-
return
|
|
7590
|
+
return crypto4.createHash("sha256").update(der).digest("hex").toUpperCase();
|
|
6907
7591
|
}
|
|
6908
7592
|
static async generatePersonalCertificate(givenName, surname, serialNumber, commonName, method = "RSA") {
|
|
6909
7593
|
const nameParts = [];
|
|
@@ -6926,7 +7610,7 @@ var CertificateService = class {
|
|
|
6926
7610
|
}
|
|
6927
7611
|
};
|
|
6928
7612
|
async function generateSelfSigned(subject, method) {
|
|
6929
|
-
x5092.cryptoProvider.set(
|
|
7613
|
+
x5092.cryptoProvider.set(crypto4.webcrypto);
|
|
6930
7614
|
let algorithm;
|
|
6931
7615
|
let signingAlgorithm;
|
|
6932
7616
|
if (method === "ECDSA") {
|
|
@@ -6941,7 +7625,7 @@ async function generateSelfSigned(subject, method) {
|
|
|
6941
7625
|
};
|
|
6942
7626
|
signingAlgorithm = algorithm;
|
|
6943
7627
|
}
|
|
6944
|
-
const keys = await
|
|
7628
|
+
const keys = await crypto4.webcrypto.subtle.generateKey(
|
|
6945
7629
|
algorithm,
|
|
6946
7630
|
true,
|
|
6947
7631
|
["sign", "verify"]
|
|
@@ -6958,9 +7642,9 @@ async function generateSelfSigned(subject, method) {
|
|
|
6958
7642
|
serialNumber: Date.now().toString(16)
|
|
6959
7643
|
});
|
|
6960
7644
|
const certPem = cert.toString("pem");
|
|
6961
|
-
const pkcs8 = await
|
|
7645
|
+
const pkcs8 = await crypto4.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
|
|
6962
7646
|
const privateKeyPem = pemEncode2(new Uint8Array(pkcs8), "PRIVATE KEY");
|
|
6963
|
-
const fingerprint =
|
|
7647
|
+
const fingerprint = crypto4.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
|
|
6964
7648
|
return { certificatePem: certPem, privateKeyPem, fingerprint };
|
|
6965
7649
|
}
|
|
6966
7650
|
function extractDerFromPem2(pem) {
|
|
@@ -6981,56 +7665,8 @@ ${lines.join("\n")}
|
|
|
6981
7665
|
// src/crypto/index.ts
|
|
6982
7666
|
init_pkcs12_loader();
|
|
6983
7667
|
|
|
6984
|
-
// src/qr/
|
|
6985
|
-
|
|
6986
|
-
var VerificationLinkService = class {
|
|
6987
|
-
constructor(baseQrUrl) {
|
|
6988
|
-
this.baseQrUrl = baseQrUrl;
|
|
6989
|
-
}
|
|
6990
|
-
/**
|
|
6991
|
-
* Build invoice verification URL (Code I).
|
|
6992
|
-
* Format: {baseQrUrl}/invoice/{NIP}/{DD-MM-YYYY}/{hash_base64url}
|
|
6993
|
-
*/
|
|
6994
|
-
buildInvoiceVerificationUrl(nip, issueDate, invoiceHashBase64) {
|
|
6995
|
-
const date = typeof issueDate === "string" ? new Date(issueDate) : issueDate;
|
|
6996
|
-
const dd = String(date.getUTCDate()).padStart(2, "0");
|
|
6997
|
-
const mm = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
6998
|
-
const yyyy = date.getUTCFullYear();
|
|
6999
|
-
const dateStr = `${dd}-${mm}-${yyyy}`;
|
|
7000
|
-
const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
|
|
7001
|
-
return `${this.baseQrUrl}/invoice/${nip}/${dateStr}/${hashBase64Url}`;
|
|
7002
|
-
}
|
|
7003
|
-
/**
|
|
7004
|
-
* Build certificate verification URL (Code II).
|
|
7005
|
-
* Format: {baseQrUrl}/certificate/{contextType}/{contextId}/{sellerNip}/{certSerial}/{hash_base64url}/{signature_base64url}
|
|
7006
|
-
*/
|
|
7007
|
-
buildCertificateVerificationUrl(contextType, contextId, sellerNip, certSerial, invoiceHashBase64, privateKeyPem) {
|
|
7008
|
-
const hashBase64Url = this.base64ToBase64Url(invoiceHashBase64);
|
|
7009
|
-
const pathWithoutSignature = `${this.baseQrUrl}/certificate/${contextType}/${contextId}/${sellerNip}/${certSerial}/${hashBase64Url}`;
|
|
7010
|
-
const dataToSign = pathWithoutSignature.replace(/^https?:\/\//, "");
|
|
7011
|
-
const key = crypto4.createPrivateKey(privateKeyPem);
|
|
7012
|
-
let signature;
|
|
7013
|
-
if (key.asymmetricKeyType === "rsa") {
|
|
7014
|
-
signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
|
|
7015
|
-
key,
|
|
7016
|
-
padding: crypto4.constants.RSA_PKCS1_PSS_PADDING,
|
|
7017
|
-
saltLength: 32
|
|
7018
|
-
});
|
|
7019
|
-
} else if (key.asymmetricKeyType === "ec") {
|
|
7020
|
-
signature = crypto4.sign("sha256", Buffer.from(dataToSign), {
|
|
7021
|
-
key,
|
|
7022
|
-
dsaEncoding: "ieee-p1363"
|
|
7023
|
-
});
|
|
7024
|
-
} else {
|
|
7025
|
-
throw new Error(`Unsupported key type: ${key.asymmetricKeyType}`);
|
|
7026
|
-
}
|
|
7027
|
-
const signatureBase64Url = signature.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
7028
|
-
return `${pathWithoutSignature}/${signatureBase64Url}`;
|
|
7029
|
-
}
|
|
7030
|
-
base64ToBase64Url(base64) {
|
|
7031
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
7032
|
-
}
|
|
7033
|
-
};
|
|
7668
|
+
// src/qr/index.ts
|
|
7669
|
+
init_verification_link_service();
|
|
7034
7670
|
|
|
7035
7671
|
// src/qr/qrcode-service.ts
|
|
7036
7672
|
import * as QRCode from "qrcode";
|
|
@@ -7091,148 +7727,270 @@ function escapeXml2(str) {
|
|
|
7091
7727
|
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
7092
7728
|
}
|
|
7093
7729
|
|
|
7094
|
-
// src/
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
const challenge = await this.auth.getChallenge();
|
|
7158
|
-
const authRequestXml = buildAuthTokenRequestXml(challenge.challenge, nip);
|
|
7159
|
-
const { SignatureService: SignatureService2 } = await Promise.resolve().then(() => (init_signature_service(), signature_service_exports));
|
|
7160
|
-
const signedXml = SignatureService2.sign(authRequestXml, certPem, keyPem);
|
|
7161
|
-
const submitResult = await this.auth.submitXadesAuthRequest(signedXml);
|
|
7162
|
-
const authToken = submitResult.authenticationToken.token;
|
|
7163
|
-
await this.awaitAuthReady(submitResult.referenceNumber, authToken);
|
|
7164
|
-
const tokens = await this.auth.getAccessToken(authToken);
|
|
7165
|
-
this.authManager.setAccessToken(tokens.accessToken.token);
|
|
7166
|
-
this.authManager.setRefreshToken(tokens.refreshToken.token);
|
|
7167
|
-
}
|
|
7168
|
-
async loginWithPkcs12(p12, password, nip) {
|
|
7169
|
-
const { Pkcs12Loader: Pkcs12Loader2 } = await Promise.resolve().then(() => (init_pkcs12_loader(), pkcs12_loader_exports));
|
|
7170
|
-
const { certificatePem, privateKeyPem } = Pkcs12Loader2.load(p12, password);
|
|
7171
|
-
await this.loginWithCertificate(certificatePem, privateKeyPem, nip);
|
|
7172
|
-
}
|
|
7173
|
-
async awaitAuthReady(referenceNumber, authToken) {
|
|
7174
|
-
for (let i = 0; i < 30; i++) {
|
|
7175
|
-
const status = await this.auth.getAuthStatus(referenceNumber, authToken);
|
|
7176
|
-
if (status.status.code === 200) return;
|
|
7177
|
-
if (status.status.code !== 100) {
|
|
7178
|
-
throw new Error(`Authentication failed with status ${status.status.code}: ${status.status.description}`);
|
|
7179
|
-
}
|
|
7180
|
-
await new Promise((r) => setTimeout(r, 1e3));
|
|
7730
|
+
// src/workflows/polling.ts
|
|
7731
|
+
async function pollUntil(action, condition, options) {
|
|
7732
|
+
const intervalMs = options?.intervalMs ?? 2e3;
|
|
7733
|
+
const maxAttempts = options?.maxAttempts ?? 60;
|
|
7734
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
7735
|
+
const result = await action();
|
|
7736
|
+
if (condition(result)) return result;
|
|
7737
|
+
options?.onProgress?.(attempt, maxAttempts);
|
|
7738
|
+
if (attempt < maxAttempts) {
|
|
7739
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
7740
|
+
}
|
|
7741
|
+
}
|
|
7742
|
+
throw new Error(
|
|
7743
|
+
`Polling timeout: ${options?.description ?? "condition"} after ${maxAttempts} attempts`
|
|
7744
|
+
);
|
|
7745
|
+
}
|
|
7746
|
+
|
|
7747
|
+
// src/workflows/online-session-workflow.ts
|
|
7748
|
+
var DEFAULT_FORM_CODE = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
|
|
7749
|
+
async function openOnlineSession(client, options) {
|
|
7750
|
+
await client.crypto.init();
|
|
7751
|
+
const encData = client.crypto.getEncryptionData();
|
|
7752
|
+
const formCode = options?.formCode ?? DEFAULT_FORM_CODE;
|
|
7753
|
+
const openResp = await client.onlineSession.openSession(
|
|
7754
|
+
{ formCode, encryption: encData.encryptionInfo },
|
|
7755
|
+
options?.upoVersion
|
|
7756
|
+
);
|
|
7757
|
+
const sessionRef = openResp.referenceNumber;
|
|
7758
|
+
return {
|
|
7759
|
+
sessionRef,
|
|
7760
|
+
validUntil: openResp.validUntil,
|
|
7761
|
+
async sendInvoice(invoiceXml) {
|
|
7762
|
+
const data = typeof invoiceXml === "string" ? new TextEncoder().encode(invoiceXml) : invoiceXml;
|
|
7763
|
+
const plainMeta = client.crypto.getFileMetadata(data);
|
|
7764
|
+
const encrypted = client.crypto.encryptAES256(data, encData.cipherKey, encData.cipherIv);
|
|
7765
|
+
const encMeta = client.crypto.getFileMetadata(encrypted);
|
|
7766
|
+
const resp = await client.onlineSession.sendInvoice(sessionRef, {
|
|
7767
|
+
invoiceHash: plainMeta.hashSHA,
|
|
7768
|
+
invoiceSize: plainMeta.fileSize,
|
|
7769
|
+
encryptedInvoiceHash: encMeta.hashSHA,
|
|
7770
|
+
encryptedInvoiceSize: encMeta.fileSize,
|
|
7771
|
+
encryptedInvoiceContent: Buffer.from(encrypted).toString("base64")
|
|
7772
|
+
});
|
|
7773
|
+
return resp.referenceNumber;
|
|
7774
|
+
},
|
|
7775
|
+
async close() {
|
|
7776
|
+
await client.onlineSession.closeSession(sessionRef);
|
|
7777
|
+
},
|
|
7778
|
+
async waitForUpo(pollOpts) {
|
|
7779
|
+
const result = await pollUntil(
|
|
7780
|
+
() => client.sessionStatus.getSessionStatus(sessionRef),
|
|
7781
|
+
(s) => s.status.code === 200 || s.status.code >= 400,
|
|
7782
|
+
{ ...pollOpts, description: `UPO for session ${sessionRef}` }
|
|
7783
|
+
);
|
|
7784
|
+
if (result.status.code !== 200) {
|
|
7785
|
+
throw new Error(`Session failed: ${result.status.code} \u2014 ${result.status.description}`);
|
|
7786
|
+
}
|
|
7787
|
+
return {
|
|
7788
|
+
pages: result.upo?.pages ?? [],
|
|
7789
|
+
invoiceCount: result.invoiceCount,
|
|
7790
|
+
successfulInvoiceCount: result.successfulInvoiceCount,
|
|
7791
|
+
failedInvoiceCount: result.failedInvoiceCount
|
|
7792
|
+
};
|
|
7181
7793
|
}
|
|
7182
|
-
}
|
|
7183
|
-
async logout() {
|
|
7184
|
-
this.authManager.setAccessToken(void 0);
|
|
7185
|
-
this.authManager.setRefreshToken(void 0);
|
|
7186
|
-
}
|
|
7187
|
-
};
|
|
7188
|
-
var AUTH_TOKEN_REQUEST_NS = "http://ksef.mf.gov.pl/auth/token/2.0";
|
|
7189
|
-
function buildAuthTokenRequestXml(challenge, nip, subjectIdentifierType = "certificateSubject") {
|
|
7190
|
-
return [
|
|
7191
|
-
'<?xml version="1.0" encoding="utf-8"?>',
|
|
7192
|
-
`<AuthTokenRequest xmlns="${AUTH_TOKEN_REQUEST_NS}">`,
|
|
7193
|
-
`<Challenge>${xmlEscape(challenge)}</Challenge>`,
|
|
7194
|
-
`<ContextIdentifier>`,
|
|
7195
|
-
`<Nip>${xmlEscape(nip)}</Nip>`,
|
|
7196
|
-
`</ContextIdentifier>`,
|
|
7197
|
-
`<SubjectIdentifierType>${xmlEscape(subjectIdentifierType)}</SubjectIdentifierType>`,
|
|
7198
|
-
`</AuthTokenRequest>`
|
|
7199
|
-
].join("");
|
|
7794
|
+
};
|
|
7200
7795
|
}
|
|
7201
|
-
function
|
|
7202
|
-
|
|
7796
|
+
async function openSendAndClose(client, invoices, options) {
|
|
7797
|
+
const handle = await openOnlineSession(client, options);
|
|
7798
|
+
for (const inv of invoices) {
|
|
7799
|
+
await handle.sendInvoice(inv);
|
|
7800
|
+
}
|
|
7801
|
+
await handle.close();
|
|
7802
|
+
return handle.waitForUpo(options?.pollOptions);
|
|
7203
7803
|
}
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7804
|
+
|
|
7805
|
+
// src/workflows/batch-session-workflow.ts
|
|
7806
|
+
var DEFAULT_FORM_CODE2 = { systemCode: "FA", schemaVersion: "3", value: "FA (3)" };
|
|
7807
|
+
async function uploadBatch(client, zipData, options) {
|
|
7808
|
+
await client.crypto.init();
|
|
7809
|
+
const encData = client.crypto.getEncryptionData();
|
|
7810
|
+
const formCode = options?.formCode ?? DEFAULT_FORM_CODE2;
|
|
7811
|
+
const encryptFn = (part) => client.crypto.encryptAES256(part, encData.cipherKey, encData.cipherIv);
|
|
7812
|
+
const { batchFile, encryptedParts } = BatchFileBuilder.build(zipData, encryptFn, {
|
|
7813
|
+
maxPartSize: options?.maxPartSize
|
|
7814
|
+
});
|
|
7815
|
+
const openResp = await client.batchSession.openSession(
|
|
7816
|
+
{
|
|
7817
|
+
formCode,
|
|
7818
|
+
encryption: encData.encryptionInfo,
|
|
7819
|
+
batchFile,
|
|
7820
|
+
offlineMode: options?.offlineMode
|
|
7821
|
+
},
|
|
7822
|
+
options?.upoVersion
|
|
7823
|
+
);
|
|
7824
|
+
const sendingParts = encryptedParts.map((part, i) => ({
|
|
7825
|
+
data: part.buffer.slice(part.byteOffset, part.byteOffset + part.byteLength),
|
|
7826
|
+
metadata: {
|
|
7827
|
+
hashSHA: batchFile.fileParts[i].fileHash,
|
|
7828
|
+
fileSize: batchFile.fileParts[i].fileSize
|
|
7829
|
+
},
|
|
7830
|
+
ordinalNumber: i + 1
|
|
7831
|
+
}));
|
|
7832
|
+
await client.batchSession.sendParts(openResp, sendingParts);
|
|
7833
|
+
await client.batchSession.closeSession(openResp.referenceNumber);
|
|
7834
|
+
const result = await pollUntil(
|
|
7835
|
+
() => client.sessionStatus.getSessionStatus(openResp.referenceNumber),
|
|
7836
|
+
(s) => s.status.code === 200 || s.status.code >= 400,
|
|
7837
|
+
{ ...options?.pollOptions, description: `UPO for batch ${openResp.referenceNumber}` }
|
|
7838
|
+
);
|
|
7839
|
+
if (result.status.code !== 200) {
|
|
7840
|
+
throw new Error(`Batch session failed: ${result.status.code} \u2014 ${result.status.description}`);
|
|
7208
7841
|
}
|
|
7209
|
-
|
|
7210
|
-
|
|
7842
|
+
return {
|
|
7843
|
+
sessionRef: openResp.referenceNumber,
|
|
7844
|
+
upo: {
|
|
7845
|
+
pages: result.upo?.pages ?? [],
|
|
7846
|
+
invoiceCount: result.invoiceCount,
|
|
7847
|
+
successfulInvoiceCount: result.successfulInvoiceCount,
|
|
7848
|
+
failedInvoiceCount: result.failedInvoiceCount
|
|
7849
|
+
}
|
|
7850
|
+
};
|
|
7851
|
+
}
|
|
7852
|
+
|
|
7853
|
+
// src/workflows/invoice-export-workflow.ts
|
|
7854
|
+
async function doExport(client, filters, options) {
|
|
7855
|
+
await client.crypto.init();
|
|
7856
|
+
const encData = client.crypto.getEncryptionData();
|
|
7857
|
+
const opResp = await client.invoices.exportInvoices({
|
|
7858
|
+
encryption: encData.encryptionInfo,
|
|
7859
|
+
filters,
|
|
7860
|
+
onlyMetadata: options?.onlyMetadata
|
|
7861
|
+
});
|
|
7862
|
+
const result = await pollUntil(
|
|
7863
|
+
() => client.invoices.getInvoiceExportStatus(opResp.referenceNumber),
|
|
7864
|
+
(s) => s.status.code === 200 || s.status.code >= 400,
|
|
7865
|
+
{ ...options?.pollOptions, description: `export ${opResp.referenceNumber}` }
|
|
7866
|
+
);
|
|
7867
|
+
if (result.status.code !== 200) {
|
|
7868
|
+
throw new Error(`Export failed: ${result.status.code} \u2014 ${result.status.description}`);
|
|
7211
7869
|
}
|
|
7212
|
-
if (
|
|
7213
|
-
|
|
7214
|
-
} else if (options?.rateLimit) {
|
|
7215
|
-
config.rateLimitPolicy = new RateLimitPolicy({
|
|
7216
|
-
globalRps: options.rateLimit.globalRps ?? 10,
|
|
7217
|
-
endpointLimits: options.rateLimit.endpointLimits
|
|
7218
|
-
});
|
|
7870
|
+
if (!result.package) {
|
|
7871
|
+
throw new Error("Export completed but no package available");
|
|
7219
7872
|
}
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7873
|
+
return {
|
|
7874
|
+
encData,
|
|
7875
|
+
result: {
|
|
7876
|
+
parts: result.package.parts.map((p) => ({
|
|
7877
|
+
ordinalNumber: p.ordinalNumber,
|
|
7878
|
+
url: p.url,
|
|
7879
|
+
method: p.method,
|
|
7880
|
+
partSize: p.partSize,
|
|
7881
|
+
encryptedPartSize: p.encryptedPartSize,
|
|
7882
|
+
encryptedPartHash: p.encryptedPartHash,
|
|
7883
|
+
expirationDate: p.expirationDate
|
|
7884
|
+
})),
|
|
7885
|
+
invoiceCount: result.package.invoiceCount,
|
|
7886
|
+
isTruncated: result.package.isTruncated,
|
|
7887
|
+
permanentStorageHwmDate: result.package.permanentStorageHwmDate
|
|
7888
|
+
}
|
|
7889
|
+
};
|
|
7890
|
+
}
|
|
7891
|
+
async function exportInvoices(client, filters, options) {
|
|
7892
|
+
const { result } = await doExport(client, filters, options);
|
|
7893
|
+
return result;
|
|
7894
|
+
}
|
|
7895
|
+
async function exportAndDownload(client, filters, options) {
|
|
7896
|
+
const { result: exportResult, encData } = await doExport(client, filters, options);
|
|
7897
|
+
const download = options?.transport ?? fetch;
|
|
7898
|
+
const decryptedParts = [];
|
|
7899
|
+
for (const part of exportResult.parts) {
|
|
7900
|
+
const resp = await download(part.url, { method: part.method });
|
|
7901
|
+
if (!resp.ok) {
|
|
7902
|
+
throw new Error(`Download failed for part ${part.ordinalNumber}: HTTP ${resp.status}`);
|
|
7903
|
+
}
|
|
7904
|
+
const encryptedData = new Uint8Array(await resp.arrayBuffer());
|
|
7905
|
+
const decrypted = client.crypto.decryptAES256(encryptedData, encData.cipherKey, encData.cipherIv);
|
|
7906
|
+
decryptedParts.push(decrypted);
|
|
7226
7907
|
}
|
|
7227
|
-
return
|
|
7908
|
+
return {
|
|
7909
|
+
...exportResult,
|
|
7910
|
+
decryptedParts
|
|
7911
|
+
};
|
|
7912
|
+
}
|
|
7913
|
+
|
|
7914
|
+
// src/workflows/auth-workflow.ts
|
|
7915
|
+
async function authenticateWithToken(client, options) {
|
|
7916
|
+
const challenge = await client.auth.getChallenge();
|
|
7917
|
+
await client.crypto.init();
|
|
7918
|
+
const encryptedToken = client.crypto.encryptKsefToken(options.token, challenge.timestamp);
|
|
7919
|
+
const submitResult = await client.auth.submitKsefTokenAuthRequest({
|
|
7920
|
+
challenge: challenge.challenge,
|
|
7921
|
+
contextIdentifier: { type: "Nip", value: options.nip },
|
|
7922
|
+
encryptedToken: Buffer.from(encryptedToken).toString("base64"),
|
|
7923
|
+
authorizationPolicy: options.authorizationPolicy
|
|
7924
|
+
});
|
|
7925
|
+
const authToken = submitResult.authenticationToken.token;
|
|
7926
|
+
await pollUntil(
|
|
7927
|
+
() => client.auth.getAuthStatus(submitResult.referenceNumber, authToken),
|
|
7928
|
+
(s) => s.status.code !== 100,
|
|
7929
|
+
{ ...options.pollOptions, description: `auth ${submitResult.referenceNumber}` }
|
|
7930
|
+
);
|
|
7931
|
+
const tokens = await client.auth.getAccessToken(authToken);
|
|
7932
|
+
client.authManager.setAccessToken(tokens.accessToken.token);
|
|
7933
|
+
client.authManager.setRefreshToken(tokens.refreshToken.token);
|
|
7934
|
+
return {
|
|
7935
|
+
accessToken: tokens.accessToken.token,
|
|
7936
|
+
accessTokenValidUntil: tokens.accessToken.validUntil,
|
|
7937
|
+
refreshToken: tokens.refreshToken.token,
|
|
7938
|
+
refreshTokenValidUntil: tokens.refreshToken.validUntil
|
|
7939
|
+
};
|
|
7228
7940
|
}
|
|
7941
|
+
async function authenticateWithCertificate(client, options) {
|
|
7942
|
+
const challenge = await client.auth.getChallenge();
|
|
7943
|
+
const { buildAuthTokenRequestXml: buildAuthTokenRequestXml2 } = await Promise.resolve().then(() => (init_client(), client_exports));
|
|
7944
|
+
const { SignatureService: SignatureService2 } = await Promise.resolve().then(() => (init_signature_service(), signature_service_exports));
|
|
7945
|
+
const authRequestXml = buildAuthTokenRequestXml2(challenge.challenge, options.nip);
|
|
7946
|
+
const signedXml = SignatureService2.sign(authRequestXml, options.certPem, options.keyPem);
|
|
7947
|
+
const submitResult = await client.auth.submitXadesAuthRequest(
|
|
7948
|
+
signedXml,
|
|
7949
|
+
options.verifyCertificateChain ?? false,
|
|
7950
|
+
options.enforceXadesCompliance ?? false
|
|
7951
|
+
);
|
|
7952
|
+
const authToken = submitResult.authenticationToken.token;
|
|
7953
|
+
await pollUntil(
|
|
7954
|
+
() => client.auth.getAuthStatus(submitResult.referenceNumber, authToken),
|
|
7955
|
+
(s) => s.status.code !== 100,
|
|
7956
|
+
{ ...options.pollOptions, description: `auth ${submitResult.referenceNumber}` }
|
|
7957
|
+
);
|
|
7958
|
+
const tokens = await client.auth.getAccessToken(authToken);
|
|
7959
|
+
client.authManager.setAccessToken(tokens.accessToken.token);
|
|
7960
|
+
client.authManager.setRefreshToken(tokens.refreshToken.token);
|
|
7961
|
+
return {
|
|
7962
|
+
accessToken: tokens.accessToken.token,
|
|
7963
|
+
accessTokenValidUntil: tokens.accessToken.validUntil,
|
|
7964
|
+
refreshToken: tokens.refreshToken.token,
|
|
7965
|
+
refreshTokenValidUntil: tokens.refreshToken.validUntil
|
|
7966
|
+
};
|
|
7967
|
+
}
|
|
7968
|
+
async function authenticateWithPkcs12(client, options) {
|
|
7969
|
+
const { Pkcs12Loader: Pkcs12Loader2 } = await Promise.resolve().then(() => (init_pkcs12_loader(), pkcs12_loader_exports));
|
|
7970
|
+
const { certificatePem, privateKeyPem } = Pkcs12Loader2.load(options.p12, options.password);
|
|
7971
|
+
return authenticateWithCertificate(client, {
|
|
7972
|
+
nip: options.nip,
|
|
7973
|
+
certPem: certificatePem,
|
|
7974
|
+
keyPem: privateKeyPem,
|
|
7975
|
+
verifyCertificateChain: options.verifyCertificateChain,
|
|
7976
|
+
enforceXadesCompliance: options.enforceXadesCompliance,
|
|
7977
|
+
pollOptions: options.pollOptions
|
|
7978
|
+
});
|
|
7979
|
+
}
|
|
7980
|
+
|
|
7981
|
+
// src/index.ts
|
|
7982
|
+
init_client();
|
|
7229
7983
|
export {
|
|
7230
7984
|
ActiveSessionsService,
|
|
7231
7985
|
AuthKsefTokenRequestBuilder,
|
|
7232
7986
|
AuthService,
|
|
7233
7987
|
AuthTokenRequestBuilder,
|
|
7234
7988
|
AuthorizationPermissionGrantBuilder,
|
|
7989
|
+
BATCH_MAX_PARTS,
|
|
7990
|
+
BATCH_MAX_PART_SIZE,
|
|
7991
|
+
BATCH_MAX_TOTAL_SIZE,
|
|
7235
7992
|
Base64String,
|
|
7993
|
+
BatchFileBuilder,
|
|
7236
7994
|
BatchSessionService,
|
|
7237
7995
|
CERTIFICATE_NAME_MAX_LENGTH,
|
|
7238
7996
|
CERTIFICATE_NAME_MIN_LENGTH,
|
|
@@ -7243,6 +8001,7 @@ export {
|
|
|
7243
8001
|
CertificateService,
|
|
7244
8002
|
CryptographyService,
|
|
7245
8003
|
DefaultAuthManager,
|
|
8004
|
+
ENFORCE_XADES_COMPLIANCE,
|
|
7246
8005
|
EntityPermissionGrantBuilder,
|
|
7247
8006
|
Environment,
|
|
7248
8007
|
InternalId,
|
|
@@ -7251,6 +8010,7 @@ export {
|
|
|
7251
8010
|
Ip4Address,
|
|
7252
8011
|
Ip4Mask,
|
|
7253
8012
|
Ip4Range,
|
|
8013
|
+
KSEF_FEATURE_HEADER,
|
|
7254
8014
|
KSeFApiError,
|
|
7255
8015
|
KSeFAuthStatusError,
|
|
7256
8016
|
KSeFClient,
|
|
@@ -7291,13 +8051,19 @@ export {
|
|
|
7291
8051
|
SignatureService,
|
|
7292
8052
|
TestDataService,
|
|
7293
8053
|
TokenService,
|
|
8054
|
+
UpoVersion,
|
|
7294
8055
|
VatUe,
|
|
7295
8056
|
VerificationLinkService,
|
|
8057
|
+
authenticateWithCertificate,
|
|
8058
|
+
authenticateWithPkcs12,
|
|
8059
|
+
authenticateWithToken,
|
|
7296
8060
|
calculateBackoff,
|
|
7297
8061
|
defaultPresignedUrlPolicy,
|
|
7298
8062
|
defaultRateLimitPolicy,
|
|
7299
8063
|
defaultRetryPolicy,
|
|
7300
8064
|
defaultTransport,
|
|
8065
|
+
exportAndDownload,
|
|
8066
|
+
exportInvoices,
|
|
7301
8067
|
isRetryableError,
|
|
7302
8068
|
isRetryableStatus,
|
|
7303
8069
|
isValidBase64,
|
|
@@ -7306,6 +8072,8 @@ export {
|
|
|
7306
8072
|
isValidInternalId,
|
|
7307
8073
|
isValidIp4Address,
|
|
7308
8074
|
isValidKsefNumber,
|
|
8075
|
+
isValidKsefNumberV35,
|
|
8076
|
+
isValidKsefNumberV36,
|
|
7309
8077
|
isValidNip,
|
|
7310
8078
|
isValidNipVatUe,
|
|
7311
8079
|
isValidPeppolId,
|
|
@@ -7313,9 +8081,13 @@ export {
|
|
|
7313
8081
|
isValidReferenceNumber,
|
|
7314
8082
|
isValidSha256Base64,
|
|
7315
8083
|
isValidVatUe,
|
|
8084
|
+
openOnlineSession,
|
|
8085
|
+
openSendAndClose,
|
|
7316
8086
|
parseRetryAfter,
|
|
8087
|
+
pollUntil,
|
|
7317
8088
|
resolveOptions,
|
|
7318
8089
|
sleep,
|
|
8090
|
+
uploadBatch,
|
|
7319
8091
|
validatePresignedUrl
|
|
7320
8092
|
};
|
|
7321
8093
|
//# sourceMappingURL=index.js.map
|