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/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 crypto2 from "crypto";
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 crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
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 crypto2.createHash("sha256").update(canonical, "utf-8").digest("base64");
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 = crypto2.sign("sha256", data, {
6580
+ signature = crypto3.sign("sha256", data, {
4636
6581
  key: privateKeyPem,
4637
6582
  dsaEncoding: "ieee-p1363"
4638
6583
  });
4639
6584
  } else {
4640
- signature = crypto2.sign("sha256", data, privateKeyPem);
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 = crypto2.createHash("sha256").update(certDer).digest("base64");
4741
- const x5093 = new crypto2.X509Certificate(certPem);
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 = crypto2.createPrivateKey(privateKeyPem);
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
- return response;
5289
- } catch (error) {
5290
- lastError = error;
5291
- if (isRetryableError(error, this.retryPolicy) && attempt < this.retryPolicy.maxRetries) {
5292
- const delayMs = calculateBackoff(attempt, this.retryPolicy);
5293
- consola.debug(`Network error, attempt ${attempt + 1}/${this.retryPolicy.maxRetries}, waiting ${Math.round(delayMs)}ms`);
5294
- await sleep(delayMs);
5295
- continue;
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
- throw error;
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
- async ensureSuccess(response) {
5343
- if (response.ok) return;
5344
- const text = await response.text().catch(() => "");
5345
- const parseJson = () => {
5346
- try {
5347
- return JSON.parse(text);
5348
- } catch {
5349
- return void 0;
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
- if (response.status === 429) {
5353
- const parsed = parseJson();
5354
- throw KSeFRateLimitError.fromRetryAfterHeader(
5355
- response.status,
5356
- response.headers.get("Retry-After"),
5357
- parsed
5358
- );
5359
- }
5360
- if (response.status === 401) {
5361
- const body = parseJson();
5362
- if (body?.detail) {
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
- if (response.status === 403) {
5367
- const body = parseJson();
5368
- if (body?.reasonCode) {
5369
- throw new KSeFForbiddenError(body);
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
- throw KSeFApiError.fromResponse(response.status, parseJson());
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/http/rate-limit-policy.ts
5500
- var TokenBucket = class {
5501
- tokens;
5502
- maxTokens;
5503
- refillRate;
5504
- // tokens per ms
5505
- lastRefill;
5506
- constructor(rps) {
5507
- this.maxTokens = rps;
5508
- this.tokens = rps;
5509
- this.refillRate = rps / 1e3;
5510
- this.lastRefill = Date.now();
5511
- }
5512
- async acquire() {
5513
- this.refill();
5514
- if (this.tokens >= 1) {
5515
- this.tokens -= 1;
5516
- return;
5517
- }
5518
- const waitMs = Math.ceil((1 - this.tokens) / this.refillRate);
5519
- await new Promise((resolve) => setTimeout(resolve, waitMs));
5520
- this.refill();
5521
- this.tokens -= 1;
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
6869
+ }
6870
+ function buildRestClientConfig(options, authManager) {
6871
+ const config = { authManager };
6872
+ if (options?.transport) {
6873
+ config.transport = options.transport;
5522
6874
  }
5523
- refill() {
5524
- const now = Date.now();
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
- var RateLimitPolicy = class {
5531
- globalBucket;
5532
- endpointBuckets = /* @__PURE__ */ new Map();
5533
- endpointLimits;
5534
- chain = Promise.resolve();
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
- async doAcquire(endpoint) {
5545
- await this.globalBucket.acquire();
5546
- const limit = this.endpointLimits[endpoint];
5547
- if (limit !== void 0) {
5548
- let bucket = this.endpointBuckets.get(endpoint);
5549
- if (!bucket) {
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
- // src/http/auth-manager.ts
5562
- var DefaultAuthManager = class {
5563
- token;
5564
- refreshToken;
5565
- refreshFn;
5566
- refreshPromise = null;
5567
- constructor(refreshFn, initialToken) {
5568
- this.refreshFn = refreshFn;
5569
- this.token = initialToken;
5570
- }
5571
- getAccessToken() {
5572
- return this.token;
5573
- }
5574
- setAccessToken(token) {
5575
- this.token = token;
5576
- }
5577
- getRefreshToken() {
5578
- return this.refreshToken;
5579
- }
5580
- setRefreshToken(token) {
5581
- this.refreshToken = token;
5582
- }
5583
- async onUnauthorized() {
5584
- if (this.refreshPromise) return this.refreshPromise;
5585
- this.refreshPromise = this.refreshFn().then((newToken) => {
5586
- this.token = newToken ?? void 0;
5587
- return newToken;
5588
- }).finally(() => {
5589
- this.refreshPromise = null;
5590
- });
5591
- return this.refreshPromise;
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
- function isValidNip(value) {
5618
- if (!Nip.test(value)) return false;
5619
- let sum = 0;
5620
- for (let i = 0; i < 9; i++) {
5621
- sum += Number(value[i]) * NIP_WEIGHTS[i];
5622
- }
5623
- const checksum = sum % 11;
5624
- return checksum !== 10 && checksum === Number(value[9]);
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
- async getStatus() {
6149
- return this.fetchJson("/status");
6150
- }
6151
- async getMessages() {
6152
- const data = await this.fetchJson("/messages");
6153
- return data.messages ?? [];
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
- // src/services/limits.ts
6158
- var LimitsService = class {
6159
- restClient;
6160
- constructor(restClient) {
6161
- this.restClient = restClient;
6162
- }
6163
- async getContextLimits() {
6164
- const req = RestRequest.get(Routes.Limits.currentContext);
6165
- const response = await this.restClient.execute(req);
6166
- return response.body;
6167
- }
6168
- async getSubjectLimits() {
6169
- const req = RestRequest.get(Routes.Limits.currentSubject);
6170
- const response = await this.restClient.execute(req);
6171
- return response.body;
6172
- }
6173
- async getRateLimits() {
6174
- const req = RestRequest.get(Routes.Limits.rateLimits);
6175
- const response = await this.restClient.execute(req);
6176
- return response.body;
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/services/peppol.ts
6181
- var PeppolService = class {
6182
- restClient;
6183
- constructor(restClient) {
6184
- this.restClient = restClient;
6185
- }
6186
- async queryProviders(pageOffset, pageSize) {
6187
- const req = RestRequest.get(Routes.Peppol.query);
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/test-data.ts
6196
- var TestDataService = class {
6197
- restClient;
6198
- constructor(restClient) {
6199
- this.restClient = restClient;
6200
- }
6201
- // Subject management
6202
- async createSubject(request) {
6203
- const req = RestRequest.post(Routes.TestData.createSubject).body(request);
6204
- await this.restClient.executeVoid(req);
6205
- }
6206
- async removeSubject(request) {
6207
- const req = RestRequest.post(Routes.TestData.removeSubject).body(request);
6208
- await this.restClient.executeVoid(req);
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/crypto/certificate-fetcher.ts
6622
- var CertificateFetcher = class {
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
- import * as x509 from "@peculiar/x509";
6684
- var CryptographyService = class {
6685
- fetcher;
6686
- constructor(fetcher) {
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
- * Encrypt a KSeF token for session authorisation.
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
- * The EC variant outputs bytes in the Java-compatible format:
6749
- * `[ephemeralSPKI | nonce(12) | ciphertext+tag]`.
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
- encryptKsefToken(token, challengeTimestamp) {
6752
- const timestampMs = new Date(challengeTimestamp).getTime();
6753
- const plaintext = Buffer.from(`${token}|${timestampMs}`, "utf-8");
6754
- const certPem = this.fetcher.getKsefTokenEncryptionPem();
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 (publicKey.asymmetricKeyType === "ec") {
6761
- return this.encryptEcdhAesGcm(publicKey, plaintext);
7530
+ if (zipBytes.length === 0) {
7531
+ throw new KSeFValidationError("ZIP data must not be empty");
6762
7532
  }
6763
- throw new Error(`Unsupported key algorithm: ${publicKey.asymmetricKeyType ?? "unknown"}`);
6764
- }
6765
- // ---------------------------------------------------------------------------
6766
- // File metadata
6767
- // ---------------------------------------------------------------------------
6768
- /** Compute SHA-256 hash (base64) and byte length. */
6769
- getFileMetadata(file) {
6770
- const hash = crypto.createHash("sha256").update(file).digest("base64");
6771
- return { hashSHA: hash, fileSize: file.length };
6772
- }
6773
- // ---------------------------------------------------------------------------
6774
- // CSR generation
6775
- // ---------------------------------------------------------------------------
6776
- /** Generate an RSA-2048 CSR (PKCS#10, DER) and return it together with the private key PEM. */
6777
- async generateCsrRsa(fields) {
6778
- setCryptoProvider();
6779
- const algorithm = {
6780
- name: "RSASSA-PKCS1-v1_5",
6781
- hash: "SHA-256",
6782
- publicExponent: new Uint8Array([1, 0, 1]),
6783
- modulusLength: 2048
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
- const csrDer = new Uint8Array(csr.rawData);
6796
- const pkcs8 = await crypto.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
6797
- const privateKeyPem = pemEncode(new Uint8Array(pkcs8), "PRIVATE KEY");
6798
- return { csrDer, privateKeyPem };
6799
- }
6800
- /** Generate an ECDSA P-256 CSR (PKCS#10, DER) and return it together with the private key PEM. */
6801
- async generateCsrEcdsa(fields) {
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 setCryptoProvider() {
6872
- x509.cryptoProvider.set(crypto.webcrypto);
6873
- }
6874
- function buildX500Name(fields) {
7565
+ function splitBuffer(data, maxPartSize) {
7566
+ if (data.length <= maxPartSize) {
7567
+ return [data];
7568
+ }
6875
7569
  const parts = [];
6876
- if (fields.commonName) parts.push(`CN=${fields.commonName}`);
6877
- if (fields.givenName) parts.push(`2.5.4.42=${fields.givenName}`);
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 `-----BEGIN ${label}-----
6893
- ${lines.join("\n")}
6894
- -----END ${label}-----`;
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 crypto3 from "crypto";
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 crypto3.createHash("sha256").update(der).digest("hex").toUpperCase();
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(crypto3.webcrypto);
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 crypto3.webcrypto.subtle.generateKey(
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 crypto3.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
7645
+ const pkcs8 = await crypto4.webcrypto.subtle.exportKey("pkcs8", keys.privateKey);
6962
7646
  const privateKeyPem = pemEncode2(new Uint8Array(pkcs8), "PRIVATE KEY");
6963
- const fingerprint = crypto3.createHash("sha256").update(Buffer.from(cert.rawData)).digest("hex").toUpperCase();
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/verification-link-service.ts
6985
- import crypto4 from "crypto";
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
7092
7728
  }
7093
7729
 
7094
- // src/client.ts
7095
- var KSeFClient = class {
7096
- auth;
7097
- activeSessions;
7098
- onlineSession;
7099
- batchSession;
7100
- sessionStatus;
7101
- invoices;
7102
- permissions;
7103
- tokens;
7104
- certificates;
7105
- lighthouse;
7106
- limits;
7107
- peppol;
7108
- testData;
7109
- crypto;
7110
- qr;
7111
- options;
7112
- authManager;
7113
- constructor(options) {
7114
- this.options = resolveOptions(options);
7115
- const authManager = options?.authManager ?? new DefaultAuthManager(async () => {
7116
- const rt = this.authManager.getRefreshToken();
7117
- if (!rt) return null;
7118
- const res = await this.auth.refreshAccessToken(rt);
7119
- return res.accessToken.token;
7120
- });
7121
- this.authManager = authManager;
7122
- const restClientConfig = buildRestClientConfig(options, authManager);
7123
- const restClient = new RestClient(this.options, restClientConfig);
7124
- const fetcher = new CertificateFetcher(restClient);
7125
- this.crypto = new CryptographyService(fetcher);
7126
- this.auth = new AuthService(restClient);
7127
- this.activeSessions = new ActiveSessionsService(restClient);
7128
- this.onlineSession = new OnlineSessionService(restClient);
7129
- this.batchSession = new BatchSessionService(restClient);
7130
- this.sessionStatus = new SessionStatusService(restClient);
7131
- this.invoices = new InvoiceDownloadService(restClient);
7132
- this.permissions = new PermissionsService(restClient);
7133
- this.tokens = new TokenService(restClient);
7134
- this.certificates = new CertificateApiService(restClient);
7135
- this.lighthouse = new LighthouseService(this.options);
7136
- this.limits = new LimitsService(restClient);
7137
- this.peppol = new PeppolService(restClient);
7138
- this.testData = new TestDataService(restClient);
7139
- this.qr = new VerificationLinkService(this.options.baseQrUrl);
7140
- }
7141
- async loginWithToken(token, nip) {
7142
- const challenge = await this.auth.getChallenge();
7143
- await this.crypto.init();
7144
- const encryptedToken = this.crypto.encryptKsefToken(token, challenge.timestamp);
7145
- const submitResult = await this.auth.submitKsefTokenAuthRequest({
7146
- challenge: challenge.challenge,
7147
- contextIdentifier: { type: "Nip", value: nip },
7148
- encryptedToken: Buffer.from(encryptedToken).toString("base64")
7149
- });
7150
- const authToken = submitResult.authenticationToken.token;
7151
- await this.awaitAuthReady(submitResult.referenceNumber, authToken);
7152
- const tokens = await this.auth.getAccessToken(authToken);
7153
- this.authManager.setAccessToken(tokens.accessToken.token);
7154
- this.authManager.setRefreshToken(tokens.refreshToken.token);
7155
- }
7156
- async loginWithCertificate(certPem, keyPem, nip) {
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 xmlEscape(str) {
7202
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
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
- function buildRestClientConfig(options, authManager) {
7205
- const config = { authManager };
7206
- if (options?.transport) {
7207
- config.transport = options.transport;
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
- if (options?.retry) {
7210
- config.retryPolicy = { ...defaultRetryPolicy(), ...options.retry };
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 (options?.rateLimit === null) {
7213
- config.rateLimitPolicy = null;
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
- if (options?.presignedUrlHosts) {
7221
- const base = defaultPresignedUrlPolicy();
7222
- config.presignedUrlPolicy = {
7223
- ...base,
7224
- allowedHosts: [...base.allowedHosts, ...options.presignedUrlHosts]
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 config;
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