ksef-client-ts 0.6.2 → 0.7.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.cjs CHANGED
@@ -65,7 +65,8 @@ function resolveOptions(options = {}) {
65
65
  apiVersion: options.apiVersion ?? DEFAULT_API_VERSION,
66
66
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
67
67
  customHeaders: options.customHeaders ?? {},
68
- environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST")
68
+ environmentName: options.environment ?? (options.baseUrl ? void 0 : "TEST"),
69
+ errorFormat: options.errorFormat ?? "problem-details"
69
70
  };
70
71
  }
71
72
  var DEFAULT_API_VERSION, DEFAULT_TIMEOUT;
@@ -121,6 +122,9 @@ var init_ksef_api_error = __esm({
121
122
  const message = details?.length ? details.map((d) => d.exceptionDescription ?? "").filter(Boolean).join("; ") || `KSeF API error: HTTP ${statusCode}` : `KSeF API error: HTTP ${statusCode}`;
122
123
  return new _KSeFApiError(message, statusCode, body);
123
124
  }
125
+ toProblemFields() {
126
+ return { detail: this.message };
127
+ }
124
128
  };
125
129
  }
126
130
  });
@@ -132,17 +136,20 @@ var init_ksef_rate_limit_error = __esm({
132
136
  "use strict";
133
137
  init_ksef_api_error();
134
138
  KSeFRateLimitError = class _KSeFRateLimitError extends KSeFApiError {
139
+ statusCode = 429;
135
140
  retryAfterSeconds;
136
141
  retryAfterDate;
137
142
  recommendedDelay;
138
- constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate) {
143
+ problem;
144
+ constructor(message, statusCode, errorResponse, retryAfterSeconds, retryAfterDate, problem) {
139
145
  super(message, statusCode, errorResponse);
140
146
  this.name = "KSeFRateLimitError";
141
147
  this.retryAfterSeconds = retryAfterSeconds;
142
148
  this.retryAfterDate = retryAfterDate;
143
149
  this.recommendedDelay = retryAfterSeconds ?? 60;
150
+ this.problem = problem;
144
151
  }
145
- static fromRetryAfterHeader(statusCode, retryAfterHeader, body) {
152
+ static fromRetryAfterHeader(statusCode, retryAfterHeader, body, problem) {
146
153
  let retryAfterSeconds;
147
154
  let retryAfterDate;
148
155
  if (retryAfterHeader) {
@@ -157,8 +164,16 @@ var init_ksef_rate_limit_error = __esm({
157
164
  }
158
165
  }
159
166
  }
160
- const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : "Rate limited by KSeF API";
161
- return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate);
167
+ const message = retryAfterSeconds != null ? `Rate limited. Retry after ${retryAfterSeconds}s` : problem?.detail ?? "Rate limited by KSeF API";
168
+ return new _KSeFRateLimitError(message, statusCode, body, retryAfterSeconds, retryAfterDate, problem);
169
+ }
170
+ toProblemFields() {
171
+ return {
172
+ detail: this.problem?.detail,
173
+ traceId: this.problem?.traceId,
174
+ instance: this.problem?.instance,
175
+ timestamp: this.problem?.timestamp
176
+ };
162
177
  }
163
178
  };
164
179
  }
@@ -169,21 +184,29 @@ var KSeFUnauthorizedError;
169
184
  var init_ksef_unauthorized_error = __esm({
170
185
  "src/errors/ksef-unauthorized-error.ts"() {
171
186
  "use strict";
172
- init_ksef_error();
173
- KSeFUnauthorizedError = class extends KSeFError {
187
+ init_ksef_api_error();
188
+ KSeFUnauthorizedError = class extends KSeFApiError {
174
189
  statusCode = 401;
175
190
  detail;
176
191
  traceId;
177
192
  instance;
178
193
  timestamp;
179
194
  constructor(problemDetails) {
180
- super(problemDetails.detail || "Unauthorized");
195
+ super(problemDetails.detail || "Unauthorized", 401);
181
196
  this.name = "KSeFUnauthorizedError";
182
197
  this.detail = problemDetails.detail;
183
198
  this.traceId = problemDetails.traceId;
184
199
  this.instance = problemDetails.instance;
185
200
  this.timestamp = problemDetails.timestamp;
186
201
  }
202
+ toProblemFields() {
203
+ return {
204
+ detail: this.detail,
205
+ traceId: this.traceId,
206
+ instance: this.instance,
207
+ timestamp: this.timestamp
208
+ };
209
+ }
187
210
  };
188
211
  }
189
212
  });
@@ -193,8 +216,8 @@ var KSeFForbiddenError;
193
216
  var init_ksef_forbidden_error = __esm({
194
217
  "src/errors/ksef-forbidden-error.ts"() {
195
218
  "use strict";
196
- init_ksef_error();
197
- KSeFForbiddenError = class extends KSeFError {
219
+ init_ksef_api_error();
220
+ KSeFForbiddenError = class extends KSeFApiError {
198
221
  statusCode = 403;
199
222
  detail;
200
223
  reasonCode;
@@ -203,7 +226,7 @@ var init_ksef_forbidden_error = __esm({
203
226
  traceId;
204
227
  timestamp;
205
228
  constructor(problemDetails) {
206
- super(problemDetails.detail || "Forbidden");
229
+ super(problemDetails.detail || "Forbidden", 403);
207
230
  this.name = "KSeFForbiddenError";
208
231
  this.detail = problemDetails.detail;
209
232
  this.reasonCode = problemDetails.reasonCode;
@@ -212,6 +235,16 @@ var init_ksef_forbidden_error = __esm({
212
235
  this.traceId = problemDetails.traceId;
213
236
  this.timestamp = problemDetails.timestamp;
214
237
  }
238
+ toProblemFields() {
239
+ return {
240
+ detail: this.detail,
241
+ reasonCode: this.reasonCode,
242
+ security: this.security,
243
+ traceId: this.traceId,
244
+ instance: this.instance,
245
+ timestamp: this.timestamp
246
+ };
247
+ }
215
248
  };
216
249
  }
217
250
  });
@@ -221,21 +254,64 @@ var KSeFGoneError;
221
254
  var init_ksef_gone_error = __esm({
222
255
  "src/errors/ksef-gone-error.ts"() {
223
256
  "use strict";
224
- init_ksef_error();
225
- KSeFGoneError = class extends KSeFError {
257
+ init_ksef_api_error();
258
+ KSeFGoneError = class extends KSeFApiError {
226
259
  statusCode = 410;
227
260
  detail;
228
261
  instance;
229
262
  traceId;
230
263
  timestamp;
231
264
  constructor(problemDetails) {
232
- super(problemDetails.detail || "Operation status no longer available (retention expired)");
265
+ super(problemDetails.detail || "Operation status no longer available (retention expired)", 410);
233
266
  this.name = "KSeFGoneError";
234
267
  this.detail = problemDetails.detail;
235
268
  this.instance = problemDetails.instance;
236
269
  this.traceId = problemDetails.traceId;
237
270
  this.timestamp = problemDetails.timestamp;
238
271
  }
272
+ toProblemFields() {
273
+ return {
274
+ detail: this.detail,
275
+ traceId: this.traceId,
276
+ instance: this.instance,
277
+ timestamp: this.timestamp
278
+ };
279
+ }
280
+ };
281
+ }
282
+ });
283
+
284
+ // src/errors/ksef-bad-request-error.ts
285
+ var KSeFBadRequestError;
286
+ var init_ksef_bad_request_error = __esm({
287
+ "src/errors/ksef-bad-request-error.ts"() {
288
+ "use strict";
289
+ init_ksef_api_error();
290
+ KSeFBadRequestError = class extends KSeFApiError {
291
+ statusCode = 400;
292
+ detail;
293
+ instance;
294
+ errors;
295
+ traceId;
296
+ timestamp;
297
+ constructor(problemDetails) {
298
+ super(problemDetails.detail || problemDetails.title || "Bad Request", 400);
299
+ this.name = "KSeFBadRequestError";
300
+ this.detail = problemDetails.detail;
301
+ this.instance = problemDetails.instance;
302
+ this.errors = problemDetails.errors ?? [];
303
+ this.traceId = problemDetails.traceId;
304
+ this.timestamp = problemDetails.timestamp;
305
+ }
306
+ toProblemFields() {
307
+ return {
308
+ detail: this.detail,
309
+ errors: this.errors.length ? this.errors : void 0,
310
+ traceId: this.traceId,
311
+ instance: this.instance,
312
+ timestamp: this.timestamp
313
+ };
314
+ }
239
315
  };
240
316
  }
241
317
  });
@@ -341,6 +417,16 @@ var init_ksef_batch_timeout_error = __esm({
341
417
  }
342
418
  });
343
419
 
420
+ // src/errors/assert-never.ts
421
+ function assertNever(value) {
422
+ throw new Error(`Unexpected value: ${String(value)}`);
423
+ }
424
+ var init_assert_never = __esm({
425
+ "src/errors/assert-never.ts"() {
426
+ "use strict";
427
+ }
428
+ });
429
+
344
430
  // src/errors/index.ts
345
431
  var init_errors = __esm({
346
432
  "src/errors/index.ts"() {
@@ -351,11 +437,13 @@ var init_errors = __esm({
351
437
  init_ksef_unauthorized_error();
352
438
  init_ksef_forbidden_error();
353
439
  init_ksef_gone_error();
440
+ init_ksef_bad_request_error();
354
441
  init_ksef_auth_status_error();
355
442
  init_ksef_session_expired_error();
356
443
  init_ksef_validation_error();
357
444
  init_ksef_batch_timeout_error();
358
445
  init_error_codes();
446
+ init_assert_never();
359
447
  }
360
448
  });
361
449
 
@@ -603,6 +691,27 @@ var init_presigned_url_policy = __esm({
603
691
  });
604
692
 
605
693
  // src/http/rest-client.ts
694
+ function isBadRequestProblem(value) {
695
+ if (typeof value !== "object" || value === null) return false;
696
+ const v = value;
697
+ if (typeof v.title !== "string") return false;
698
+ if (v.status !== void 0 && typeof v.status !== "number") return false;
699
+ if (v.errors !== void 0) {
700
+ if (!Array.isArray(v.errors)) return false;
701
+ for (const item of v.errors) {
702
+ if (typeof item !== "object" || item === null) return false;
703
+ const detail = item;
704
+ if (typeof detail.code !== "number") return false;
705
+ if (typeof detail.description !== "string") return false;
706
+ }
707
+ }
708
+ return true;
709
+ }
710
+ function isTooManyRequestsProblem(value) {
711
+ if (typeof value !== "object" || value === null) return false;
712
+ const v = value;
713
+ return typeof v.title === "string" && (v.status === void 0 || typeof v.status === "number") && (v.detail === void 0 || typeof v.detail === "string") && (v.instance === void 0 || typeof v.instance === "string") && (v.traceId === void 0 || typeof v.traceId === "string") && (v.timestamp === void 0 || typeof v.timestamp === "string");
714
+ }
606
715
  var import_consola, RestClient;
607
716
  var init_rest_client = __esm({
608
717
  "src/http/rest-client.ts"() {
@@ -613,6 +722,7 @@ var init_rest_client = __esm({
613
722
  init_ksef_unauthorized_error();
614
723
  init_ksef_forbidden_error();
615
724
  init_ksef_gone_error();
725
+ init_ksef_bad_request_error();
616
726
  init_ksef_batch_timeout_error();
617
727
  init_error_codes();
618
728
  init_route_builder();
@@ -701,6 +811,10 @@ var init_rest_client = __esm({
701
811
  ...this.options.customHeaders,
702
812
  ...request.getHeaders()
703
813
  };
814
+ const hasHeader = (name) => Object.keys(headers).some((header) => header.toLowerCase() === name.toLowerCase());
815
+ if (this.options.errorFormat !== "legacy" && !hasHeader("x-error-format")) {
816
+ headers["X-Error-Format"] = "problem-details";
817
+ }
704
818
  if (!headers["Authorization"] && this.authManager) {
705
819
  const token = overrideToken ?? this.authManager.getAccessToken();
706
820
  if (token) {
@@ -739,19 +853,40 @@ var init_rest_client = __esm({
739
853
  async ensureSuccess(response) {
740
854
  if (response.ok) return;
741
855
  const text = await response.text().catch(() => "");
856
+ let jsonCache = null;
742
857
  const parseJson = () => {
743
- try {
744
- return JSON.parse(text);
745
- } catch {
746
- return void 0;
858
+ if (jsonCache === null) {
859
+ try {
860
+ jsonCache = { value: JSON.parse(text) };
861
+ } catch {
862
+ jsonCache = { value: void 0 };
863
+ }
747
864
  }
865
+ return jsonCache.value;
748
866
  };
749
- if (response.status === 429) {
867
+ const tryParseProblem = (guard) => {
750
868
  const parsed = parseJson();
869
+ return parsed !== void 0 && guard(parsed) ? parsed : void 0;
870
+ };
871
+ if (response.status === 400) {
872
+ const problem = tryParseProblem(isBadRequestProblem);
873
+ if (problem) {
874
+ throw new KSeFBadRequestError(problem);
875
+ }
876
+ const legacy = parseJson();
877
+ if (hasErrorCode(legacy, KSeFErrorCode.BatchTimeout)) {
878
+ throw KSeFBatchTimeoutError.fromResponse(400, legacy);
879
+ }
880
+ throw KSeFApiError.fromResponse(400, legacy);
881
+ }
882
+ if (response.status === 429) {
883
+ const problem = tryParseProblem(isTooManyRequestsProblem);
884
+ const legacy = problem ? void 0 : parseJson();
751
885
  throw KSeFRateLimitError.fromRetryAfterHeader(
752
886
  response.status,
753
887
  response.headers.get("Retry-After"),
754
- parsed
888
+ legacy,
889
+ problem
755
890
  );
756
891
  }
757
892
  if (response.status === 401) {
@@ -2701,6 +2836,115 @@ var init_schema_registry = __esm({
2701
2836
  }
2702
2837
  });
2703
2838
 
2839
+ // src/validation/char-validity.ts
2840
+ function validateCharValidity(xml) {
2841
+ return [...findProcessingInstructions(xml), ...findDiscouragedUnicode(xml)];
2842
+ }
2843
+ function findProcessingInstructionTokens(xml) {
2844
+ const tokens = [];
2845
+ for (let i = 0; i < xml.length; ) {
2846
+ if (xml.startsWith("<!--", i)) {
2847
+ const end = xml.indexOf("-->", i + 4);
2848
+ i = end === -1 ? xml.length : end + 3;
2849
+ continue;
2850
+ }
2851
+ if (xml.startsWith("<![CDATA[", i)) {
2852
+ const end = xml.indexOf("]]>", i + 9);
2853
+ i = end === -1 ? xml.length : end + 3;
2854
+ continue;
2855
+ }
2856
+ if (xml.startsWith("<?", i)) {
2857
+ const end = xml.indexOf("?>", i + 2);
2858
+ if (end === -1) break;
2859
+ tokens.push({ token: xml.slice(i, end + 2), index: i });
2860
+ i = end + 2;
2861
+ continue;
2862
+ }
2863
+ i += 1;
2864
+ }
2865
+ return tokens;
2866
+ }
2867
+ function findProcessingInstructions(xml) {
2868
+ const errors = [];
2869
+ const matches = findProcessingInstructionTokens(xml);
2870
+ if (matches.length === 0) return errors;
2871
+ const firstMatch = matches[0];
2872
+ const firstTarget = firstMatch.token.match(PI_TARGET_RE)?.[1];
2873
+ const hasBom = xml.charCodeAt(0) === 65279;
2874
+ const prologPosition = hasBom ? 1 : 0;
2875
+ const firstIsProlog = firstMatch.index === prologPosition && firstTarget === "xml";
2876
+ for (let i = 0; i < matches.length; i++) {
2877
+ if (i === 0 && firstIsProlog) continue;
2878
+ const m = matches[i];
2879
+ const target = m.token.match(PI_TARGET_RE)?.[1] ?? "?";
2880
+ errors.push({
2881
+ code: "XML_PROCESSING_INSTRUCTION",
2882
+ message: `Processing instruction <?${target}?> at offset ${m.index} is not allowed (only <?xml ... ?> prolog is permitted)`,
2883
+ path: `offset:${m.index}`
2884
+ });
2885
+ }
2886
+ return errors;
2887
+ }
2888
+ function findDiscouragedUnicode(xml) {
2889
+ const errors = [];
2890
+ const seenRanges = /* @__PURE__ */ new Set();
2891
+ let utf16Offset = 0;
2892
+ for (const ch of xml) {
2893
+ const cp = ch.codePointAt(0);
2894
+ const idx = rangeIndex(cp);
2895
+ if (idx >= 0 && !seenRanges.has(idx)) {
2896
+ seenRanges.add(idx);
2897
+ errors.push({
2898
+ code: "XML_DISCOURAGED_UNICODE",
2899
+ message: `Discouraged Unicode character U+${cp.toString(16).toUpperCase().padStart(4, "0")} found at offset ${utf16Offset} (W3C XML 1.0 \xA72.2 rejects this range)`,
2900
+ path: `offset:${utf16Offset}`
2901
+ });
2902
+ }
2903
+ utf16Offset += ch.length;
2904
+ }
2905
+ return errors;
2906
+ }
2907
+ function rangeIndex(cp) {
2908
+ let lo = 0;
2909
+ let hi = DISCOURAGED_UNICODE_RANGES.length - 1;
2910
+ while (lo <= hi) {
2911
+ const mid = lo + hi >> 1;
2912
+ const [start, end] = DISCOURAGED_UNICODE_RANGES[mid];
2913
+ if (cp < start) hi = mid - 1;
2914
+ else if (cp > end) lo = mid + 1;
2915
+ else return mid;
2916
+ }
2917
+ return -1;
2918
+ }
2919
+ var DISCOURAGED_UNICODE_RANGES, PI_TARGET_RE;
2920
+ var init_char_validity = __esm({
2921
+ "src/validation/char-validity.ts"() {
2922
+ "use strict";
2923
+ DISCOURAGED_UNICODE_RANGES = [
2924
+ [127, 132],
2925
+ [134, 159],
2926
+ [64976, 65007],
2927
+ [131070, 131071],
2928
+ [196606, 196607],
2929
+ [262142, 262143],
2930
+ [327678, 327679],
2931
+ [393214, 393215],
2932
+ [458750, 458751],
2933
+ [524286, 524287],
2934
+ [589822, 589823],
2935
+ [655358, 655359],
2936
+ [720894, 720895],
2937
+ [786430, 786431],
2938
+ [851966, 851967],
2939
+ [917502, 917503],
2940
+ [983038, 983039],
2941
+ [1048574, 1048575],
2942
+ [1114110, 1114111]
2943
+ ];
2944
+ PI_TARGET_RE = /^<\?(\S+)/;
2945
+ }
2946
+ });
2947
+
2704
2948
  // src/validation/invoice-validator.ts
2705
2949
  var invoice_validator_exports = {};
2706
2950
  __export(invoice_validator_exports, {
@@ -2853,6 +3097,12 @@ function collectDateErrors(obj, rootElement, errors) {
2853
3097
  }
2854
3098
  }
2855
3099
  async function validate(xml, options) {
3100
+ if (!options?.skipCharValidity) {
3101
+ const l1aErrors = validateCharValidity(xml);
3102
+ if (l1aErrors.length > 0) {
3103
+ return { valid: false, schemaType: null, errors: l1aErrors };
3104
+ }
3105
+ }
2856
3106
  const parsed = xml && xml.trim() ? xmlToObject(xml) : void 0;
2857
3107
  const l1 = validateWellFormedness(xml, parsed);
2858
3108
  if (!l1.valid) return l1;
@@ -2879,6 +3129,7 @@ var init_invoice_validator = __esm({
2879
3129
  "use strict";
2880
3130
  init_xml_to_object();
2881
3131
  init_schema_registry();
3132
+ init_char_validity();
2882
3133
  init_patterns();
2883
3134
  }
2884
3135
  });
@@ -3343,9 +3594,10 @@ var PermissionsService;
3343
3594
  var init_permissions = __esm({
3344
3595
  "src/services/permissions.ts"() {
3345
3596
  "use strict";
3597
+ init_ksef_validation_error();
3346
3598
  init_rest_request();
3347
3599
  init_routes();
3348
- PermissionsService = class {
3600
+ PermissionsService = class _PermissionsService {
3349
3601
  restClient;
3350
3602
  constructor(restClient) {
3351
3603
  this.restClient = restClient;
@@ -3403,6 +3655,7 @@ var init_permissions = __esm({
3403
3655
  }
3404
3656
  // Search methods
3405
3657
  async queryPersonalGrants(options, pageOffset, pageSize) {
3658
+ _PermissionsService.validateContextIdentifier(options?.contextIdentifier);
3406
3659
  const req = RestRequest.post(Routes.Permissions.Query.personalGrants).body(options ?? {});
3407
3660
  if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
3408
3661
  if (pageSize !== void 0) req.query("pageSize", String(pageSize));
@@ -3431,6 +3684,7 @@ var init_permissions = __esm({
3431
3684
  return response.body;
3432
3685
  }
3433
3686
  async queryEntitiesGrants(options, pageOffset, pageSize) {
3687
+ _PermissionsService.validateContextIdentifier(options?.contextIdentifier);
3434
3688
  const req = RestRequest.post(Routes.Permissions.Query.entitiesGrants).body(options ?? {});
3435
3689
  if (pageOffset !== void 0) req.query("pageOffset", String(pageOffset));
3436
3690
  if (pageSize !== void 0) req.query("pageSize", String(pageSize));
@@ -3469,17 +3723,90 @@ var init_permissions = __esm({
3469
3723
  const response = await this.restClient.execute(req);
3470
3724
  return response.body;
3471
3725
  }
3726
+ static validateContextIdentifier(ctx) {
3727
+ if (!ctx) return;
3728
+ if (ctx.type === "InternalId") {
3729
+ const len = ctx.value.length;
3730
+ if (len < 10 || len > 16) {
3731
+ throw KSeFValidationError.fromField(
3732
+ "contextIdentifier.value",
3733
+ `InternalId must be 10-16 characters, got ${len}`
3734
+ );
3735
+ }
3736
+ }
3737
+ }
3472
3738
  };
3473
3739
  }
3474
3740
  });
3475
3741
 
3742
+ // src/utils/jwt.ts
3743
+ function decodeJwtPayload(token) {
3744
+ const parts = token.split(".");
3745
+ if (parts.length !== 3) return null;
3746
+ try {
3747
+ const payload = parts[1];
3748
+ const json = Buffer.from(payload, "base64url").toString("utf-8");
3749
+ return JSON.parse(json);
3750
+ } catch {
3751
+ return null;
3752
+ }
3753
+ }
3754
+ function tryParseJson(value) {
3755
+ if (typeof value !== "string") return void 0;
3756
+ try {
3757
+ return JSON.parse(value);
3758
+ } catch {
3759
+ return void 0;
3760
+ }
3761
+ }
3762
+ function tryParseJsonArray(value) {
3763
+ if (typeof value !== "string") return void 0;
3764
+ try {
3765
+ const parsed = JSON.parse(value);
3766
+ return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
3767
+ } catch {
3768
+ return void 0;
3769
+ }
3770
+ }
3771
+ function parseKSeFTokenContext(token) {
3772
+ const raw = decodeJwtPayload(token);
3773
+ if (!raw) return null;
3774
+ return {
3775
+ type: typeof raw["typ"] === "string" ? raw["typ"] : void 0,
3776
+ contextIdentifierType: typeof raw["cit"] === "string" ? raw["cit"] : void 0,
3777
+ contextIdentifierValue: typeof raw["civ"] === "string" ? raw["civ"] : void 0,
3778
+ authMethod: typeof raw["aum"] === "string" ? raw["aum"] : void 0,
3779
+ permissions: tryParseJsonArray(raw["per"]),
3780
+ subjectDetails: tryParseJson(raw["sud"]),
3781
+ authorSubjectIdentifier: tryParseJson(raw["asi"]),
3782
+ issuedAt: typeof raw["iat"] === "number" ? raw["iat"] : void 0,
3783
+ expiresAt: typeof raw["exp"] === "number" ? raw["exp"] : void 0
3784
+ };
3785
+ }
3786
+ var init_jwt = __esm({
3787
+ "src/utils/jwt.ts"() {
3788
+ "use strict";
3789
+ }
3790
+ });
3791
+
3476
3792
  // src/services/tokens.ts
3477
- var TokenService;
3793
+ function toTokenAuthorIdentifierType(value) {
3794
+ return TOKEN_AUTHOR_IDENTIFIER_TYPES.has(value) ? value : void 0;
3795
+ }
3796
+ var TOKEN_AUTHOR_IDENTIFIER_TYPES, TokenService;
3478
3797
  var init_tokens = __esm({
3479
3798
  "src/services/tokens.ts"() {
3480
3799
  "use strict";
3481
3800
  init_rest_request();
3482
3801
  init_routes();
3802
+ init_jwt();
3803
+ init_ksef_api_error();
3804
+ init_ksef_error();
3805
+ TOKEN_AUTHOR_IDENTIFIER_TYPES = /* @__PURE__ */ new Set([
3806
+ "Nip",
3807
+ "Pesel",
3808
+ "Fingerprint"
3809
+ ]);
3483
3810
  TokenService = class {
3484
3811
  restClient;
3485
3812
  constructor(restClient) {
@@ -3514,6 +3841,73 @@ var init_tokens = __esm({
3514
3841
  const req = RestRequest.delete(Routes.Tokens.byReference(ref));
3515
3842
  await this.restClient.executeVoid(req);
3516
3843
  }
3844
+ /**
3845
+ * Resolves the reference number of the token currently in use for authentication.
3846
+ * The only JWT payload field treated as authoritative is the KSeF-specific `trn`
3847
+ * (token reference number). Standard RFC 7519 claims such as `jti` are NOT a safe
3848
+ * fallback — a `jti` that differs from the KSeF reference would cause a DELETE to
3849
+ * hit a non-existent path, which `revokeSelf` treats as already-revoked, falsely
3850
+ * reporting success while leaving the token active on the server. When `trn` is
3851
+ * absent, we fall back to `GET /tokens` filtered by author and context; requires
3852
+ * exactly one active match and returns undefined when ambiguous.
3853
+ */
3854
+ async findSelfReferenceNumber(accessToken) {
3855
+ if (!accessToken) return void 0;
3856
+ const payload = decodeJwtPayload(accessToken);
3857
+ if (payload && typeof payload["trn"] === "string" && payload["trn"].length > 0) {
3858
+ return payload["trn"];
3859
+ }
3860
+ const ctx = parseKSeFTokenContext(accessToken);
3861
+ const author = ctx?.authorSubjectIdentifier;
3862
+ if (!author?.type || !author.value) return void 0;
3863
+ if (!ctx?.contextIdentifierType || !ctx?.contextIdentifierValue) return void 0;
3864
+ const authorType = toTokenAuthorIdentifierType(author.type);
3865
+ if (!authorType) return void 0;
3866
+ let continuationToken;
3867
+ let match;
3868
+ do {
3869
+ const list = await this.queryTokens({
3870
+ status: ["Active"],
3871
+ authorIdentifier: author.value,
3872
+ authorIdentifierType: authorType,
3873
+ pageSize: 50,
3874
+ continuationToken
3875
+ });
3876
+ for (const t of list.tokens) {
3877
+ if (t.status === "Active" && t.contextIdentifier?.value === ctx.contextIdentifierValue && t.contextIdentifier?.type === ctx.contextIdentifierType) {
3878
+ if (match) return void 0;
3879
+ match = t.referenceNumber;
3880
+ }
3881
+ }
3882
+ continuationToken = list.continuationToken ?? void 0;
3883
+ } while (continuationToken);
3884
+ return match;
3885
+ }
3886
+ /**
3887
+ * Revokes the token currently used for authentication.
3888
+ * Treats 404/409/410 on DELETE as "already revoked" and returns successfully with
3889
+ * `alreadyRevoked: true` so callers can still clear local state.
3890
+ */
3891
+ async revokeSelf(opts = {}) {
3892
+ let ref = opts.referenceNumber;
3893
+ if (!ref && opts.accessToken) {
3894
+ ref = await this.findSelfReferenceNumber(opts.accessToken);
3895
+ }
3896
+ if (!ref) {
3897
+ throw new KSeFError(
3898
+ "Could not determine the current token reference number: no cache, JWT lacks the field, and the active-token list had 0 or 2+ matches in the current context."
3899
+ );
3900
+ }
3901
+ try {
3902
+ await this.revokeToken(ref);
3903
+ return { referenceNumber: ref, alreadyRevoked: false };
3904
+ } catch (err) {
3905
+ if (err instanceof KSeFApiError && (err.statusCode === 404 || err.statusCode === 409 || err.statusCode === 410)) {
3906
+ return { referenceNumber: ref, alreadyRevoked: true };
3907
+ }
3908
+ throw err;
3909
+ }
3910
+ }
3517
3911
  };
3518
3912
  }
3519
3913
  });
@@ -4139,8 +4533,8 @@ function computeRootDigest(doc) {
4139
4533
  return crypto3.createHash("sha256").update(canonical, "utf-8").digest("base64");
4140
4534
  }
4141
4535
  function computeSignedPropertiesDigest(qualifyingPropertiesXml) {
4142
- const parser = new import_xmldom2.DOMParser();
4143
- const qpDoc = parser.parseFromString(qualifyingPropertiesXml, "text/xml");
4536
+ const parser2 = new import_xmldom2.DOMParser();
4537
+ const qpDoc = parser2.parseFromString(qualifyingPropertiesXml, "text/xml");
4144
4538
  const signedProps = findElementByLocalName(qpDoc.documentElement, "SignedProperties");
4145
4539
  if (!signedProps) {
4146
4540
  throw new Error("SignedProperties element not found in QualifyingProperties");
@@ -4295,8 +4689,8 @@ var init_signature_service = __esm({
4295
4689
  const isEc = privateKey.asymmetricKeyType === "ec";
4296
4690
  const signatureAlgorithm = isEc ? ECDSA_SHA256_SIGNATURE : RSA_SHA256_SIGNATURE;
4297
4691
  const signingTime = new Date(Date.now() + CLOCK_SKEW_BUFFER_MS).toISOString();
4298
- const parser = new import_xmldom2.DOMParser();
4299
- const doc = parser.parseFromString(xml, "text/xml");
4692
+ const parser2 = new import_xmldom2.DOMParser();
4693
+ const doc = parser2.parseFromString(xml, "text/xml");
4300
4694
  const root = doc.documentElement;
4301
4695
  if (!root) {
4302
4696
  throw new Error("XML document has no root element");
@@ -4316,7 +4710,7 @@ var init_signature_service = __esm({
4316
4710
  rootDigest,
4317
4711
  signedPropertiesDigest
4318
4712
  );
4319
- const signedInfoDoc = parser.parseFromString(signedInfoXml, "text/xml");
4713
+ const signedInfoDoc = parser2.parseFromString(signedInfoXml, "text/xml");
4320
4714
  const canonicalSignedInfo = canonicalize(signedInfoDoc.documentElement);
4321
4715
  const signatureValue = computeSignatureValue(
4322
4716
  canonicalSignedInfo,
@@ -4329,7 +4723,7 @@ var init_signature_service = __esm({
4329
4723
  certBase64,
4330
4724
  qualifyingPropertiesXml
4331
4725
  );
4332
- const signatureDoc = parser.parseFromString(signatureXml, "text/xml");
4726
+ const signatureDoc = parser2.parseFromString(signatureXml, "text/xml");
4333
4727
  const importedNode = doc.importNode(signatureDoc.documentElement, true);
4334
4728
  root.appendChild(importedNode);
4335
4729
  return new import_xmldom2.XMLSerializer().serializeToString(doc);
@@ -5229,10 +5623,13 @@ __export(index_exports, {
5229
5623
  CertificateService: () => CertificateService,
5230
5624
  CryptographyService: () => CryptographyService,
5231
5625
  DEFAULT_FORM_CODE: () => DEFAULT_FORM_CODE,
5626
+ DISCOURAGED_UNICODE_RANGES: () => DISCOURAGED_UNICODE_RANGES,
5232
5627
  DefaultAuthManager: () => DefaultAuthManager,
5233
5628
  ENFORCE_XADES_COMPLIANCE: () => ENFORCE_XADES_COMPLIANCE,
5629
+ ETD_NAMESPACE: () => ETD_NAMESPACE,
5234
5630
  EntityPermissionGrantBuilder: () => EntityPermissionGrantBuilder,
5235
5631
  Environment: () => Environment,
5632
+ FAKTURA_NAMESPACE: () => FAKTURA_NAMESPACE,
5236
5633
  FORM_CODES: () => FORM_CODES,
5237
5634
  FORM_CODE_KEYS: () => FORM_CODE_KEYS,
5238
5635
  FileHwmStore: () => FileHwmStore,
@@ -5249,6 +5646,7 @@ __export(index_exports, {
5249
5646
  KSEF_FEATURE_HEADER: () => KSEF_FEATURE_HEADER,
5250
5647
  KSeFApiError: () => KSeFApiError,
5251
5648
  KSeFAuthStatusError: () => KSeFAuthStatusError,
5649
+ KSeFBadRequestError: () => KSeFBadRequestError,
5252
5650
  KSeFBatchTimeoutError: () => KSeFBatchTimeoutError,
5253
5651
  KSeFClient: () => KSeFClient,
5254
5652
  KSeFError: () => KSeFError,
@@ -5266,8 +5664,10 @@ __export(index_exports, {
5266
5664
  LimitsService: () => LimitsService,
5267
5665
  Nip: () => Nip,
5268
5666
  NipVatUe: () => NipVatUe,
5667
+ ORDER_MAP: () => ORDER_MAP,
5269
5668
  OfflineInvoiceWorkflow: () => OfflineInvoiceWorkflow,
5270
5669
  OnlineSessionService: () => OnlineSessionService,
5670
+ PEF_NAMESPACE: () => PEF_NAMESPACE,
5271
5671
  PERMISSION_DESCRIPTION_MAX_LENGTH: () => PERMISSION_DESCRIPTION_MAX_LENGTH,
5272
5672
  PERMISSION_DESCRIPTION_MIN_LENGTH: () => PERMISSION_DESCRIPTION_MIN_LENGTH,
5273
5673
  PeppolId: () => PeppolId,
@@ -5297,14 +5697,21 @@ __export(index_exports, {
5297
5697
  VatUe: () => VatUe,
5298
5698
  VerificationLinkService: () => VerificationLinkService,
5299
5699
  addBusinessDays: () => addBusinessDays,
5700
+ assertNever: () => assertNever,
5300
5701
  authenticateWithCertificate: () => authenticateWithCertificate,
5301
5702
  authenticateWithExternalSignature: () => authenticateWithExternalSignature,
5302
5703
  authenticateWithPkcs12: () => authenticateWithPkcs12,
5303
5704
  authenticateWithToken: () => authenticateWithToken,
5304
5705
  batchValidationDetails: () => batchValidationDetails,
5706
+ buildFakturaXml: () => buildFakturaXml,
5707
+ buildPefXml: () => buildPefXml,
5708
+ buildRawXmlString: () => buildRawXmlString,
5305
5709
  buildUnsignedAuthTokenRequestXml: () => buildUnsignedAuthTokenRequestXml,
5710
+ buildXml: () => buildXml,
5711
+ buildXmlFromObject: () => buildXmlFromObject,
5306
5712
  calculateBackoff: () => calculateBackoff,
5307
5713
  calculateOfflineDeadline: () => calculateOfflineDeadline,
5714
+ comparePKey: () => comparePKey,
5308
5715
  createZip: () => createZip,
5309
5716
  decodeJwtPayload: () => decodeJwtPayload,
5310
5717
  deduplicateByKsefNumber: () => deduplicateByKsefNumber,
@@ -5323,6 +5730,9 @@ __export(index_exports, {
5323
5730
  getTimeUntilDeadline: () => getTimeUntilDeadline,
5324
5731
  incrementalExportAndDownload: () => incrementalExportAndDownload,
5325
5732
  isExpired: () => isExpired,
5733
+ isFakturaInput: () => isFakturaInput,
5734
+ isFormCodeShape: () => isFormCodeShape,
5735
+ isPefUblDocumentInput: () => isPefUblDocumentInput,
5326
5736
  isPolishHoliday: () => isPolishHoliday,
5327
5737
  isRetryableError: () => isRetryableError,
5328
5738
  isRetryableStatus: () => isRetryableStatus,
@@ -5344,16 +5754,21 @@ __export(index_exports, {
5344
5754
  nextBusinessDay: () => nextBusinessDay,
5345
5755
  openOnlineSession: () => openOnlineSession,
5346
5756
  openSendAndClose: () => openSendAndClose,
5757
+ orderXmlObject: () => orderXmlObject,
5347
5758
  parseFormCode: () => parseFormCode,
5348
5759
  parseKSeFTokenContext: () => parseKSeFTokenContext,
5349
5760
  parseRetryAfter: () => parseRetryAfter,
5350
5761
  parseUpoXml: () => parseUpoXml,
5762
+ parseXml: () => parseXml,
5351
5763
  pollUntil: () => pollUntil,
5352
5764
  resolveOptions: () => resolveOptions,
5353
5765
  resumeOnlineSession: () => resumeOnlineSession,
5354
5766
  runWithConcurrency: () => runWithConcurrency,
5767
+ serializeInvoiceXml: () => serializeInvoiceXml,
5355
5768
  sha256Base64: () => sha256Base642,
5356
5769
  sleep: () => sleep,
5770
+ stripBom: () => stripBom,
5771
+ toKodFormularza: () => toKodFormularza,
5357
5772
  unzip: () => unzip,
5358
5773
  updateContinuationPoint: () => updateContinuationPoint,
5359
5774
  uploadBatch: () => uploadBatch,
@@ -5363,6 +5778,7 @@ __export(index_exports, {
5363
5778
  validate: () => validate,
5364
5779
  validateBatch: () => validateBatch,
5365
5780
  validateBusinessRules: () => validateBusinessRules,
5781
+ validateCharValidity: () => validateCharValidity,
5366
5782
  validateFormCodeForSession: () => validateFormCodeForSession,
5367
5783
  validatePresignedUrl: () => validatePresignedUrl,
5368
5784
  validateSchema: () => validateSchema,
@@ -5402,6 +5818,7 @@ var PERMISSION_DESCRIPTION_MAX_LENGTH = 256;
5402
5818
  init_xml_to_object();
5403
5819
  init_schema_registry();
5404
5820
  init_invoice_validator();
5821
+ init_char_validity();
5405
5822
 
5406
5823
  // src/models/index.ts
5407
5824
  init_document_structures();
@@ -6093,51 +6510,7 @@ function escapeXml2(str) {
6093
6510
 
6094
6511
  // src/utils/index.ts
6095
6512
  init_zip();
6096
-
6097
- // src/utils/jwt.ts
6098
- function decodeJwtPayload(token) {
6099
- const parts = token.split(".");
6100
- if (parts.length !== 3) return null;
6101
- try {
6102
- const payload = parts[1];
6103
- const json = Buffer.from(payload, "base64url").toString("utf-8");
6104
- return JSON.parse(json);
6105
- } catch {
6106
- return null;
6107
- }
6108
- }
6109
- function tryParseJson(value) {
6110
- if (typeof value !== "string") return void 0;
6111
- try {
6112
- return JSON.parse(value);
6113
- } catch {
6114
- return void 0;
6115
- }
6116
- }
6117
- function tryParseJsonArray(value) {
6118
- if (typeof value !== "string") return void 0;
6119
- try {
6120
- const parsed = JSON.parse(value);
6121
- return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
6122
- } catch {
6123
- return void 0;
6124
- }
6125
- }
6126
- function parseKSeFTokenContext(token) {
6127
- const raw = decodeJwtPayload(token);
6128
- if (!raw) return null;
6129
- return {
6130
- type: typeof raw["typ"] === "string" ? raw["typ"] : void 0,
6131
- contextIdentifierType: typeof raw["cit"] === "string" ? raw["cit"] : void 0,
6132
- contextIdentifierValue: typeof raw["civ"] === "string" ? raw["civ"] : void 0,
6133
- authMethod: typeof raw["aum"] === "string" ? raw["aum"] : void 0,
6134
- permissions: tryParseJsonArray(raw["per"]),
6135
- subjectDetails: tryParseJson(raw["sud"]),
6136
- authorSubjectIdentifier: tryParseJson(raw["asi"]),
6137
- issuedAt: typeof raw["iat"] === "number" ? raw["iat"] : void 0,
6138
- expiresAt: typeof raw["exp"] === "number" ? raw["exp"] : void 0
6139
- };
6140
- }
6513
+ init_jwt();
6141
6514
 
6142
6515
  // src/utils/hash.ts
6143
6516
  var import_node_crypto2 = __toESM(require("crypto"), 1);
@@ -6333,6 +6706,524 @@ function nonEmptyString(value) {
6333
6706
  return typeof value === "string" && value.length > 0 ? value : void 0;
6334
6707
  }
6335
6708
 
6709
+ // src/xml/xml-engine.ts
6710
+ var import_fast_xml_parser3 = require("fast-xml-parser");
6711
+ var XML_DECLARATION = '<?xml version="1.0" encoding="UTF-8"?>\n';
6712
+ var parser = new import_fast_xml_parser3.XMLParser({
6713
+ ignoreAttributes: false,
6714
+ preserveOrder: true,
6715
+ attributeNamePrefix: "@_",
6716
+ textNodeName: "#text",
6717
+ allowBooleanAttributes: true,
6718
+ // Preserve leading zeros and keep everything as strings — KSeF fields like
6719
+ // KRS (`\d{10}`) and NIP (`\d{10}`) would otherwise be lossy through parse.
6720
+ parseTagValue: false,
6721
+ parseAttributeValue: false,
6722
+ trimValues: false
6723
+ });
6724
+ var builder = new import_fast_xml_parser3.XMLBuilder({
6725
+ ignoreAttributes: false,
6726
+ preserveOrder: true,
6727
+ attributeNamePrefix: "@_",
6728
+ textNodeName: "#text",
6729
+ format: false,
6730
+ suppressBooleanAttributes: false,
6731
+ suppressEmptyNode: false,
6732
+ processEntities: true
6733
+ });
6734
+ function createObjectBuilder(pretty = false) {
6735
+ return new import_fast_xml_parser3.XMLBuilder({
6736
+ ignoreAttributes: false,
6737
+ preserveOrder: false,
6738
+ attributeNamePrefix: "@_",
6739
+ textNodeName: "#text",
6740
+ format: pretty,
6741
+ suppressBooleanAttributes: false,
6742
+ suppressEmptyNode: false,
6743
+ processEntities: true
6744
+ });
6745
+ }
6746
+ function prependDeclaration(xml) {
6747
+ return xml.startsWith("<?xml") ? xml : `${XML_DECLARATION}${xml}`;
6748
+ }
6749
+ function parseXml(xml) {
6750
+ return parser.parse(xml);
6751
+ }
6752
+ function buildXml(document) {
6753
+ return prependDeclaration(builder.build(document));
6754
+ }
6755
+ function buildXmlFromObject(document, options) {
6756
+ return prependDeclaration(createObjectBuilder(options?.pretty).build(document));
6757
+ }
6758
+ function stripBom(input) {
6759
+ return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
6760
+ }
6761
+
6762
+ // src/xml/order-map.ts
6763
+ var ORDER_MAP = {
6764
+ Faktura: ["Naglowek", "Podmiot1", "Podmiot2", "Podmiot3", "Fa", "Stopka"],
6765
+ Naglowek: ["KodFormularza", "WariantFormularza", "DataWytworzeniaFa", "SystemInfo"],
6766
+ Podmiot1: [
6767
+ "PrefiksPodatnika",
6768
+ "NrEORI",
6769
+ "DaneIdentyfikacyjne",
6770
+ "Adres",
6771
+ "AdresKoresp",
6772
+ "DaneKontaktowe",
6773
+ "StatusInfoPodatnika"
6774
+ ],
6775
+ Podmiot2: [
6776
+ "NrEORI",
6777
+ "DaneIdentyfikacyjne",
6778
+ "Adres",
6779
+ "AdresKoresp",
6780
+ "DaneKontaktowe",
6781
+ "NrKlienta",
6782
+ "IDNabywcy",
6783
+ "JST",
6784
+ "GV"
6785
+ ],
6786
+ Podmiot3: [
6787
+ "IDNabywcy",
6788
+ "NrEORI",
6789
+ "DaneIdentyfikacyjne",
6790
+ "Adres",
6791
+ "AdresKoresp",
6792
+ "DaneKontaktowe",
6793
+ "Rola",
6794
+ "Udzial"
6795
+ ],
6796
+ DaneIdentyfikacyjne: [
6797
+ "NIP",
6798
+ "IDWew",
6799
+ "KodUE",
6800
+ "NrVatUE",
6801
+ "KodKraju",
6802
+ "NrID",
6803
+ "BrakID",
6804
+ "Nazwa",
6805
+ "Identyfikator",
6806
+ "KRS"
6807
+ ],
6808
+ Adres: ["KodKraju", "AdresL1", "AdresL2", "AdresL3"],
6809
+ DaneKontaktowe: ["Email", "Telefon"],
6810
+ Fa: [
6811
+ "KodWaluty",
6812
+ "P_1",
6813
+ "P_1M",
6814
+ "P_2",
6815
+ "WZ",
6816
+ "P_6",
6817
+ "OkresFa",
6818
+ // Multi-rate interleave per VAT group — DO NOT flatten into P_13_* block then P_14_* block.
6819
+ // See smekcio TS d1ec8fe and the "multi-rate interleave" regression test.
6820
+ "P_13_1",
6821
+ "P_14_1",
6822
+ "P_14_1W",
6823
+ "P_13_2",
6824
+ "P_14_2",
6825
+ "P_14_2W",
6826
+ "P_13_3",
6827
+ "P_14_3",
6828
+ "P_14_3W",
6829
+ "P_13_4",
6830
+ "P_14_4",
6831
+ "P_14_4W",
6832
+ "P_13_5",
6833
+ "P_14_5",
6834
+ "P_13_6_1",
6835
+ "P_13_6_2",
6836
+ "P_13_6_3",
6837
+ "P_13_7",
6838
+ "P_13_8",
6839
+ "P_13_9",
6840
+ "P_13_10",
6841
+ "P_13_11",
6842
+ "P_15",
6843
+ "KursWalutyZ",
6844
+ "Adnotacje",
6845
+ "RodzajFaktury",
6846
+ "PrzyczynaKorekty",
6847
+ "TypKorekty",
6848
+ "DaneFaKorygowanej",
6849
+ "OkresFaKorygowanej",
6850
+ "NrFaKorygowany",
6851
+ "Podmiot1K",
6852
+ "Podmiot2K",
6853
+ "Podmiot3K",
6854
+ "ZaliczkaCzesciowa",
6855
+ "FP",
6856
+ "TP",
6857
+ "DodatkowyOpis",
6858
+ "FakturaZaliczkowa",
6859
+ "ZwrotAkcyzy",
6860
+ "FaWiersz",
6861
+ "FaWiersze",
6862
+ "Rozliczenie",
6863
+ "Platnosc"
6864
+ ],
6865
+ Adnotacje: ["P_16", "P_17", "P_18", "P_18A", "Zwolnienie", "NoweSrodkiTransportu", "P_23", "PMarzy"],
6866
+ OkresFa: ["P_6_Od", "P_6_Do"],
6867
+ FaWiersz: [
6868
+ "NrWierszaFa",
6869
+ "UU_ID",
6870
+ "P_6A",
6871
+ "P_7",
6872
+ "Indeks",
6873
+ "GTIN",
6874
+ "PKWiU",
6875
+ "CN",
6876
+ "PKOB",
6877
+ "P_8A",
6878
+ "P_8B",
6879
+ "P_9A",
6880
+ "P_9B",
6881
+ "P_10",
6882
+ "P_11",
6883
+ "P_11A",
6884
+ "P_11Vat",
6885
+ "P_12",
6886
+ "P_12_XII",
6887
+ "P_12_Zal_15",
6888
+ "KwotaAkcyzy",
6889
+ "GTU",
6890
+ "Procedura",
6891
+ "KursWaluty",
6892
+ "StanPrzed"
6893
+ ]
6894
+ };
6895
+ function comparePKey(a, b) {
6896
+ const normalize = (value) => value.replace(/^P_/, "").split("_").map((part) => Number.isNaN(Number(part)) ? part : Number(part));
6897
+ const aParts = normalize(a);
6898
+ const bParts = normalize(b);
6899
+ const max = Math.max(aParts.length, bParts.length);
6900
+ for (let i = 0; i < max; i += 1) {
6901
+ const left = aParts[i];
6902
+ const right = bParts[i];
6903
+ if (left === void 0) return -1;
6904
+ if (right === void 0) return 1;
6905
+ if (typeof left === "number" && typeof right === "number") {
6906
+ if (left !== right) return left - right;
6907
+ continue;
6908
+ }
6909
+ const leftStr = String(left);
6910
+ const rightStr = String(right);
6911
+ if (leftStr !== rightStr) return leftStr < rightStr ? -1 : 1;
6912
+ }
6913
+ return 0;
6914
+ }
6915
+ function isObject(value) {
6916
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6917
+ }
6918
+ function normalizeValueForKey(key, value) {
6919
+ if (Array.isArray(value)) {
6920
+ return value.map(
6921
+ (item) => isObject(item) ? orderXmlObject(item, key) : normalizeValue(item)
6922
+ );
6923
+ }
6924
+ if (isObject(value)) return orderXmlObject(value, key);
6925
+ return value;
6926
+ }
6927
+ function normalizeValue(value) {
6928
+ if (Array.isArray(value)) return value.map((item) => normalizeValue(item));
6929
+ if (isObject(value)) return orderXmlObject(value);
6930
+ return value;
6931
+ }
6932
+ function orderXmlObject(value, contextKey) {
6933
+ const order = contextKey ? ORDER_MAP[contextKey] : void 0;
6934
+ const keys = Object.keys(value);
6935
+ const used = /* @__PURE__ */ new Set();
6936
+ const ordered = {};
6937
+ if (order) {
6938
+ for (const key of order) {
6939
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
6940
+ const item = value[key];
6941
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6942
+ used.add(key);
6943
+ }
6944
+ }
6945
+ }
6946
+ const pKeys = keys.filter((key) => !used.has(key) && key.startsWith("P_")).sort(comparePKey);
6947
+ for (const key of pKeys) {
6948
+ const item = value[key];
6949
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6950
+ used.add(key);
6951
+ }
6952
+ for (const key of keys) {
6953
+ if (used.has(key)) continue;
6954
+ const item = value[key];
6955
+ if (item !== void 0) ordered[key] = normalizeValueForKey(key, item);
6956
+ }
6957
+ return ordered;
6958
+ }
6959
+
6960
+ // src/xml/faktura-builder.ts
6961
+ var FAKTURA_NAMESPACE = {
6962
+ FA2: "http://crd.gov.pl/wzor/2023/06/29/12648/",
6963
+ FA3: "http://crd.gov.pl/wzor/2025/06/25/13775/"
6964
+ };
6965
+ var ETD_NAMESPACE = {
6966
+ FA2: "http://crd.gov.pl/xml/schematy/2020/10/08/eDokumenty",
6967
+ FA3: "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2022/01/05/eD/DefinicjeTypy/"
6968
+ };
6969
+ function toKodFormularza(formCode) {
6970
+ return {
6971
+ "@_kodSystemowy": formCode.systemCode,
6972
+ "@_wersjaSchemy": formCode.schemaVersion,
6973
+ "#text": formCode.value
6974
+ };
6975
+ }
6976
+ function isFormCodeShape(value) {
6977
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
6978
+ const candidate = value;
6979
+ return typeof candidate.systemCode === "string" && typeof candidate.schemaVersion === "string" && typeof candidate.value === "string";
6980
+ }
6981
+ function isObject2(value) {
6982
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6983
+ }
6984
+ function normalizeTopLevelChild(key, value) {
6985
+ if (key === "Naglowek" && isObject2(value)) {
6986
+ return normalizeNaglowek(value);
6987
+ }
6988
+ if (Array.isArray(value)) {
6989
+ return value.map((item) => isObject2(item) ? orderXmlObject(item, key) : item);
6990
+ }
6991
+ if (isObject2(value)) return orderXmlObject(value, key);
6992
+ return value;
6993
+ }
6994
+ function normalizeNaglowek(value) {
6995
+ const result = {};
6996
+ for (const [key, item] of Object.entries(value)) {
6997
+ if (item === void 0) continue;
6998
+ if (key === "KodFormularza" && isFormCodeShape(item)) {
6999
+ result[key] = toKodFormularza(item);
7000
+ continue;
7001
+ }
7002
+ if (Array.isArray(item)) {
7003
+ result[key] = item.map(
7004
+ (entry) => isObject2(entry) ? orderXmlObject(entry, key) : entry
7005
+ );
7006
+ continue;
7007
+ }
7008
+ if (isObject2(item)) {
7009
+ result[key] = orderXmlObject(item, key);
7010
+ continue;
7011
+ }
7012
+ result[key] = item;
7013
+ }
7014
+ return result;
7015
+ }
7016
+ function normalizeTopLevel(input) {
7017
+ const result = {};
7018
+ for (const [key, value] of Object.entries(input)) {
7019
+ if (value === void 0) continue;
7020
+ result[key] = normalizeTopLevelChild(key, value);
7021
+ }
7022
+ return result;
7023
+ }
7024
+ function buildFakturaXml(faktura, options = {}) {
7025
+ const schema = options.schema ?? "FA3";
7026
+ const fakturaNamespace = options.fakturaNamespace ?? FAKTURA_NAMESPACE[schema];
7027
+ const etdNamespace = options.etdNamespace ?? ETD_NAMESPACE[schema];
7028
+ const normalized = normalizeTopLevel(faktura);
7029
+ const ordered = orderXmlObject(normalized, "Faktura");
7030
+ const document = {
7031
+ Faktura: {
7032
+ ...ordered,
7033
+ "@_xmlns": fakturaNamespace,
7034
+ "@_xmlns:etd": etdNamespace
7035
+ }
7036
+ };
7037
+ return buildXmlFromObject(document, { pretty: options.pretty });
7038
+ }
7039
+ function isFakturaInput(input) {
7040
+ if (!isObject2(input)) return false;
7041
+ const candidate = input;
7042
+ if (!Object.prototype.hasOwnProperty.call(candidate, "Naglowek")) return false;
7043
+ if (!Object.prototype.hasOwnProperty.call(candidate, "Fa")) return false;
7044
+ return isObject2(candidate.Naglowek) && isObject2(candidate.Fa);
7045
+ }
7046
+
7047
+ // src/xml/pef-builder.ts
7048
+ init_ksef_validation_error();
7049
+ var PEF_NAMESPACE = {
7050
+ PEF: "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
7051
+ PEF_KOR: "urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
7052
+ };
7053
+ var UBL_EXT_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2";
7054
+ var UBL_CBC_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2";
7055
+ var UBL_CAC_NS = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2";
7056
+ var UBL_CBC_PL_NS = "urn:pl:extended:CommonBasicComponents-2";
7057
+ var UBL_CAC_PL_NS = "urn:pl:extended:CommonAggregateComponents-2";
7058
+ function isPefUblDocumentInput(input) {
7059
+ if (typeof input !== "object" || input === null || Array.isArray(input)) return false;
7060
+ const obj = input;
7061
+ const invoice = obj.Invoice;
7062
+ const creditNote = obj.CreditNote;
7063
+ const hasInvoice = typeof invoice === "object" && invoice !== null && !Array.isArray(invoice);
7064
+ const hasCreditNote = typeof creditNote === "object" && creditNote !== null && !Array.isArray(creditNote);
7065
+ return hasInvoice !== hasCreditNote;
7066
+ }
7067
+ function inferSchema(input) {
7068
+ return "Invoice" in input ? "PEF" : "PEF_KOR";
7069
+ }
7070
+ function isNonArrayObject(value) {
7071
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7072
+ }
7073
+ function assertPefShape(input) {
7074
+ if (!isNonArrayObject(input)) {
7075
+ throw new KSeFValidationError("PEF input must be a non-array object.");
7076
+ }
7077
+ const hasInvoiceKey = "Invoice" in input;
7078
+ const hasCreditNoteKey = "CreditNote" in input;
7079
+ if (hasInvoiceKey && hasCreditNoteKey) {
7080
+ throw new KSeFValidationError(
7081
+ "PEF input must contain exactly one of `Invoice` or `CreditNote`, not both."
7082
+ );
7083
+ }
7084
+ if (!hasInvoiceKey && !hasCreditNoteKey) {
7085
+ throw new KSeFValidationError(
7086
+ "PEF input must contain either an `Invoice` or a `CreditNote` root element."
7087
+ );
7088
+ }
7089
+ const rootKey = hasInvoiceKey ? "Invoice" : "CreditNote";
7090
+ if (!isNonArrayObject(input[rootKey])) {
7091
+ throw new KSeFValidationError(
7092
+ `PEF \`${rootKey}\` value must be a non-array object.`
7093
+ );
7094
+ }
7095
+ }
7096
+ function buildPefXml(input, options = {}) {
7097
+ assertPefShape(input);
7098
+ const inferred = inferSchema(input);
7099
+ const schema = options.schema ?? input.schema ?? inferred;
7100
+ if (schema !== inferred) {
7101
+ throw new KSeFValidationError(
7102
+ `PEF schema mismatch: expected ${inferred} based on root element, got ${schema}.`
7103
+ );
7104
+ }
7105
+ const commonNamespaces = {
7106
+ "@_xmlns:ext": UBL_EXT_NS,
7107
+ "@_xmlns:cbc": UBL_CBC_NS,
7108
+ "@_xmlns:cac": UBL_CAC_NS,
7109
+ "@_xmlns:cbc-pl": UBL_CBC_PL_NS,
7110
+ "@_xmlns:cac-pl": UBL_CAC_PL_NS
7111
+ };
7112
+ const document = "Invoice" in input ? {
7113
+ Invoice: {
7114
+ ...input.Invoice,
7115
+ "@_xmlns": PEF_NAMESPACE.PEF,
7116
+ ...commonNamespaces
7117
+ }
7118
+ } : {
7119
+ CreditNote: {
7120
+ ...input.CreditNote,
7121
+ "@_xmlns": PEF_NAMESPACE.PEF_KOR,
7122
+ ...commonNamespaces
7123
+ }
7124
+ };
7125
+ return buildXmlFromObject(document, { pretty: options.pretty });
7126
+ }
7127
+
7128
+ // src/xml/invoice-serializer.ts
7129
+ init_ksef_validation_error();
7130
+ var FAKTURA_SCHEMAS = /* @__PURE__ */ new Set(["FA2", "FA3"]);
7131
+ var PEF_SCHEMAS = /* @__PURE__ */ new Set(["PEF", "PEF_KOR"]);
7132
+ function isNonArrayObject2(value) {
7133
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7134
+ }
7135
+ function classifyUnknownObject(input) {
7136
+ const looksLikeFaktura = "Naglowek" in input || "Fa" in input || "Podmiot1" in input || "Podmiot2" in input;
7137
+ const hasInvoice = "Invoice" in input;
7138
+ const hasCreditNote = "CreditNote" in input;
7139
+ if (hasInvoice && hasCreditNote) {
7140
+ return new KSeFValidationError(
7141
+ "Input must contain exactly one of `Invoice` or `CreditNote`, not both."
7142
+ );
7143
+ }
7144
+ if (hasInvoice !== hasCreditNote) {
7145
+ const rootKey = hasInvoice ? "Invoice" : "CreditNote";
7146
+ if (!isNonArrayObject2(input[rootKey])) {
7147
+ return KSeFValidationError.fromField(
7148
+ rootKey,
7149
+ `PEF \`${rootKey}\` value must be a non-array object.`
7150
+ );
7151
+ }
7152
+ }
7153
+ if (looksLikeFaktura) {
7154
+ const missing = [];
7155
+ if (!("Naglowek" in input)) missing.push("Naglowek");
7156
+ if (!("Fa" in input)) missing.push("Fa");
7157
+ if (missing.length > 0) {
7158
+ return KSeFValidationError.fromField(
7159
+ missing[0],
7160
+ `Faktura input is missing required top-level key(s): ${missing.join(", ")}.`
7161
+ );
7162
+ }
7163
+ for (const key of ["Naglowek", "Fa"]) {
7164
+ if (!isNonArrayObject2(input[key])) {
7165
+ return KSeFValidationError.fromField(
7166
+ key,
7167
+ `Faktura \`${key}\` value must be a non-null, non-array object.`
7168
+ );
7169
+ }
7170
+ }
7171
+ return new KSeFValidationError(
7172
+ "Faktura-like input failed shape validation: `Naglowek` and `Fa` must be own enumerable properties on the input object."
7173
+ );
7174
+ }
7175
+ return new KSeFValidationError(
7176
+ "Unsupported invoice input shape: expected `FakturaInput` (with `Naglowek` + `Fa`) or `PefUblDocumentInput` (with `Invoice` or `CreditNote`)."
7177
+ );
7178
+ }
7179
+ function serializeInvoiceXml(input, options) {
7180
+ if (Buffer.isBuffer(input)) return input;
7181
+ if (typeof input === "string") {
7182
+ return Buffer.from(stripBom(input), "utf8");
7183
+ }
7184
+ if (Array.isArray(input)) {
7185
+ return Buffer.from(stripBom(buildXml(input)), "utf8");
7186
+ }
7187
+ if (input && typeof input === "object") {
7188
+ const schema = options?.schema;
7189
+ if (isPefUblDocumentInput(input)) {
7190
+ if (schema && !PEF_SCHEMAS.has(schema)) {
7191
+ throw new KSeFValidationError(
7192
+ `schema option ${schema} is not compatible with a PEF / PEF_KOR input.`
7193
+ );
7194
+ }
7195
+ const pefSchema = schema === "PEF" || schema === "PEF_KOR" ? schema : void 0;
7196
+ const xml = buildPefXml(input, {
7197
+ schema: pefSchema,
7198
+ pretty: options?.pretty
7199
+ });
7200
+ return Buffer.from(stripBom(xml), "utf8");
7201
+ }
7202
+ if (isFakturaInput(input)) {
7203
+ if (schema && !FAKTURA_SCHEMAS.has(schema)) {
7204
+ throw new KSeFValidationError(
7205
+ `schema option ${schema} is not compatible with a Faktura input.`
7206
+ );
7207
+ }
7208
+ const fakturaSchema = schema === "FA2" || schema === "FA3" ? schema : void 0;
7209
+ const xml = buildFakturaXml(input, {
7210
+ schema: fakturaSchema,
7211
+ fakturaNamespace: options?.fakturaNamespace,
7212
+ etdNamespace: options?.etdNamespace,
7213
+ pretty: options?.pretty
7214
+ });
7215
+ return Buffer.from(stripBom(xml), "utf8");
7216
+ }
7217
+ throw classifyUnknownObject(input);
7218
+ }
7219
+ throw new KSeFValidationError(
7220
+ "Unsupported invoice input type: expected Buffer, string, XmlDocument, FakturaInput, or PefUblDocumentInput."
7221
+ );
7222
+ }
7223
+ function buildRawXmlString(document, options) {
7224
+ return buildXmlFromObject(document, options);
7225
+ }
7226
+
6336
7227
  // src/workflows/online-session-workflow.ts
6337
7228
  init_invoice_validator();
6338
7229
  init_ksef_validation_error();
@@ -7062,10 +7953,13 @@ init_client();
7062
7953
  CertificateService,
7063
7954
  CryptographyService,
7064
7955
  DEFAULT_FORM_CODE,
7956
+ DISCOURAGED_UNICODE_RANGES,
7065
7957
  DefaultAuthManager,
7066
7958
  ENFORCE_XADES_COMPLIANCE,
7959
+ ETD_NAMESPACE,
7067
7960
  EntityPermissionGrantBuilder,
7068
7961
  Environment,
7962
+ FAKTURA_NAMESPACE,
7069
7963
  FORM_CODES,
7070
7964
  FORM_CODE_KEYS,
7071
7965
  FileHwmStore,
@@ -7082,6 +7976,7 @@ init_client();
7082
7976
  KSEF_FEATURE_HEADER,
7083
7977
  KSeFApiError,
7084
7978
  KSeFAuthStatusError,
7979
+ KSeFBadRequestError,
7085
7980
  KSeFBatchTimeoutError,
7086
7981
  KSeFClient,
7087
7982
  KSeFError,
@@ -7099,8 +7994,10 @@ init_client();
7099
7994
  LimitsService,
7100
7995
  Nip,
7101
7996
  NipVatUe,
7997
+ ORDER_MAP,
7102
7998
  OfflineInvoiceWorkflow,
7103
7999
  OnlineSessionService,
8000
+ PEF_NAMESPACE,
7104
8001
  PERMISSION_DESCRIPTION_MAX_LENGTH,
7105
8002
  PERMISSION_DESCRIPTION_MIN_LENGTH,
7106
8003
  PeppolId,
@@ -7130,14 +8027,21 @@ init_client();
7130
8027
  VatUe,
7131
8028
  VerificationLinkService,
7132
8029
  addBusinessDays,
8030
+ assertNever,
7133
8031
  authenticateWithCertificate,
7134
8032
  authenticateWithExternalSignature,
7135
8033
  authenticateWithPkcs12,
7136
8034
  authenticateWithToken,
7137
8035
  batchValidationDetails,
8036
+ buildFakturaXml,
8037
+ buildPefXml,
8038
+ buildRawXmlString,
7138
8039
  buildUnsignedAuthTokenRequestXml,
8040
+ buildXml,
8041
+ buildXmlFromObject,
7139
8042
  calculateBackoff,
7140
8043
  calculateOfflineDeadline,
8044
+ comparePKey,
7141
8045
  createZip,
7142
8046
  decodeJwtPayload,
7143
8047
  deduplicateByKsefNumber,
@@ -7156,6 +8060,9 @@ init_client();
7156
8060
  getTimeUntilDeadline,
7157
8061
  incrementalExportAndDownload,
7158
8062
  isExpired,
8063
+ isFakturaInput,
8064
+ isFormCodeShape,
8065
+ isPefUblDocumentInput,
7159
8066
  isPolishHoliday,
7160
8067
  isRetryableError,
7161
8068
  isRetryableStatus,
@@ -7177,16 +8084,21 @@ init_client();
7177
8084
  nextBusinessDay,
7178
8085
  openOnlineSession,
7179
8086
  openSendAndClose,
8087
+ orderXmlObject,
7180
8088
  parseFormCode,
7181
8089
  parseKSeFTokenContext,
7182
8090
  parseRetryAfter,
7183
8091
  parseUpoXml,
8092
+ parseXml,
7184
8093
  pollUntil,
7185
8094
  resolveOptions,
7186
8095
  resumeOnlineSession,
7187
8096
  runWithConcurrency,
8097
+ serializeInvoiceXml,
7188
8098
  sha256Base64,
7189
8099
  sleep,
8100
+ stripBom,
8101
+ toKodFormularza,
7190
8102
  unzip,
7191
8103
  updateContinuationPoint,
7192
8104
  uploadBatch,
@@ -7196,6 +8108,7 @@ init_client();
7196
8108
  validate,
7197
8109
  validateBatch,
7198
8110
  validateBusinessRules,
8111
+ validateCharValidity,
7199
8112
  validateFormCodeForSession,
7200
8113
  validatePresignedUrl,
7201
8114
  validateSchema,